docs(platform.ci-cd): branch lifecycle — auto-delete vs protected develop

Auto-delete-head-branch-on-merge is on fleet-wide and is correct for
feature branches, but on a develop->main release PR the head IS develop,
so it deleted develop itself (hit hiveops-agent twice). Documents the
2026-07-19 fix: a deliberately permissive protection rule on develop in
41/42 repos that blocks deletion and nothing else, why hiveops-deploy is
excluded, and that the guard is by-name so other integration branches
need the same treatment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 12:42:43 -04:00
parent 5db0c610d2
commit a59a29d490
@@ -156,6 +156,46 @@ together on 2026-07-13 fired six workflows simultaneously and **broke runner-01'
builds failed with the lease/network errors above. **Stagger merges**, or accept that you will be
repairing the runner afterwards.
## Branch lifecycle — auto-delete on merge, and why `develop` is protected
**Auto-delete-head-branch-on-merge is ON in all 49 repos.** It exists to reap the feature branches
cut *from* `develop` after they merge back, and for that it is correct — leave it on.
⚠️ **The trap:** on a `develop` → `main` release PR, the head branch **is `develop`**, so the same
setting deleted `develop` itself on merge. `hiveops-agent` hit this twice; each time `develop` had to
be recreated from `main`. Gitea has no per-branch exclusion for auto-delete — the only lever is that
**a protected branch cannot be deleted**.
**Fixed 2026-07-19:** `develop` now carries a branch-protection rule in **41 of 42** repos that have
one. The rule is deliberately permissive and **restricts nothing except deletion** —
`enable_push: true`, no push whitelist, `required_approvals: 0`, no status checks, no
outdated-branch blocking. Direct pushes and PR merges into `develop` behave exactly as before.
| Operation on `develop` | Before | After |
|---|---|---|
| Delete branch | `204` deleted | `403 branch protected` |
| Direct push / write | allowed | allowed (unchanged) |
| PR merge into `develop` | allowed | allowed (unchanged) |
`hiveops-deploy` is the one exclusion — it is **archived** (the API returns `423 Locked`), so no
merge can run and there is nothing to protect against.
⛔ **Do not remove this protection as "redundant".** It looks like a no-op rule precisely because it
is designed to be one; deleting it re-arms the trap above.
**It guards `develop` by name only.** Any other long-lived integration branch used as a PR *head*
(release branches, recovery branches) is still exposed — protect those the same way:
```bash
curl -X POST "$GITEA/api/v1/repos/<org>/<repo>/branch_protections" \
-H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \
-d '{"branch_name":"develop","enable_push":true,"enable_push_whitelist":false,
"required_approvals":0,"block_on_rejected_reviews":false,
"block_on_official_review_requests":false,"block_on_outdated_branch":false,
"enable_status_check":false}'
# verify: GET /repos/<org>/<repo>/branches/develop → "protected": true
```
## Root fragility
The runners are VMs on the cluster they depend on, with a single non-HA resolver — so cluster