Skip to content

ci: add safe stale run janitor - #13143

Merged
teamleaderleo merged 5 commits into
mainfrom
feat/ci-stale-run-janitor
Sep 20, 2026
Merged

teamleaderleo merged 5 commits into
mainfrom
feat/ci-stale-run-janitor

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 20, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Queued and in-progress Actions runs can remain after their pull request is merged or closed. They consume queue capacity and make the live backlog hard to distinguish from useful work.

Change

  • Add a scheduled, report-only janitor that inspects queued and in-progress runs every 30 minutes.
  • Resolve each run's commit to its associated pull requests through the GitHub API.
  • Consider only runs older than 24 hours whose PRs are all closed or merged.
  • Preserve runs with no PR, an open PR, or a reused branch with an open PR.
  • Add an explicit workflow_dispatch cleanup mode, capped at 25 actions. Queued runs are deleted; in-progress runs are cancelled.
  • Run the control plane on the fixed GitHub-hosted runner with narrowly scoped actions: write permission.

Scheduled runs are always dry runs, so rollout starts with an auditable inventory. Manual cleanup is opt-in and bounded.

Validation

  • python3 -m unittest -v tests/test_cleanup_stale_runs.py
  • python3 -m py_compile scripts/ci/cleanup-stale-runs.py
  • ./tests/test_ci_self_hosted_guard.sh
  • git diff --check

Related: #13117, #13128


Summary by cubic

Adds a scheduled janitor that reports queued and in-progress Actions runs stranded by closed or merged pull requests, so stale runs stop hiding useful work in the backlog (addresses #13117, #13128). Scheduled runs are always dry runs, so rollout starts with an auditable inventory.

  • Runs every 30 minutes; manual workflow_dispatch with cleanup=true deletes queued runs and cancels in-progress ones, capped at 25 actions.
  • Only pull_request runs older than 24 hours whose pull requests are all closed or merged are eligible; runs with no PR, any open PR, or non-PR events are preserved.
  • Cleanup rechecks each run and its PRs right before acting, so completed runs and reopened PRs are skipped.
  • Runs on the fixed GitHub-hosted runner with actions: write scoped to this workflow only.
  • Manual cleanup rejects non-positive age/action limits and any max_actions above 25.

Written for commit 880fc84. Summary will update on new commits.

Review in cubic

@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 14 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 11a8341d-5da6-4bf8-9936-8183d23310ba

📥 Commits

Reviewing files that changed from the base of the PR and between 1f887f1 and 880fc84.

📒 Files selected for processing (5)
  • .github/workflows/ci-stale-run-janitor.yml
  • .github/workflows/ci.yml
  • docs/ci-stale-run-janitor.md
  • scripts/ci/cleanup-stale-runs.py
  • tests/test_cleanup_stale_runs.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@greptile-apps

greptile-apps Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the previous defects are fixed and no new actionable failure remains.

Summary

Adds a scheduled GitHub Actions janitor for identifying stale PR workflow runs, with explicitly bounded manual cleanup.

  • Scheduled executions remain report-only.
  • Manual cleanup is limited to 25 actions and revalidates run and PR state before deletion or cancellation.
  • Eligibility fails closed for missing PR data, unknown PR state, non-PR events, recent runs, and completed runs.
  • Adds CI coverage and operational documentation for classification and cleanup behavior.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Trigger{Invocation} -->|Schedule| DryRun[Report only]
    Trigger -->|Manual cleanup=true| Inventory[Fetch queued and in-progress runs]
    DryRun --> Inventory
    Inventory --> Classify{Pull-request event, older than threshold, and all PRs closed?}
    Classify -->|No| Preserve[Preserve run]
    Classify -->|Yes, report mode| Report[Report eligible run]
    Classify -->|Yes, cleanup mode| Refresh[Refresh run and PR state]
    Refresh --> Recheck{Still eligible?}
    Recheck -->|No| Preserve
    Recheck -->|Queued| Delete[Delete run]
    Recheck -->|In progress| Cancel[Cancel run]
    Delete --> Cap[Stop after configured limit, never above 25]
    Cancel --> Cap
Loading

Reviews (4) · Last reviewed commit: "fix: restrict stale cleanup to current c..."

Comment thread scripts/ci/cleanup-stale-runs.py
Comment thread tests/test_cleanup_stale_runs.py Outdated
Comment thread scripts/ci/cleanup-stale-runs.py Outdated
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Fixed a cleanup eligibility gap in 880fc84. Commit-to-PR association alone also matches main pushes and scheduled runs after a merge. Cleanup now accepts only ordinary pull_request events in queued/in_progress state, preserves missing/unknown PR state, and refreshes run/PR facts immediately before each action so completed runs and reopened PRs are skipped. Scheduled operation remains report-only.

Regression commit: 345619f. The original classifier failed seven regression subcases locally; the fixed version passes all nine tests, including mocked cleanup requests and preservation on changed state. The suite is now wired into the existing CI workflow. git diff --check passes. Fresh hosted checks are pending; no cleanup workflow was dispatched.

@teamleaderleo
teamleaderleo enabled auto-merge (squash) September 20, 2026 17:49
@teamleaderleo
teamleaderleo merged commit 95fdfd7 into main Sep 20, 2026
38 of 39 checks passed
rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 20, 2026
e77a6b1 feat: add current-work reads and Find Work (manaflow-ai#13269)
6386ba5 Cache Ghostty CLI helper builds across local invocations (manaflow-ai#13206)
8f6c0ea ci: measure compiled test artifact transfer cost (manaflow-ai#13172)
55092b9 docs: add a concise guide for public CMUX writing (manaflow-ai#13257)
9e7d3be fix(web): preserve locale preference during prefetch (manaflow-ai#13255)
b093335 build: skip unchanged diff sidecar builds (manaflow-ai#13212)
b79d77d perf: skip unchanged bundled resource builds (manaflow-ai#13209)
4c19fcb feat: expose stable surface and workspace IDs in catalog reads (manaflow-ai#13247)
95fdfd7 ci: add safe stale run janitor (manaflow-ai#13143)
0bcf003 docs: make the contributor verification ladder explicit (manaflow-ai#13242)
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.

1 participant