From f9aa2f6f5f1a3ed91bc582d477a4d31f732f5566 Mon Sep 17 00:00:00 2001 From: Lucas Bedatty Date: Mon, 27 Apr 2026 09:54:02 -0300 Subject: [PATCH 1/3] refactor(self-routine): collapse to a single weekly cron firing all jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously each routine had its own cron (Mon 03:00 for branch cleanup, daily 04:00 for stale PRs, Wed 04:30 for stale issues, Sun 05:00 for labels sync, monthly 1st 06:00 for workflow runs cleanup). That produced fragmented "stale-pr ran at 04:00, then branch cleanup at 03:00 next Monday, then..." noise across the Actions tab. Switch to a single cron — `0 3 * * 1` (Mon 03:00 UTC) — that fires the whole workflow once a week. Every job's schedule gate is now just `github.event_name == 'schedule'`, so all routines run together in the same run. Why this is fine: - actions/stale and the cleanup composites are idempotent — items that don't meet the threshold are listed and skipped, no side effect. - A weekly cadence for stale-pr (instead of daily) is acceptable for this volume; if a faster PR cycle is needed later, add a second cron with a job-level `if` gating only `stale_pr`. - Per-routine triggers other than schedule are unchanged: `branch_cleanup_merged` still fires on every merged PR, `labels_sync` still fires on `push` to main when `.github/labels.yml` changes, and every job remains dispatchable individually via `workflow_dispatch`. --- .github/workflows/self-routine.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/self-routine.yml b/.github/workflows/self-routine.yml index 284713ac..6e6936b8 100644 --- a/.github/workflows/self-routine.yml +++ b/.github/workflows/self-routine.yml @@ -2,11 +2,12 @@ name: Self — Repository Routines on: schedule: - - cron: "0 3 * * 1" # weekly Mon 03:00 UTC — branch cleanup (stale scan) - - cron: "0 4 * * *" # daily 04:00 UTC — stale PRs - - cron: "30 4 * * 3" # weekly Wed 04:30 UTC — stale issues - - cron: "0 5 * * 0" # weekly Sun 05:00 UTC — labels sync (reconciliation) - - cron: "0 6 1 * *" # monthly 1st 06:00 UTC — workflow runs cleanup + # Single weekly cron — every Monday at 03:00 UTC fires every routine in + # the same workflow run. Stale/cleanup actions are idempotent: any item + # that doesn't meet the threshold is logged and skipped, so running them + # together once a week is the simplest mental model with no real cost + # over staggered cadences. + - cron: "0 3 * * 1" pull_request: types: [closed] push: @@ -52,7 +53,7 @@ jobs: branch_cleanup_stale: name: Clean stale branches if: | - (github.event_name == 'schedule' && github.event.schedule == '0 3 * * 1') + github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'branch-cleanup-stale')) uses: ./.github/workflows/branch-cleanup.yml with: @@ -65,7 +66,7 @@ jobs: stale_pr: name: Close stale PRs if: | - (github.event_name == 'schedule' && github.event.schedule == '0 4 * * *') + github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'stale-pr')) uses: ./.github/workflows/stale-pr.yml with: @@ -77,7 +78,7 @@ jobs: stale_issue: name: Close stale issues if: | - (github.event_name == 'schedule' && github.event.schedule == '30 4 * * 3') + github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'stale-issue')) uses: ./.github/workflows/stale-issue.yml with: @@ -92,7 +93,7 @@ jobs: name: Sync labels if: | github.event_name == 'push' - || (github.event_name == 'schedule' && github.event.schedule == '0 5 * * 0') + || github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'labels-sync')) uses: ./.github/workflows/labels-sync.yml with: @@ -104,7 +105,7 @@ jobs: workflow_runs_cleanup: name: Delete old workflow runs if: | - (github.event_name == 'schedule' && github.event.schedule == '0 6 1 * *') + github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'workflow-runs-cleanup')) uses: ./.github/workflows/workflow-runs-cleanup.yml with: From d945c15afde1df5c9179f866b1d02ad543c3d070 Mon Sep 17 00:00:00 2001 From: Lucas Bedatty Date: Mon, 27 Apr 2026 11:08:40 -0300 Subject: [PATCH 2/3] fix(self-routine): bump stale ops budget for weekly cadence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the cron was daily, `operations_per_run: 60` (reusable default) refreshed every 24h — effectively ~420 ops/week. Collapsing to a single weekly cron meant the same 60-op cap applied to a full week of backlog, so any repo with >60 candidates would have items drift past the stale and close windows. Override the input on schedule events to 420 in both `stale_pr` and `stale_issue` jobs of `self-routine.yml`. The expression is conditional so manual `workflow_dispatch` runs keep the leaner 60-op default, which is appropriate for an interactive sanity-check. Reusable defaults are unchanged — external consumers that drive `stale-pr.yml` / `stale-issue.yml` directly are free to keep daily schedules with 60 ops/run. --- .github/workflows/self-routine.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/self-routine.yml b/.github/workflows/self-routine.yml index 6e6936b8..e421912e 100644 --- a/.github/workflows/self-routine.yml +++ b/.github/workflows/self-routine.yml @@ -70,6 +70,11 @@ jobs: || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'stale-pr')) uses: ./.github/workflows/stale-pr.yml with: + # Schedule is weekly here, so we raise the per-run budget from the + # reusable's daily-sized default (60) to roughly a week's worth (420) + # — keeps stale/close throughput equivalent to the pre-unified-cron + # cadence even if the open-PR backlog grows past 60 items. + operations_per_run: ${{ github.event_name == 'schedule' && 420 || 60 }} dry_run: ${{ inputs.dry_run || false }} secrets: inherit @@ -82,6 +87,10 @@ jobs: || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'stale-issue')) uses: ./.github/workflows/stale-issue.yml with: + # Same rationale as stale_pr — bump the weekly-scheduled budget to + # match the pre-refactor daily refresh, so issue throughput isn't + # gated by the 60-op default when running once a week. + operations_per_run: ${{ github.event_name == 'schedule' && 420 || 60 }} dry_run: ${{ inputs.dry_run || false }} secrets: inherit From d24c9c72a7e3288a5696fbe0d3dda72a8a2e3c24 Mon Sep 17 00:00:00 2001 From: Lucas Bedatty Date: Mon, 27 Apr 2026 11:19:56 -0300 Subject: [PATCH 3/3] fix(self-routine): keep stale_issue at the reusable default; drop YAML rationale comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per CodeRabbit's correctness note on PR #282 and the no-yaml-comments project rule, two changes: - `stale_issue` no longer overrides `operations_per_run`. Stale issues were already scheduled weekly before the unified-cron refactor (the prior cron was `30 4 * * 3`), so the 60-op default already maps to weekly throughput. Bumping it to 420 would have expanded the scheduled mutation budget 7x without justification — stale_pr was the only side that needed the bump (it was daily before). - The inline rationale comments on the `operations_per_run` lines are removed in line with the project's no-`# why` policy for workflow YAML — the rationale belongs in the commit message, not in the file. --- .github/workflows/self-routine.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/self-routine.yml b/.github/workflows/self-routine.yml index e421912e..26389dc1 100644 --- a/.github/workflows/self-routine.yml +++ b/.github/workflows/self-routine.yml @@ -70,10 +70,6 @@ jobs: || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'stale-pr')) uses: ./.github/workflows/stale-pr.yml with: - # Schedule is weekly here, so we raise the per-run budget from the - # reusable's daily-sized default (60) to roughly a week's worth (420) - # — keeps stale/close throughput equivalent to the pre-unified-cron - # cadence even if the open-PR backlog grows past 60 items. operations_per_run: ${{ github.event_name == 'schedule' && 420 || 60 }} dry_run: ${{ inputs.dry_run || false }} secrets: inherit @@ -87,10 +83,6 @@ jobs: || (github.event_name == 'workflow_dispatch' && (inputs.routine == 'all' || inputs.routine == 'stale-issue')) uses: ./.github/workflows/stale-issue.yml with: - # Same rationale as stale_pr — bump the weekly-scheduled budget to - # match the pre-refactor daily refresh, so issue throughput isn't - # gated by the 60-op default when running once a week. - operations_per_run: ${{ github.event_name == 'schedule' && 420 || 60 }} dry_run: ${{ inputs.dry_run || false }} secrets: inherit