Skip to content

chore(#116): adopt release-cut branch model (dev/main + tags) — framework only#126

Merged
atlas-apex merged 2 commits into
devfrom
chore/GH-116-release-cut-model
Apr 25, 2026
Merged

chore(#116): adopt release-cut branch model (dev/main + tags) — framework only#126
atlas-apex merged 2 commits into
devfrom
chore/GH-116-release-cut-model

Conversation

@atlas-apex

Copy link
Copy Markdown
Collaborator

Summary

Formalises the release-cut branch model (sometimes called gitflow-lite) that the framework repo has been operating under informally since the start of this hooks-wave. dev is daily-work; main only receives release PRs from dev; each release-PR merge tags a semver. Adopters' /update skill pulls upstream/main, which is now strictly release-only — no more WIP commits leaking to forks.

Framework-only. This pattern is for me2resh/apexyard itself. Managed projects under apexyard governance (entries in apexyard.projects.yaml) stay trunk-based — they have no downstream consumers and don't need the ceremony. Both CLAUDE.md and docs/multi-project.md call this out explicitly so the pattern doesn't cargo-cult into project templates.

Added:

  • AgDR-0007 — decision record with the options table (full git flow vs trunk-only vs gitflow-lite — chose gitflow-lite)
  • /release skill at .claude/skills/release/SKILL.md — diffs dev against main, proposes a semver bump from conventional-commit types, generates a CHANGELOG draft, opens the release PR, tags + pushes after merge
  • docs/release-process.md — prose runbook (the skill is the automation; the doc is the manual fallback + conceptual reference)
  • .git.protected_branches in project-config.defaults.json (default [main, master, dev, develop])

Modified:

  • block-main-push.sh — extended to block direct pushes/commits to ALL protected branches, not just main/master. Reads the list from project config via the shared reader ([Chore] Make ticket-prefix whitelist + schema project-configurable (not hardcoded) #109). Forks that legitimately use dev as a working trunk under their own convention can override.
  • CLAUDE.md — new "Branch model — framework only" subsection under Git Conventions. /release added to the skills table.
  • docs/multi-project.md — note in the "Upgrades" section that upstream/main is release-only as of v1.2.0 + reminder that the split applies to apexyard itself, not to managed projects.

Testing

No automated tests (the /release skill is a markdown spec; block-main-push.sh extension is verified by tracing the regex against the protected list).

Manual smoke:

# Hook respects the new protected list
echo '{"tool_input":{"command":"git push origin dev"}}' | bash .claude/hooks/block-main-push.sh
# → exit 2, "Cannot push directly to a protected branch"

# Hook still blocks main
echo '{"tool_input":{"command":"git push origin main"}}' | bash .claude/hooks/block-main-push.sh
# → exit 2

# Feature-branch push still allowed
echo '{"tool_input":{"command":"git push origin chore/GH-116-foo"}}' | bash .claude/hooks/block-main-push.sh
# → exit 0

The first real /release invocation will be the v1.2.0 cut — at that point we'll dogfood the skill end-to-end and any rough edges show up there.

Scope — what this does NOT do

Branch protection (manual GitHub setting)

For maintainers of me2resh/apexyard, configure GitHub branch protection on main per docs/release-process.md § Branch protection:

  • Require pull request before merging
  • Require approvals: 1
  • Require all status checks to pass
  • (Optional) Restrict who can push (admins only, for the rare manual tag-fix case)

This is documentation-only here — the actual GitHub setting is a one-time admin action.

Glossary

Term Definition
Release-cut model Two-branch (dev + main) + tags. Daily work on dev, releases on main. Sometimes called "gitflow-lite".
Framework-only This pattern applies to me2resh/apexyard itself, NOT to managed projects under governance.
Protected branch A branch where direct pushes and commits are blocked by block-main-push.sh. Default list is configurable.
Release PR A dev → main PR that, when merged, becomes the source for a new semver tag. Body uses the <!-- multi-close: approved --> skip marker because it legitimately closes many tickets.

Closes #116

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants