chore(ci): a manually-run workflow to delete old Actions runs (#324) #325

Merged
bermudalamb merged 1 commits from chore/324-cleanup-actions-workflow into main 2026-09-09 10:48:29 -05:00
Owner

Gitea 1.27.3 expires a run's logs and artifacts but never the run record itself, so the Actions list grows without limit and fills with entries whose logs are already gone. Clearing it took 455 API calls from a scratch file on one machine — the wrong home for something that recurs every few weeks.

Safety choices

  • Dry run unless apply is typed as true. The operation cannot be undone and there is no confirmation once it starts, so the harmless answer has to be what you get by leaving a box alone.
  • Manual only, deliberately not scheduled. The list is an annoyance rather than a problem, and a cron that quietly deletes history should be a decision taken on its own rather than one bundled in with the tool.
  • A run that is not completed is never a candidate — which is also what stops the cleanup deleting the run it is executing in.

The bug worth committing this for

The script ages a run by started_at, falling back to completed_at.

That fallback is the whole reason this belongs in the repo rather than being retyped from memory. A run cancelled before it ever started reports an epoch started_at while carrying a perfectly real completed_at. Reading only the first makes every cancelled run look undateable.

The manual pass did exactly that, and left 19 runs from three weeks earlier sitting in a list that was supposed to hold seven days — which is how the gap was found. Anyone rewriting this from scratch would hit the same thing.

When neither timestamp is usable the run is still kept: an epoch date read as "1969, therefore old" would delete precisely the runs that have not happened yet.

Token

Uses a dedicated ACTIONS_CLEANUP_TOKEN repository secret rather than the automatic per-job token, since deleting a run may be beyond what that token permits. You'll need to add that secret before the first run. If the built-in token turns out to be sufficient, both the secret and the env line can go — worth checking on the first dispatch, since a token with delete rights in repository secrets is not nothing on an instance that also hosts the deploy.

Host and repository come from the run's own context, so this file carries no hostname and survives the move #313 may yet make.

No npm install step: the script uses node's own https module, so there is nothing to fetch and nothing to break when a dependency moves.

Verification

Run against the live instance, not just reasoned about:

  • Dry run reported the 19 stale cancelled runs the earlier pass had missed.
  • Applying it removed them — 19 deleted, 0 failed.
  • The list went 632 → 158 across both passes.

node --check clean. Nothing else in the repo imports it.

Closes #324

🤖 Generated with Claude Code

Gitea 1.27.3 expires a run's logs and artifacts but **never the run record itself**, so the Actions list grows without limit and fills with entries whose logs are already gone. Clearing it took 455 API calls from a scratch file on one machine — the wrong home for something that recurs every few weeks. ## Safety choices - **Dry run unless `apply` is typed as `true`.** The operation cannot be undone and there is no confirmation once it starts, so the harmless answer has to be what you get by leaving a box alone. - **Manual only, deliberately not scheduled.** The list is an annoyance rather than a problem, and a cron that quietly deletes history should be a decision taken on its own rather than one bundled in with the tool. - **A run that is not completed is never a candidate** — which is also what stops the cleanup deleting the run it is executing in. ## The bug worth committing this for The script ages a run by `started_at`, **falling back to `completed_at`**. That fallback is the whole reason this belongs in the repo rather than being retyped from memory. A run **cancelled before it ever started** reports an epoch `started_at` while carrying a perfectly real `completed_at`. Reading only the first makes every cancelled run look undateable. The manual pass did exactly that, and left **19 runs from three weeks earlier** sitting in a list that was supposed to hold seven days — which is how the gap was found. Anyone rewriting this from scratch would hit the same thing. When *neither* timestamp is usable the run is still kept: an epoch date read as "1969, therefore old" would delete precisely the runs that have not happened yet. ## Token Uses a dedicated `ACTIONS_CLEANUP_TOKEN` repository secret rather than the automatic per-job token, since deleting a run may be beyond what that token permits. **You'll need to add that secret before the first run.** If the built-in token turns out to be sufficient, both the secret and the env line can go — worth checking on the first dispatch, since a token with delete rights in repository secrets is not nothing on an instance that also hosts the deploy. Host and repository come from the run's own context, so this file carries no hostname and survives the move #313 may yet make. No `npm install` step: the script uses node's own `https` module, so there is nothing to fetch and nothing to break when a dependency moves. ## Verification Run against the live instance, not just reasoned about: - Dry run reported the 19 stale cancelled runs the earlier pass had missed. - Applying it removed them — **19 deleted, 0 failed**. - The list went 632 → 158 across both passes. `node --check` clean. Nothing else in the repo imports it. Closes #324 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bermudalamb added 1 commit 2026-09-09 09:31:06 -05:00
chore(ci): a manually-run workflow to delete old Actions runs (#324)
SonarQube Analysis / sonarqube (pull_request) Failing after 22m15s
Linting / lint (pull_request) Successful in 4m46s
d7bfd47797
Gitea 1.27.3 expires a run's logs and artifacts but never the run record itself, so the Actions list grows without limit and fills with entries whose logs are already gone. Clearing it meant 455 API calls from a scratch file on one machine, which is the wrong home for something that has to happen again every few weeks.

Dry run unless apply is typed as true. The operation cannot be undone and there is no confirmation once it starts, so the harmless answer has to be the default rather than the one you get by leaving a box alone.

Manual only, deliberately. The list is an annoyance rather than a problem, and a cron that quietly deletes history deserves to be a decision taken on its own rather than one that arrives bundled with the tool.

A run that is not completed is never a candidate, which is also what stops the cleanup deleting the run it is executing in.

Ages a run by started_at, falling back to completed_at. That fallback is the whole reason this is worth committing rather than repeating from memory: a run cancelled before it ever started reports an epoch started_at while carrying a real completed_at, so reading only the first makes every cancelled run look undateable. The manual pass did exactly that and left nineteen runs from three weeks earlier in a list that was supposed to hold seven days. Neither timestamp usable still means keep — an epoch read as 1969 would delete the runs that have not happened yet.

Uses a dedicated ACTIONS_CLEANUP_TOKEN secret rather than the automatic per-job token, since deleting a run may be beyond what that token permits. If it turns out to be enough, the secret and the env line both go. Host and repository come from the run's own context, so the file carries no hostname and survives the move #313 may yet make.

No npm install: the script uses node's own https module, so there is nothing to fetch and nothing to break when a dependency moves.

Verified by running the script against the live instance: a dry run reported 19 stale cancelled runs the earlier pass had missed, and applying it removed them with no failures.

Closes #324

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bermudalamb merged commit de979f4bb6 into main 2026-09-09 10:48:29 -05:00
bermudalamb deleted branch chore/324-cleanup-actions-workflow 2026-09-09 10:48:30 -05:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bermudalamb/redefined-designs#325