|
| 1 | +# Branch Protection Setup |
| 2 | + |
| 3 | +This document describes how to set up branch protection rules for the `main` branch to enforce CI checks and prevent direct commits. |
| 4 | + |
| 5 | +## Required Steps |
| 6 | + |
| 7 | +### 1. Enable Branch Protection |
| 8 | + |
| 9 | +Go to: **Repository Settings → Branches → Add branch protection rule** |
| 10 | + |
| 11 | +### 2. Configure Protection Rules |
| 12 | + |
| 13 | +**Branch name pattern:** `main` |
| 14 | + |
| 15 | +**Required Settings:** |
| 16 | + |
| 17 | +- ✅ **Require a pull request before merging** |
| 18 | + - ✅ Require approvals: 1 (adjust based on team size) |
| 19 | + - ✅ Dismiss stale pull request approvals when new commits are pushed |
| 20 | + - ✅ Require review from Code Owners (optional, if using CODEOWNERS) |
| 21 | + |
| 22 | +- ✅ **Require status checks to pass before merging** |
| 23 | + - ✅ Require branches to be up to date before merging |
| 24 | + - **Required status checks:** |
| 25 | + - `Lint` |
| 26 | + - `Test (Python 3.11)` |
| 27 | + - `Test (Python 3.12)` |
| 28 | + - `All checks passed` |
| 29 | + |
| 30 | +- ✅ **Require conversation resolution before merging** (recommended) |
| 31 | + |
| 32 | +- ✅ **Require linear history** (optional, enforces rebase/squash) |
| 33 | + |
| 34 | +- ✅ **Do not allow bypassing the above settings** (recommended) |
| 35 | + |
| 36 | +- ✅ **Restrict who can push to matching branches** |
| 37 | + - Only allow administrators (prevents direct commits to main) |
| 38 | + |
| 39 | +### 3. Additional Recommended Settings |
| 40 | + |
| 41 | +- ✅ **Allow force pushes:** Disabled |
| 42 | +- ✅ **Allow deletions:** Disabled |
| 43 | + |
| 44 | +## Enforcement |
| 45 | + |
| 46 | +Once enabled, all changes to `main` must: |
| 47 | + |
| 48 | +1. Be submitted via pull request |
| 49 | +2. Pass all CI checks (lint + tests) |
| 50 | +3. Be reviewed and approved by at least 1 person |
| 51 | +4. Have all conversations resolved |
| 52 | + |
| 53 | +Direct commits to `main` will be blocked, even for administrators. |
| 54 | + |
| 55 | +## Emergency Override |
| 56 | + |
| 57 | +Repository administrators can temporarily disable branch protection in extreme emergencies, but this should be: |
| 58 | + |
| 59 | +1. Documented in an incident report |
| 60 | +2. Re-enabled immediately after the emergency |
| 61 | +3. Followed up with a post-mortem |
| 62 | + |
| 63 | +## Verification |
| 64 | + |
| 65 | +After setup, verify protection is working: |
| 66 | + |
| 67 | +```bash |
| 68 | +# This should fail (cannot push to main directly) |
| 69 | +git checkout main |
| 70 | +echo "test" >> README.md |
| 71 | +git commit -am "test direct commit" |
| 72 | +git push origin main |
| 73 | +# Expected: ERROR - protected branch hook declined |
| 74 | +``` |
| 75 | + |
| 76 | +## CI Status Checks |
| 77 | + |
| 78 | +The following jobs must pass: |
| 79 | + |
| 80 | +1. **Lint** - Code formatting (black) and style (ruff) |
| 81 | +2. **Test (Python 3.11)** - Full test suite on Python 3.11 |
| 82 | +3. **Test (Python 3.12)** - Full test suite on Python 3.12 |
| 83 | +4. **All checks passed** - Aggregates all job results |
| 84 | + |
| 85 | +Each PR will show these checks at the bottom with pass/fail status. |
| 86 | + |
| 87 | +## Workflow for Contributors |
| 88 | + |
| 89 | +1. Create feature branch: `git checkout -b feature/my-feature` |
| 90 | +2. Make changes and commit |
| 91 | +3. Push branch: `git push origin feature/my-feature` |
| 92 | +4. Open PR on GitHub |
| 93 | +5. Wait for CI checks to pass |
| 94 | +6. Request review |
| 95 | +7. Address feedback |
| 96 | +8. Merge after approval + passing checks |
| 97 | + |
| 98 | +## Troubleshooting |
| 99 | + |
| 100 | +**Q: CI checks not running?** |
| 101 | +- Ensure workflow file is in `.github/workflows/ci.yml` |
| 102 | +- Check Actions tab for errors |
| 103 | +- Verify branch is not filtered in workflow `on:` section |
| 104 | + |
| 105 | +**Q: Status checks not appearing in branch protection?** |
| 106 | +- Status checks only appear after they've run at least once |
| 107 | +- Push a PR to trigger the workflow first |
| 108 | +- Then they'll be available in branch protection settings |
| 109 | + |
| 110 | +**Q: Need to bypass for hotfix?** |
| 111 | +- Don't. Instead, create an emergency branch protection policy |
| 112 | +- Or temporarily add yourself to an exception list |
| 113 | +- Always re-enable protection immediately after |
| 114 | + |
| 115 | +## Related Files |
| 116 | + |
| 117 | +- `.github/workflows/ci.yml` - CI workflow definition |
| 118 | +- `pyproject.toml` - Tool configuration (black, ruff, pytest) |
| 119 | +- `CONTRIBUTING.md` - Contributor guidelines |
0 commit comments