Branch protection on main in mcp-hangar/mcp-hangar ensures that every commit landing in the default branch has passed the full CI validation suite. It prevents direct pushes, enforces linear history (squash-merge; rebase-merge is disabled), and requires conversation resolution before merge.
Two layers apply to main, and both must pass.
Classic branch protection:
- Required status checks (strict — branch must be up to date): the 14 listed below
- Required approving reviewers: 0
- Require code owner reviews: false
- Enforce admins: true
- Required linear history: true
- Allow force pushes: false
- Allow deletions: false
- Block creations: false
- Required conversation resolution: true
Repository rulesets, both with an always-bypass for the admin role:
main(default branch): no deletion, no force push.main-integrity(refs/heads/main): no deletion, no force push, linear history, the same 14 status checks (strict), and a pull request with 0 approvals and every review thread resolved.
Read the live state with gh api repos/mcp-hangar/mcp-hangar/branches/main/protection
and gh api repos/mcp-hangar/mcp-hangar/rules/branches/main.
The context is the job name; a check from a reusable workflow is
<calling job> / <reusable job>.
| Check name | Workflow file | What it enforces |
|---|---|---|
required-check |
pr-validation.yml |
Paths-filter summary gate |
check |
changelog-check.yml |
Changelog fragment present in changelog.d/ |
pr-title / validate |
pr-title.yml |
Conventional Commits title |
branch-name / validate |
branch-name.yml |
Branch naming convention |
pr-body / validate |
pr-body.yml |
PR body section structure |
lint |
ci-core.yml |
ruff check and format, mypy, import contracts |
test (3.11), test (3.12), test (3.13), test (3.14) |
ci-core.yml |
Tests per Python version; on a pull request 3.12 and 3.13 report a skip and run on main only |
decision-coverage |
ci-core.yml |
Branch-coverage floors on decision paths |
integration, integration-newest |
ci-core.yml |
Integration tests |
build |
ci-core.yml |
Package build |
| Setting | Solo | Community |
|---|---|---|
| Required approving reviewers | 0 | 1 |
| Require code owner reviews | false | true |
| Enforce admins | false | true |
These are the script's two modes. The live setting matches neither: 0
reviewers and no code owner reviews, as in solo, but enforce_admins: true, as
in community.
Flip to community mode when there is at least one second maintainer. Until then require_code_owner_reviews: true would block all merges to CODEOWNERS-protected paths since GitHub does not allow self-approval.
scripts/setup-branch-protection.sh has not kept up: it still writes the six
checks of an older layout, two of which (pr-validation / required-check and
enterprise-boundary) no job reports, and its solo mode sets
enforce_admins: false. Running it replaces the live list above. Update its
contexts array before running it; the rulesets are not managed by the script.
bash scripts/setup-branch-protection.sh
bash scripts/setup-branch-protection.sh --mode community
bash scripts/setup-branch-protection.sh --dry-run- Merge the workflow producing the check.
- Wait for at least one PR to run it green.
- Add the check name to the
contextsarray inscripts/setup-branch-protection.sh. - Re-run the script.
- Add it to the
main-integrityruleset too. The ruleset carries its own copy of the required checks, which the script never touches.
- Comment out (do not delete) the check name in the script.
- Re-run the script to apply the reduced list.
- Remove it from the
main-integrityruleset, which the script does not change; a check still listed there stays required. - Delete or disable the workflow file in a separate PR.
The live setting is enforce_admins: true, so the classic protection applies to admins as well, and a direct git push origin main is not an option while it is set; the rulesets' admin bypass does not lift the classic protection. Use only when CI itself is broken or a critical hotfix cannot wait. Bypass requires:
- Temporarily set
enforce_admins: falsevia GitHub UI. - Perform the emergency action.
- Set
enforce_adminsback totruein the GitHub UI, or withgh api -X POST repos/mcp-hangar/mcp-hangar/branches/main/protection/enforce_admins. Do not restore it by re-running the script, which also rewrites the required checks and the review settings.