ci(actions): keep push runs on main from being cancelled #28

Merged
lucas merged 2 commits from agent/issue-26-push-run-concurrency into main 2026-11-13 15:04:39 +01:00
Collaborator

Adds a workflow-level concurrency block to .forgejo/workflows/build.yml:

concurrency:
  cancel-in-progress: ${{ forgejo.event_name == 'pull_request' }}

A push run on main is no longer cancelled when a second merge lands seconds later, so every main commit keeps a verdict that is not retracted. Pull-request runs keep superseding each other.

Design points (also in the commit message and as a comment in the file):

  • No group key, deliberately. Per the reference, without a group a false cancel-in-progress means no concurrency management at all — runs proceed in parallel up to the runner's capacity and all finish. A group would instead serialise runs that are independent.
  • Keyed on event_name, not on the ref. The docs' example uses forgejo.ref_name != 'main', but the documented sample forgejo context for a pull-request event carries "ref_name": "main", so a ref-based test risks disabling cancellation on PR runs too. Since on.push.branches is ["main"], "event is not pull_request" is exactly "push on main".

Verified: concurrency is listed as accepting the forgejo context, and event_name is a documented field of it. The file still parses as YAML with the expression intact. The real check is this PR's own Build run — Forgejo evaluates the expression server-side at run creation, so an unsupported key or malformed expression shows up as a run that does not start.

Fallback if the instance rejects the expression: the plain documented form concurrency: / cancel-in-progress: false, which still fixes the main case at the cost of letting superseded PR runs finish too. I will report here if that happens.

Note: the existing red check on 530bd777ae041662a64195eb7254beca641f5ff7 stays red until run #19 is re-run from the Actions UI; this change only affects future runs. Genuine parallelism additionally depends on the runner's runner.capacity (instance-side, not reachable from this repository); with capacity 1 the runs simply execute one after the other — both to completion, which is the property asked for.

Closes: #26

Adds a workflow-level `concurrency` block to `.forgejo/workflows/build.yml`: ```yaml concurrency: cancel-in-progress: ${{ forgejo.event_name == 'pull_request' }} ``` A `push` run on `main` is no longer cancelled when a second merge lands seconds later, so every `main` commit keeps a verdict that is not retracted. Pull-request runs keep superseding each other. Design points (also in the commit message and as a comment in the file): - **No `group` key, deliberately.** Per the [reference](https://forgejo.org/docs/v17.0/user/actions/reference/#concurrencycancel-in-progress), without a group a false `cancel-in-progress` means *no concurrency management at all* — runs proceed in parallel up to the runner's capacity and all finish. A `group` would instead serialise runs that are independent. - **Keyed on `event_name`, not on the ref.** The docs' example uses `forgejo.ref_name != 'main'`, but the documented sample `forgejo` context for a pull-request event carries `"ref_name": "main"`, so a ref-based test risks disabling cancellation on PR runs too. Since `on.push.branches` is `["main"]`, "event is not `pull_request`" is exactly "push on `main`". Verified: `concurrency` is listed as accepting the `forgejo` context, and `event_name` is a documented field of it. The file still parses as YAML with the expression intact. The real check is this PR's own `Build` run — Forgejo evaluates the expression server-side at run creation, so an unsupported key or malformed expression shows up as a run that does not start. Fallback if the instance rejects the expression: the plain documented form `concurrency:` / `cancel-in-progress: false`, which still fixes the `main` case at the cost of letting superseded PR runs finish too. I will report here if that happens. Note: the existing red check on `530bd777ae041662a64195eb7254beca641f5ff7` stays red until run #19 is re-run from the Actions UI; this change only affects future runs. Genuine parallelism additionally depends on the runner's `runner.capacity` (instance-side, not reachable from this repository); with capacity 1 the runs simply execute one after the other — both to completion, which is the property asked for. Closes: #26
ci(actions): keep push runs on main from being cancelled
All checks were successful
Build / build (pull_request) Successful in 46s
be6af55c92
Without a `concurrency` key, Forgejo cancels any in-progress invocation
of a workflow as soon as a newer push or pull_request event triggers it.
When two pull requests are merged within seconds of each other, the run
for the first merge commit is killed mid-step and that commit keeps a
red "has been cancelled" check forever, even though its content is fine
and the proof sits one commit later.

Setting `cancel-in-progress` to false for push events removes that
management for `main` while leaving it in place for pull requests, where
superseding is useful: the result for an obsolete commit is not worth
runner time. The `group` key is omitted on purpose — without a group a
false `cancel-in-progress` means no concurrency management at all and
every run completes, while adding a group would serialise runs that are
independent.

The condition tests `forgejo.event_name` rather than the ref: a
pull-request event's context carries the base ref (`ref_name: main`), so
the ref-based form documented upstream would disable cancellation for
pull requests as well.

Refs: #26
Co-Authored-By: Claude Opus 5 via omp-deck
omp-deck changed title from WIP: ci(actions): keep push runs on main from being cancelled to ci(actions): keep push runs on main from being cancelled 2026-11-13 14:38:36 +01:00
Author
Collaborator

Verification done: Build / build (pull_request) on be6af55 ran and finished green (run 16498). The run was created and dispatched normally, so this instance accepts the concurrency key and evaluates the forgejo.event_name expression server-side — the fallback to the plain cancel-in-progress: false form is not needed.

Marked ready for review.

Verification done: `Build / build (pull_request)` on `be6af55` ran and finished green ([run 16498](/lucas/nanoKontroller2/actions/runs/23)). The run was created and dispatched normally, so this instance accepts the `concurrency` key and evaluates the `forgejo.event_name` expression server-side — the fallback to the plain `cancel-in-progress: false` form is not needed. Marked ready for review.
lucas requested changes 2026-11-13 15:01:33 +01:00
Dismissed
@ -8,0 +20,4 @@
# The test is on `event_name` and not on the ref because a pull-request event's
# context carries the base ref (`ref_name: main`), which would switch
# cancellation off there too. Push runs can only come from `main` (see
# `on.push.branches` above), so "not a pull request" is exactly "push on main".
Owner

Are you trying to write a novel here?

Are you trying to write a novel here?
Author
Collaborator

Fair. Cut from 16 lines to 5 in 07be414, keeping only the two things that aren't obvious from the setting itself — why there is no group, and why the condition tests the event rather than the ref. The incident narrative is in the commit message and #26, where it belongs.

# Keeps a `main` run from being cancelled by the next merge, so every commit
# keeps its verdict; superseded pull-request runs still cancel. No `group`: a
# group would serialise independent runs, whereas omitting it disables the
# cancellation outright. Not keyed on the ref, because a pull-request event's
# context carries the base ref (`ref_name: main`).
# https://forgejo.org/docs/v17.0/user/actions/reference/#concurrencycancel-in-progress

Say the word if you want it shorter still — the group and ref rationales are the two I'd argue hardest to keep, since both are traps someone would otherwise walk into when editing this.

Fair. Cut from 16 lines to 5 in `07be414`, keeping only the two things that aren't obvious from the setting itself — why there is no `group`, and why the condition tests the event rather than the ref. The incident narrative is in the commit message and #26, where it belongs. ```yaml # Keeps a `main` run from being cancelled by the next merge, so every commit # keeps its verdict; superseded pull-request runs still cancel. No `group`: a # group would serialise independent runs, whereas omitting it disables the # cancellation outright. Not keyed on the ref, because a pull-request event's # context carries the base ref (`ref_name: main`). # https://forgejo.org/docs/v17.0/user/actions/reference/#concurrencycancel-in-progress ``` Say the word if you want it shorter still — the `group` and ref rationales are the two I'd argue hardest to keep, since both are traps someone would otherwise walk into when editing this.
docs(actions): cut the concurrency comment down to its reasons
All checks were successful
Build / build (pull_request) Successful in 50s
07be414935
Sixteen lines of prose for a two-line setting buried the two facts a
reader actually needs: why there is no `group`, and why the condition
looks at the event instead of the ref. The rest restated the setting or
retold the incident, which belongs in the commit history and the issue,
not in the workflow file.

Refs: #26
Co-Authored-By: Claude Opus 5 via omp-deck
lucas approved these changes 2026-11-13 15:04:35 +01:00
lucas merged commit 0859597bba into main 2026-11-13 15:04:39 +01:00
lucas deleted branch agent/issue-26-push-run-concurrency 2026-11-13 15:04:40 +01:00
Sign in to join this conversation.
No reviewers
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
lucas/nanoKontroller2!28
No description provided.