Files
agentic-dev/docs/guides/releasing.md
Danijel Martinek f77e6ea881 chore(template): clean-slate template snapshot from bb4a0c7
Curated, product-agnostic snapshot of the post-story-04 tree: demo
content deleted, auth-only reference feature, web-next shell, all gates
green. Product-specific docs, ADRs 027-029, PRDs/epics/archive, editor
library traces, and product naming are curated out; generic template
repairs (coverage provider devDeps, root test:coverage script, live
lint fixes, root-only release-please) are kept. See TEMPLATE.md for
provenance, curation list, and usage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 20:40:54 +02:00

6.7 KiB

Releasing

Architecture: ADR-021. Convention: Conventional Commits — see CLAUDE.md Key Conventions.

This template uses release-please to derive versions + changelog entries from Conventional Commits. On every push to main, release-please updates a rolling release PR. Merging that PR cuts tags + GitHub releases.

The six tracked packages

Path Package Tag prefix Initial version
. template-vertical (root template) template-v... 0.1.0
packages/auth @repo/auth auth-v... 0.1.0
packages/blog @repo/blog blog-v... 0.1.0
packages/media @repo/media media-v... 0.1.0
packages/marketing-pages @repo/marketing-pages marketing-pages-v... 0.1.0
packages/navigation @repo/navigation navigation-v... 0.1.0

Core packages, tooling packages, and apps are intentionally NOT versioned (ADR-021).

How a commit lands in a release

  1. Author the commit per Conventional Commits: <type>(<scope>): <imperative subject>.
  2. Push / merge to main.
  3. release-please's GH Action runs: scans commits since the last tag, groups by tracked package (using commit-path, not the conventional-commit scope), and updates the rolling release PR.
  4. When you (or a reviewer) merge the release PR, tags are cut + GitHub releases are created.

Bump targeting

release-please looks at the files changed in each commit, not the commit's (scope):

  • A commit touching packages/auth/** → bumps @repo/auth.
  • A commit touching docs/**, scripts/**, .github/**, root config files → bumps the root template (template-v...).
  • A commit touching packages/auth/** + docs/** → bumps BOTH.
  • A commit touching ONLY packages/core-shared/** → bumps the root template (core packages aren't independently versioned).

The conventional-commit (scope) parenthetical is for human readability in the changelog — it doesn't drive routing.

Pre-1.0 bump policy

While each package is <1.0.0:

Commit Bump
feat: patch
fix: patch
feat!: or BREAKING CHANGE: footer minor
perf: patch
refactor: patch
docs: patch
revert: patch
chore, ci, build, style, test none

When a package crosses 1.0.0, standard semver kicks in: feat: → minor, feat!: → major.

Day-to-day commands

# Inspect current versions
cat .release-please-manifest.json
node -e "console.log(JSON.parse(require('fs').readFileSync('package.json','utf8')).version)"
git tag --list 'template-v*' --sort=-version:refname | head -5
git tag --list 'auth-v*' --sort=-version:refname | head -5

# See what changed in a feature since a tag
git log auth-v0.1.0..HEAD -- packages/auth/

# View a tag's changelog entry
git show <tag>:CHANGELOG.md   # root
git show <tag>:packages/auth/CHANGELOG.md   # feature

Common scenarios

"I want to ship the open release PR right now"

Merge it. The Action cuts tags + creates GitHub releases for each affected package.

"The release PR's grouping looks wrong"

It's reproducible from commits — you can't directly edit. Either:

  • (a) Land a follow-up commit and let release-please regenerate, OR
  • (b) Close the PR, push the missing/fixing commits, release-please will reopen with the new state.

"I want to bypass a bump for a specific commit"

Use chore: / ci: / build: / style: / test: — those types are configured as hidden + non-bumping. Or extend the commit body with the manual override directive (see release-please release-as: footer).

"I want a manual bump to a specific version"

Add this trailer to your commit body:

Release-As: 0.5.0

release-please will honor it for the package whose path the commit touches.

"I want to skip releasing entirely for one merge"

Add [skip release-please] to the commit subject. The Action will still run but produce no PR changes.

"I need to mark a package as breaking-changes-allowed-pre-1.0"

By default the pre-1.0 policy treats feat!: as a minor bump (not major). That's typically what you want — pre-1.0 means the surface can change. If you genuinely want to start signalling stability earlier, edit bump-patch-for-minor-pre-major: false in release-please-config.json. Restart from a fresh major when crossing 1.0.

"Where do I see the per-package CHANGELOG?"

  • Root template: CHANGELOG.md at the repo root
  • Per-feature: packages/<feature>/CHANGELOG.md

Don't edit these manually — release-please regenerates them. The exception is the initial 0.1.0 baseline content, which was hand-seeded.

Cutting a 1.0.0 release

The Conventional Commits pre-1.0 policy says feat!: bumps minor. To explicitly cross 1.0:

feat!: cross 1.0 stability boundary

Release-As: 1.0.0

The Release-As: trailer overrides the auto-derived bump. From 1.0.0 onward, feat: → minor and feat!: → major per standard semver.

Verifying release-please locally

# Install once
pnpm dlx release-please --help

# Dry-run the manifest workflow
pnpm dlx release-please manifest-pr \
  --token "$GITHUB_TOKEN" \
  --repo-url "$(git remote get-url origin)" \
  --config-file release-please-config.json \
  --manifest-file .release-please-manifest.json \
  --dry-run

(The CI workflow itself does this on every push to main; local dry-runs are mostly for debugging config changes.)

Cross-references

  • ADR-021 — the architecture + design rationale
  • Conventional Commits spec
  • release-please docs
  • release-please-config.json — package list + section mapping + bump policy
  • .release-please-manifest.json — current version per tracked package
  • .github/workflows/release-please.yml — CI wiring