This commit is contained in:
jarek committed 2026-01-28 07:34:12 +01:00
1 parent a88d3d5788
commit 8f3a7eb435
96 files changed
+5235 -1870

No files matched your search

+41 -1
View File
@@ -12,6 +12,7 @@ import {
getAllAutoUpdateSettings,
getAllAutoUpdateGitStacks,
getAllEnvUpdateCheckSettings,
getAllImagePruneSettings,
getLastExecutionForSchedule,
getRecentExecutionsForSchedule,
getEnvironment,
@@ -24,7 +25,7 @@ import { getGlobalScannerDefaults, getScannerSettingsWithDefaults } from '$lib/s
export interface ScheduleInfo {
id: number;
type: 'container_update' | 'git_stack_sync' | 'system_cleanup' | 'env_update_check';
type: 'container_update' | 'git_stack_sync' | 'system_cleanup' | 'env_update_check' | 'image_prune';
name: string;
entityName: string;
description?: string;
@@ -164,6 +165,45 @@ export const GET: RequestHandler = async () => {
);
schedules.push(...envUpdateCheckSchedules);
// Get image prune schedules
const imagePruneConfigs = await getAllImagePruneSettings();
const imagePruneSchedules = await Promise.all(
imagePruneConfigs.map(async ({ envId, settings }) => {
const [env, lastExecution, recentExecutions, timezone] = await Promise.all([
getEnvironment(envId),
getLastExecutionForSchedule('image_prune', envId),
getRecentExecutionsForSchedule('image_prune', envId, 5),
getEnvironmentTimezone(envId)
]);
const isEnabled = settings.enabled ?? false;
const nextRun = isEnabled && settings.cronExpression ? getNextRun(settings.cronExpression, timezone) : null;
// Build description based on prune mode
const description = settings.pruneMode === 'all'
? 'Prune all unused images'
: 'Prune dangling images only';
return {
id: envId,
type: 'image_prune' as const,
name: `Prune images: ${env?.name || 'Unknown'}`,
entityName: env?.name || 'Unknown',
description,
environmentId: envId,
environmentName: env?.name ?? null,
enabled: isEnabled,
scheduleType: 'custom',
cronExpression: settings.cronExpression ?? null,
nextRun: nextRun?.toISOString() ?? null,
lastExecution: lastExecution ?? null,
recentExecutions,
isSystem: false,
pruneMode: settings.pruneMode
};
})
);
schedules.push(...imagePruneSchedules);
// Get system schedules
const systemSchedules = await getSystemSchedules();
const sysSchedules = await Promise.all(
@@ -9,7 +9,8 @@ import {
getAutoUpdateSettingById,
deleteAutoUpdateSchedule,
updateGitStack,
deleteEnvUpdateCheckSettings
deleteEnvUpdateCheckSettings,
deleteImagePruneSettings
} from '$lib/server/db';
import { unregisterSchedule } from '$lib/server/scheduler';
@@ -49,6 +50,12 @@ export const DELETE: RequestHandler = async ({ params }) => {
unregisterSchedule(scheduleId, 'env_update_check');
return json({ success: true });
} else if (type === 'image_prune') {
// Delete image prune settings (scheduleId is environmentId)
await deleteImagePruneSettings(scheduleId);
unregisterSchedule(scheduleId, 'image_prune');
return json({ success: true });
} else if (type === 'system_cleanup') {
return json({ error: 'System schedules cannot be removed' }, { status: 400 });
@@ -4,13 +4,13 @@
* POST /api/schedules/[type]/[id]/run - Trigger a manual execution
*
* Path params:
* - type: 'container_update' | 'git_stack_sync' | 'system_cleanup'
* - type: 'container_update' | 'git_stack_sync' | 'system_cleanup' | 'env_update_check' | 'image_prune'
* - id: schedule ID
*/
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { triggerContainerUpdate, triggerGitStackSync, triggerSystemJob, triggerEnvUpdateCheck } from '$lib/server/scheduler';
import { triggerContainerUpdate, triggerGitStackSync, triggerSystemJob, triggerEnvUpdateCheck, triggerImagePrune } from '$lib/server/scheduler';
export const POST: RequestHandler = async ({ params }) => {
try {
@@ -36,6 +36,9 @@ export const POST: RequestHandler = async ({ params }) => {
case 'env_update_check':
result = await triggerEnvUpdateCheck(scheduleId);
break;
case 'image_prune':
result = await triggerImagePrune(scheduleId);
break;
default:
return json({ error: 'Invalid schedule type' }, { status: 400 });
}
@@ -5,7 +5,7 @@
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { getAutoUpdateSettingById, updateAutoUpdateSettingById, getGitStack, updateGitStack, getEnvUpdateCheckSettings, setEnvUpdateCheckSettings } from '$lib/server/db';
import { getAutoUpdateSettingById, updateAutoUpdateSettingById, getGitStack, updateGitStack, getEnvUpdateCheckSettings, setEnvUpdateCheckSettings, getImagePruneSettings, setImagePruneSettings } from '$lib/server/db';
import { registerSchedule, unregisterSchedule } from '$lib/server/scheduler';
export const POST: RequestHandler = async ({ params }) => {
@@ -75,6 +75,27 @@ export const POST: RequestHandler = async ({ params }) => {
unregisterSchedule(scheduleId, 'env_update_check');
}
return json({ success: true, enabled: newEnabled });
} else if (type === 'image_prune') {
// scheduleId is environmentId for image prune
const config = await getImagePruneSettings(scheduleId);
if (!config) {
return json({ error: 'Schedule not found' }, { status: 404 });
}
const newEnabled = !config.enabled;
await setImagePruneSettings(scheduleId, {
...config,
enabled: newEnabled
});
// Register or unregister schedule with croner
if (newEnabled && config.cronExpression) {
await registerSchedule(scheduleId, 'image_prune', scheduleId);
} else {
unregisterSchedule(scheduleId, 'image_prune');
}
return json({ success: true, enabled: newEnabled });
} else if (type === 'system_cleanup') {
return json({ error: 'System schedules cannot be paused' }, { status: 400 });
@@ -9,6 +9,7 @@ import {
getAllAutoUpdateSettings,
getAllAutoUpdateGitStacks,
getAllEnvUpdateCheckSettings,
getAllImagePruneSettings,
getLastExecutionForSchedule,
getRecentExecutionsForSchedule,
getEnvironment,
@@ -140,6 +141,45 @@ async function getSchedulesData(): Promise<ScheduleInfo[]> {
);
schedules.push(...envUpdateCheckSchedules);
// Get image prune schedules
const imagePruneConfigs = await getAllImagePruneSettings();
const imagePruneSchedules = await Promise.all(
imagePruneConfigs.map(async ({ envId, settings }) => {
const [env, lastExecution, recentExecutions, timezone] = await Promise.all([
getEnvironment(envId),
getLastExecutionForSchedule('image_prune', envId),
getRecentExecutionsForSchedule('image_prune', envId, 5),
getEnvironmentTimezone(envId)
]);
const isEnabled = settings.enabled ?? false;
const nextRun = isEnabled && settings.cronExpression ? getNextRun(settings.cronExpression, timezone) : null;
// Build description based on prune mode
const description = settings.pruneMode === 'all'
? 'Prune all unused images'
: 'Prune dangling images only';
return {
id: envId,
type: 'image_prune' as const,
name: `Prune images: ${env?.name || 'Unknown'}`,
entityName: env?.name || 'Unknown',
description,
environmentId: envId,
environmentName: env?.name ?? null,
enabled: isEnabled,
scheduleType: 'custom',
cronExpression: settings.cronExpression ?? null,
nextRun: nextRun?.toISOString() ?? null,
lastExecution: lastExecution ?? null,
recentExecutions,
isSystem: false,
pruneMode: settings.pruneMode
};
})
);
schedules.push(...imagePruneSchedules);
// Get system schedules
const systemSchedules = await getSystemSchedules();
const sysSchedules = await Promise.all(