Skip to content

Commit 4634236

Browse files
TMHSDigitalclaude
andcommitted
docs: document the main branch protection model
`main` now carries the `main-integrity` ruleset: deletion, non-fast-forward, and required-linear-history, with no bypass actors. Record what is enforced, what is not, and why. Required status checks and a PR requirement are deliberately absent. A required-check rule blocks direct pushes for any actor without a bypass, and `release.yml` pushes its bump commit to `main` as github-actions[bot]. On a user-owned repository GitHub refuses the GitHub Actions integration as a bypass actor, and a role-based bypass covers the owner rather than the bot. Tracked in #192. Also record the required-check set to adopt if that constraint lifts, and why `Blender 5.1 smoke`, `Auto-label by path`, and `Resolve smoke matrix` must stay out of it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
1 parent ab005ff commit 4634236

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,76 @@ Default PR smoke is Blender 5.2 and 4.5 (`.github/workflows/blender-smoke.yml`).
145145
deploy Pages. Observed on `13ea521` (`ci:` #137): Validate, drift-check,
146146
and Release ran; Pages did not. Intentional, not a failed job.
147147

148+
## Branch protection on `main`
149+
150+
`main` carries the repository ruleset **`main-integrity`** (branch target
151+
`~DEFAULT_BRANCH`, enforcement `active`, **no bypass actors**). Three rules:
152+
153+
- `deletion` — the branch cannot be deleted
154+
- `non_fast_forward` — force-push is refused for every actor, owner included
155+
- `required_linear_history` — merge commits are refused, matching the
156+
squash-merge convention
157+
158+
Verify with `gh api repos/TMHSDigital/Blender-Developer-Tools/rules/branches/main`.
159+
The classic `/branches/main/protection` endpoint returns 404 by design: this
160+
is a ruleset, not classic branch protection, and the two are separate APIs.
161+
162+
**Required status checks are deliberately absent, and a pull request is not
163+
required.** A PR whose smoke jobs are red can still be merged. Merge-on-green
164+
is convention here, not enforcement — see
165+
[#192](https://github.com/TMHSDigital/Blender-Developer-Tools/issues/192).
166+
167+
The reason is structural. A required-status-check rule blocks *direct pushes*
168+
to the branch for any actor without a bypass, not only PR merges.
169+
`release.yml` pushes its version-bump commit straight to `main` as
170+
`github-actions[bot]` using `secrets.GITHUB_TOKEN`, so the rule would break
171+
every release. On a user-owned repository GitHub rejects the only bypass
172+
actor that would cover it:
173+
174+
```
175+
422 Validation Failed
176+
"Actor GitHub Actions integration must be part of the ruleset source or owner organization"
177+
```
178+
179+
A role-based bypass does not substitute: `RepositoryRole:Write` covers the
180+
repository owner (admin inherits write) and never covers the bot — backwards
181+
from what is needed, and it would re-open admin merges of red PRs, which is
182+
the hole the protection exists to close.
183+
184+
The three rules that *are* active were chosen because a fast-forward,
185+
single-parent push does not violate any of them, so `release.yml` keeps
186+
working untouched: the bump commit lands, the tag push proceeds (a branch
187+
ruleset does not target tags), the GitHub release is cut, and the
188+
`gh workflow run pages.yml --ref main` dispatch fires.
189+
190+
### If required checks become enforceable
191+
192+
Should the repository move to an organization, or `release.yml` stop pushing
193+
to `main`, these are the checks that run unconditionally on every PR and are
194+
therefore the required-check set:
195+
196+
- `Blender 4.5 smoke`
197+
- `Blender 5.2 smoke`
198+
- `Ecosystem drift check`
199+
- `Validate content counts`
200+
- `Validate plugin manifest`
201+
- `Validate smoke harness protocol`
202+
- `Validate structure and frontmatter`
203+
204+
Three checks that appear on PRs are deliberately **excluded**:
205+
206+
- **`Blender 5.1 smoke` is label-gated.** It only runs when `needs-5.1` is
207+
applied. As a required check it would block every unlabeled PR forever on
208+
a job that never reports.
209+
- **`Auto-label by path`** — `label-sync.yml` triggers on `opened` and
210+
`synchronize` only. A reopened PR with no new push never reports it.
211+
- **`Resolve smoke matrix`** — skipped on label events other than
212+
`needs-5.1`, and it is plumbing rather than a gate; its failure already
213+
blocks the two smoke jobs that depend on it.
214+
215+
The two `Socket Security` checks come from a third-party GitHub App. An
216+
outage or an uninstall would deadlock merges, so they are advisory.
217+
148218
## Exit codes
149219

150220
Three roles, not one global table. Do not copy a code from one script into

0 commit comments

Comments
 (0)