Skip to content

Cap what a single fork pull request can spend - #21

Merged
gvonnessi merged 1 commit into
mainfrom
ci/limit-fork-pr-runs
Aug 20, 2026
Merged

Cap what a single fork pull request can spend#21
gvonnessi merged 1 commit into
mainfrom
ci/limit-fork-pr-runs

Conversation

@gvonnessi

Copy link
Copy Markdown
Contributor

Cap what a single fork pull request can spend

This workflow is reachable from a fork pull request and had neither a
concurrency group nor a job timeout, so it inherited GitHub's defaults for
both: unlimited concurrent runs, and six hours per job. On paid
Blacksmith runners that is a real number rather than a theoretical one —
6 job runs at the six-hour ceiling is 36 compute-hours for a single
push, and without a concurrency group a contributor pushing five times held
five complete sets at once rather than superseding the previous one.

The repo now requires approval for every external contributor's fork PR, so
nothing external starts without a deliberate click. This is the second half:
the approval gate decides who runs, and these two settings decide how
much
a run that has been approved can cost. It bounds our own pushes too,
which is where most of the waste actually was.

Sized against measurement rather than a guess. Over the last six runs the
slowest job here is 30s; 20 minutes leaves generous headroom while turning
the worst case from 36 compute-hours into about 2. A job that hits 20
minutes is not a slow job, it is a stuck one.

Change

  • concurrency group keyed on workflow + ref, with cancel-in-progress: true
  • timeout-minutes: 20 on all 4 job definitions

Worst case per push

before after
6 job runs at the ceiling 36 compute-hours ~2 compute-hours
repeated pushes accumulate superseded

Test plan

  • YAML parses; triggers unchanged; step count identical to main
  • Every job definition carries timeout-minutes
  • This PR's own run is the check — confirm it passes well inside 20 min
  • Push twice in quick succession and confirm the first run is cancelled

This workflow is reachable from a fork pull request and had neither a
concurrency group nor a job timeout, so it inherited GitHub's defaults for
both: unlimited concurrent runs, and **six hours** per job. On paid
Blacksmith runners that is a real number rather than a theoretical one —
6 job runs at the six-hour ceiling is 36 compute-hours for a single
push, and without a concurrency group a contributor pushing five times held
five complete sets at once rather than superseding the previous one.

The repo now requires approval for every external contributor's fork PR, so
nothing external starts without a deliberate click. This is the second half:
the approval gate decides *who* runs, and these two settings decide *how
much* a run that has been approved can cost. It bounds our own pushes too,
which is where most of the waste actually was.

Sized against measurement rather than a guess. Over the last six runs the
slowest job here is 30s; 20 minutes leaves generous headroom while turning
the worst case from 36 compute-hours into about 2. A job that hits 20
minutes is not a slow job, it is a stuck one.
@gvonnessi
gvonnessi merged commit 055c74f into main Aug 20, 2026
6 checks passed
@gvonnessi
gvonnessi deleted the ci/limit-fork-pr-runs branch August 20, 2026 11:04
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