Skip to content

Commit 3ce1ef4

Browse files
committed
docs(governance): enforce release-branch protected flow
1 parent 3b4b3c1 commit 3ce1ef4

3 files changed

Lines changed: 61 additions & 10 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI (Master Promotion)
2+
3+
on:
4+
pull_request_target:
5+
branches:
6+
- master
7+
types:
8+
- opened
9+
- reopened
10+
- synchronize
11+
- edited
12+
- ready_for_review
13+
14+
jobs:
15+
master-promotion:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Enforce master source branch
19+
env:
20+
HEAD_REF: ${{ github.event.pull_request.head.ref }}
21+
BASE_REF: ${{ github.event.pull_request.base.ref }}
22+
run: |
23+
set -euo pipefail
24+
[ "$BASE_REF" = "master" ] || exit 0
25+
if [[ ! "$HEAD_REF" =~ ^release/ ]]; then
26+
echo "::error::PRs targeting master must come from release/* branches. Found head branch: $HEAD_REF"
27+
exit 1
28+
fi
29+
echo "master promotion rule satisfied: $HEAD_REF -> $BASE_REF"

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ This repository follows Tinman Doctrine.
2424
- Prefer small, unambiguous issues; split broad tasks into manageable subtasks
2525
- Keep commits small and issue-scoped; default to one issue -> one small commit set
2626
- Exceptions are allowed for non-diff tasks, discovery-first work, or unavoidable architecture-level changes; document rationale in the issue or PR
27+
- Do not push directly to protected branches (`master`, `develop`); use PR flow even when operating with admin credentials or AI automation
2728
- Ensure lint/tests/build pass for touched areas
2829
5. If local repo policy conflicts with doctrine snapshot, follow local repo files and call out the conflict explicitly.

docs/doctrine/repo-management.md

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ For important repositories (templates, core libs, product repos), enable:
6969
- Require status checks to pass
7070
- Restrict who can push (optional)
7171
- Require linear history (optional)
72+
- Do not allow admin bypass on protected branch rules
7273

7374
If using an organization, prefer organization rulesets over per-repo configuration.
7475

@@ -245,25 +246,45 @@ This section applies only to this Doctrine repository.
245246

246247
### Branch model
247248

249+
- `master` -> stable release branch
248250
- `develop` -> integration branch for ongoing changes
249-
- `master` -> stable branch for promoted releases
250-
- `feature/*` -> short-lived heavy refactor branches
251+
- `feature/*` -> short-lived implementation branches merged into `develop`
252+
- `fix/*` -> short-lived bugfix branches merged into `develop`
253+
- `release/*` -> short-lived release stabilization branches cut from `develop`
251254

252255
### Release process
253256

254-
1. Ensure release-ready work is merged into `develop`.
255-
2. Promote `develop` to `master` using a PR with base `master` and head `develop`.
256-
3. Merge only after required checks pass.
257-
4. Create signed tag on `master`:
258-
- `git tag -s vX.Y -m "Release vX.Y"`
259-
5. Push `master` and tag:
257+
1. Ensure release-ready work is merged into `develop` via PRs from feature/fix branches.
258+
2. Create release branch from `develop`:
259+
- `git checkout -b release/vX.Y.Z develop`
260+
3. Apply final stabilization updates on `release/*` (final fixes, docs, changelog/release notes, version touches).
261+
4. Promote release to stable via PR with base `master` and head `release/*`.
262+
5. After merge to `master`, back-propagate identical release changes via PR with base `develop` and head `release/*`.
263+
6. Merge only after required checks pass on both PRs.
264+
7. Create signed tag on `master`:
265+
- `git tag -s vX.Y.Z -m "Release vX.Y.Z"`
266+
8. Push `master` and tag:
260267
- `git push origin master`
261-
- `git push origin vX.Y`
262-
6. If tag was created unsigned by mistake, recreate it as signed on the same commit and force-push:
268+
- `git push origin vX.Y.Z`
269+
9. Delete the short-lived release branch after both merges complete.
270+
10. If tag was created unsigned by mistake, recreate it as signed on the same commit and force-push:
263271
- `git tag -d vX.Y`
264272
- `git tag -s vX.Y -m "Release vX.Y" <release-commit>`
265273
- `git push --force origin vX.Y`
266274

275+
### Protected branch behavior
276+
277+
- No direct pushes to `master` or `develop`.
278+
- All changes to protected branches must arrive through pull requests.
279+
- Protected branch rules apply to admins and automation identities as well (no bypass).
280+
- PRs targeting `master` must come from `release/*` branches.
281+
282+
### Emergency hotfix rule
283+
284+
- If an emergency requires immediate stabilization, use `release/hotfix-*` branch naming.
285+
- Merge `release/hotfix-*` to `master` first, then merge the same branch to `develop`.
286+
- Keep the same signed-commit and signed-tag requirements.
287+
267288
### Document status model
268289

269290
Each file must contain:

0 commit comments

Comments
 (0)