Skip to content

Refuse a pull request that does not target main - #463

Merged
jeremymanning merged 1 commit into
mainfrom
ci/require-main-base
Aug 3, 2026
Merged

Refuse a pull request that does not target main#463
jeremymanning merged 1 commit into
mainfrom
ci/require-main-base

Conversation

@jeremymanning

Copy link
Copy Markdown
Member

The mechanical version of a discipline I have been applying by hand.

What it prevents

#452, #453 and #455 were each merged into a feature branch that had itself already been merged and deleted. GitHub reported MERGED for all three. None of the work reached main. It was found later by checking file contents against origin/maingit cat-file -e origin/main:<path> — rather than by trusting the badge.

The badge cannot distinguish "merged into main" from "merged into a dead branch". This check can, and it runs before the merge rather than after it.

Root cause was stacking three PRs deep and merging them in what looked like the natural order.

The check

One job, gated to pull requests, failing when base_ref != main with a message explaining the failure mode rather than just the condition.

base_ref is passed through env rather than interpolated into the shell body — branch names are attacker-controllable from forks, so ${{ github.base_ref }} inside run: would be a script-injection hole.

Verification

  • Workflow parses; the guard accepts main and rejects epic/some-feature, fix/already-merged-branch, and main; echo INJECTED (the last reaching the comparison as one literal string, not as shell).
  • This PR targets main, so the new check should pass on itself.

Not included

Requiring an independent approval for compiler/runtime/validator changes is branch-protection configuration, not a workflow file. It governs whether this work can merge unreviewed, so it is a repository-owner decision rather than something to grant myself in a PR.

🤖 Generated with Claude Code

#452, #453 and #455 were each merged into a feature branch that had itself
already been merged and deleted. GitHub reported MERGED for all three, and
none of the work reached main. It was found later by checking file contents
against origin/main, not by looking at badges.

The badge cannot distinguish 'merged into main' from 'merged into a dead
branch'. This check can, and it runs before the merge rather than after it.

The branch name goes through env rather than into the shell body: base_ref is
attacker-controllable from a fork, so interpolating it into run: would be a
script injection.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jeremymanning
jeremymanning merged commit e30feee into main Aug 3, 2026
10 checks passed
@jeremymanning
jeremymanning deleted the ci/require-main-base branch August 3, 2026 23:53
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