Skip to content

About

Bind a merge to a review decision and a CI verdict taken on the same exact head.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

merge-guard

Bind a merge to a review decision and a CI verdict taken on the same exact head.

merge-guard is a pre-merge gate. It refuses a merge unless the review and the CI result both belong to the commit being merged, and it names the rule that refused. The first public release is a walking skeleton — the change classifier and the check profile it selects — and the rest of the gate follows.

Status

Pre-release. v0.0.2 is current: it carries the approval rule — an approval counts only if the review could have seen the head — and the release notes state what that still does not prove. v0.0.1 released the change classifier as one standard-library file. There is no package and no container image.

The composite action is installable today and pinned by commit SHA — see Use it in a repository. This repository runs that same gate on its own pull requests; .github/merge-guard.toml is its policy.

Design principles

  • Evidence is bound to a revision. A green run for another commit is not evidence for this one.
  • Refusals are named. Every refusal carries a stable code, so a caller can branch on it without parsing prose.
  • Fail closed. Missing CI, an unreadable forge or an ambiguous verdict is a refusal, never a pass.
  • One owner per fact. The classifier owns the rule that a path needs a stronger check; nothing else copies that list.

Use it in a repository

  1. Copy examples/merge-guard.toml to .github/merge-guard.toml and replace every placeholder: OWNER/REPO, REVIEWER[bot], its numeric reviewer_id, CHECKS, the workflow file names and the ordinary-path allowlist.
  2. Add the three workflows from examples/. The policy defaults name merge-guard-review.yml and merge-guard-merge.yml; review-relay.yml is the no-op relay and has no policy entry. Pin mikomiel/merge-guard by 40-hex SHA, and replace the placeholder values each file names at the top: the base branch, your CI workflow's display name, and the policy placeholders.
  3. Grant them the permissions each file declares and nothing more. The gate status is written by github-actions[bot]; the token input cannot change that identity, and a status from any other creator is refused.

Read docs/trusted-relay.md before changing the triggers: the relay is what makes the writes trustworthy.

A release is consumed as a pinned, generated copy rather than a dependency upgrade. docs/pin-bump.md is the procedure: what a release guarantees, how to record the pin, how to bump it, and the states to avoid.

Carried approvals

Required branches-up-to-date stays on, so a base advance normally invalidates an exact-head approval. When a person updates the branch, the engine carries the configured reviewer's latest approval from the previous head only if the pull request's own patch is identical: same files, same statuses, same patch text, renames included. A changed hunk, an extra file, a conflict-resolution merge that changes the patch, or a file whose patch GitHub does not return (binary or too large) means no carry-over. The published status says approved at <old head> (carried, unchanged diff) so the reviewer is visible.

Carry-over is a policy choice, not a fixed rule. carry_unchanged_diff = false in [review] turns it off, and then an approval binds to the commit it was given for: an identical patch on a new head inherits nothing and needs its own approval. It defaults to true so a consumer that already relies on it keeps the behaviour it pinned.

Development

The gate is Python, standard library where it can be, so a forge integration adds a client rather than a runtime. CI runs the public-content scan now, and lint and tests once there is code:

python3 scripts/check_estate_identifiers.py

See CONTRIBUTING.md. When a pull request cannot merge and the reason is not obvious, docs/troubleshooting.md covers the missed-trigger case and what the gate's status descriptions mean.

Licence

Apache-2.0. See LICENSE.

About

Bind a merge to a review decision and a CI verdict taken on the same exact head.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages