Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@cabaucom376
Copy link
Contributor

@cabaucom376 cabaucom376 commented Oct 30, 2025

Replace the interval-based auto-update system entirely with a cron-based scheduler that supports:

  • Global cron schedules
  • Project-level cron overrides
  • Service-level boolean opt-in/out via com.ofkm.arcane.updater label
  • Human-readable cron descriptions in the UI with i18n support
  • Backend validation of cron expressions

closes #491

Disclaimer Greptiles Reviews uses AI, make sure to check over its work

Greptile Overview

Updated On: 2025-11-03 13:27:39 UTC

Greptile Summary

This PR successfully replaces the interval-based auto-update system with a comprehensive cron-based scheduler that addresses issue #491.

Key Changes

  • Global cron schedules: New autoUpdateCron setting replaces the old interval-based system, supporting standard 5-field cron expressions validated by the robfig/cron library
  • Project-level overrides: Projects can now set their own auto_update (nullable boolean) and auto_update_cron (nullable string) to override global settings, providing fine-grained control
  • Service-level opt-in/out: The com.ofkm.arcane.updater label is automatically injected into containers based on project settings, allowing per-service control
  • Immediate mode: Empty/null cron expressions trigger immediate updates (checks every 5 minutes when updates are detected)
  • UI improvements: New collapsible cron schedule component with intuitive presets (immediate, daily, weekdays, weekends, every N hours) and custom input with i18n support
  • Backend validation: Cron expressions are validated server-side using the robfig/cron parser before being saved, preventing invalid expressions

Implementation Quality

The implementation is well-structured with proper separation of concerns:

  • Validation is centralized in a reusable utility (cron_util.go)
  • The three-level hierarchy (global → project → service) is cleanly implemented
  • Database migrations properly handle the schema changes with nullable columns
  • The UI provides an excellent user experience with presets and custom input
  • Backward compatibility is maintained through migrations

Confidence Score: 5/5

  • This PR is safe to merge - the implementation is solid with proper validation, migrations, and comprehensive testing coverage
  • Score reflects excellent implementation quality with proper validation using a well-established library (robfig/cron), comprehensive migrations, clean architecture with three-level hierarchy (global/project/service), and good UI/UX. The previous comment about step value validation is incorrect - the robfig/cron library properly validates all cron expressions including step values. The feature is well-tested and maintains backward compatibility.
  • No files require special attention - all changes are well-implemented

Important Files Changed

File Analysis

Filename Score Overview
backend/internal/utils/cron/cron_util.go 5/5 New cron validation utility using robfig/cron library parser - properly validates all cron expressions including step values
backend/internal/job/auto_update_job.go 5/5 Replaced interval-based scheduling with cron-based scheduling, supports immediate mode (empty cron) and scheduled mode with proper job registration
backend/internal/services/settings_service.go 5/5 Added cron validation for autoUpdateCron setting at line 320-323, triggers reschedule callback on change
backend/internal/services/project_service.go 5/5 Added cron validation for project-level autoUpdateCron at line 791-794, passes project settings to LoadComposeProject
backend/internal/utils/projects/load.go 5/5 Added UpdaterLabel constant and label injection logic at lines 110-114 to set com.ofkm.arcane.updater based on project AutoUpdate setting
frontend/src/lib/components/cron-schedule-select.svelte 5/5 New reusable cron schedule component with presets (immediate, daily, weekdays, weekends, every N hours) and custom input support
frontend/src/routes/projects/components/ProjectSettingsPanel.svelte 5/5 New project settings panel with global/project toggle for auto-update, integrates cron schedule selector with proper state management

@cabaucom376 cabaucom376 marked this pull request as ready for review October 30, 2025 23:10
@cabaucom376 cabaucom376 requested a review from a team as a code owner October 30, 2025 23:10
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

33 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@cabaucom376 cabaucom376 requested a review from kmendell October 30, 2025 23:26
Copy link
Member

@kmendell kmendell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving for a trip in a few days, but few things I noticed so far.

  1. The cron logic in the front and backend is not maintainable , there are libraries out there that can parse cron gocron it self may be able to as well.

Some of the friend logic like normalizing empty inputs can most like be solved by the backed by adding omitempty to. The JSON tags.

I'll try to take a look tomorrow if I have time, but it may be little bit before I can fully review everything.

@cabaucom376
Copy link
Contributor Author

I tried scouring for a good parsing package but everything seems un-maintained or unused so didn't feel confident choosing anything.

@kmendell
Copy link
Member

@cabaucom376 I made some changes, i use libraries to parse the cron stuff, and teh frontend just had its use a zod schema instead. I also updated the styling to use the existsing styling ofr teh select component vs making a new component for this i though it looked clunky.

Ill try to look more later.

@cabaucom376
Copy link
Contributor Author

Cool, just checked it out. Only thing I'm noticing is that you cannot select immediate and null out the cron expression.

@cabaucom376
Copy link
Contributor Author

I also did really enjoy the human readable part of it, but if you think its too much thats okay.

@kmendell
Copy link
Member

The Human Readable part? its still there just not for custom, If we do a human readbale format we get rid of the presets and somehow make universal logic to detect it which is just hard cause id rather not have that done on the fly it could make thinsg feel slow or clunky.

global cron expression can not be null. It has nothing to inherit from.
$effect(() => {
if (cronScheduleMode !== 'custom') {
$formInputs.autoUpdateCron.value = cronScheduleMode;
$formInputs.autoUpdateCron.value = cronScheduleMode === null ? '' : cronScheduleMode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think this check is needed, 1. im pretty sure it gets set to null anyways and before i chnaged it to hide the text box, it did get set to null. 2. The logic is just messy and not how any of the rest of the data is sent, theres a much easier way to handle this, i just dont have the time to do it right now.

@cabaucom376 cabaucom376 closed this Nov 3, 2025
@cabaucom376 cabaucom376 deleted the cron-updating branch November 3, 2025 13:23
@cabaucom376 cabaucom376 restored the cron-updating branch November 3, 2025 13:24
@cabaucom376 cabaucom376 reopened this Nov 3, 2025
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

35 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@kmendell kmendell requested a review from a team as a code owner November 6, 2025 17:06
c.JSON(http.StatusInternalServerError, gin.H{
c.JSON(http.StatusBadRequest, gin.H{
"success": false,
"data": dto.MessageDto{Message: "Failed to update settings"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be the data field as the frontend services apiserver this.handleReponse will grab from the data field

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding some e2e test for setting the settings of a project will be useful, that way if functionaltiy breaks we will know.

.updateSettings(data)
.then(() => toast.success(m.navigation_settings_saved()))
.catch((error) => {
.catch((error: any) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment about the data field above, for all of this : any types. This should not be needed since it was all working with the "data" field.

composeContent,
envContent
};
const payload: any = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is overkill, we should aollow the same pattern as before, the backend should just send empty values if its not set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

⚡️ Feature: Add option to schedule auto updates

3 participants