Skip to content

Skip redundant push builds for branches with an open PR - #3941

Merged
siegfriedpammer merged 3 commits into
masterfrom
ci-skip-duplicate-push-builds
Jul 31, 2026
Merged

Skip redundant push builds for branches with an open PR#3941
siegfriedpammer merged 3 commits into
masterfrom
ci-skip-duplicate-push-builds

Conversation

@siegfriedpammer

Copy link
Copy Markdown
Member

Every push to a branch with an open PR currently builds twice: once via the push trigger and once via the pull_request trigger, doubling the Actions cost of every PR iteration (including the 10x-billed macOS leg).

This adds a small Gate job to build-ilspy.yml and build-frontends.yml that skips the push-triggered build when the pushed branch has an open PR that already builds it via the pull_request trigger. The pull_request run is kept as the canonical one because it tests the merge with the base branch. Details:

  • Pushes to master and release/* always build (their runs publish packages, and no PR of theirs may suppress that).
  • Only open PRs with base master/release/* suppress a push build; a PR targeting any other branch never fires the pull_request trigger, so its head branch keeps building via push.
  • Branches without a PR build on push, unchanged. Fork PRs are unaffected.
  • The gate cannot live in the on: section: trigger filters cannot see whether an open PR exists, so a job queries GET /repos/.../pulls?head=... (needs pull-requests: read).

Known benign race: pushing a branch and then opening its PR lets the already-started push run finish, so that one iteration still builds twice.

Verified with actionlint; the PR query and jq base filter were tested against the live repo, and the event/branch routing (master/release/*/feature pushes, pull_request merge refs) was exercised in a shell self-check.

🤖 Generated with Claude Code

A branch with an open PR was built twice per push, once by the push
trigger and once by the pull_request trigger, doubling the Actions cost
of every PR iteration. The pull_request run is the canonical one (it
tests the merge with the base branch), so a small gate job now asks the
API whether the pushed branch has an open PR whose base would fire the
pull_request trigger and skips the push build if so. Pushes to master
and release/* are exempt because their runs publish packages; PRs
targeting other branches are ignored because they never trigger a
pull_request build that could replace the push one.

Filtering fork PRs in the on: section instead was considered and
rejected: trigger-level filters cannot see whether an open PR exists,
and skipping the pull_request runs would have lost merge testing.

Assisted-by: Claude:claude-fable-5:Claude Code
The gate job was copy-pasted into build-ilspy.yml and build-frontends.yml
and the two copies had already started drifting (job casing, comment
wording). A workflow_call workflow keeps a single definition; the callers
shrink to a uses: job and route its "run" output to their build jobs
unchanged. Each caller must still grant pull-requests: read explicitly,
because the called workflow's token is the intersection of what the
caller grants and what the callee requests, and both callers default to
contents: read only.

Assisted-by: Claude:claude-fable-5:Claude Code
The decompiler suite is cross-platform code already exercised by the
Windows and Linux jobs; running it a third time on macOS only made the
slowest job of the matrix (~54 min vs ~41 min on Linux) slower without
adding coverage.

Assisted-by: Claude:claude-fable-5:Claude Code
@siegfriedpammer
siegfriedpammer merged commit 4a73dcb into master Jul 31, 2026
15 checks passed
@siegfriedpammer
siegfriedpammer deleted the ci-skip-duplicate-push-builds branch July 31, 2026 10:33
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.

2 participants