Closes the user's ask: versioning + a changelog generated on merging
to main, building on the just-mandated Conventional Commits substrate
(CLAUDE.md Key Conventions).
Architecture: ADR-021. Cookbook: docs/guides/releasing.md.
Initial state — six tracked packages at v0.1.0:
- . -> template-vertical (tag: template-v...)
- packages/auth -> @repo/auth (tag: auth-v...)
- packages/blog -> @repo/blog (tag: blog-v...)
- packages/media -> @repo/media (tag: media-v...)
- packages/marketing-pages -> @repo/marketing-pages (tag: marketing-pages-v...)
- packages/navigation -> @repo/navigation (tag: navigation-v...)
Core packages, tooling, and apps are NOT independently versioned
(ADR-021 rationale: core bumps cascade; apps aren't consumables;
surfacing them would create noise without information).
Configuration:
- release-please-config.json - 6 tracked packages, hybrid scope,
pre-1.0 conservative bump policy
(feat: -> patch, feat!: -> minor),
conventional-commit type mapping
- .release-please-manifest.json - baseline 0.1.0 for all 6 packages
- .github/workflows/release-please.yml - googleapis/release-please-
action@v4 on push to main,
concurrency-gated, write
permissions for the rolling PR
Workflow: on every push to main, release-please scans commits since
the last release tag PER PACKAGE (using commit-path, not the
conventional-commit scope), updates a single rolling release PR with
version bumps + per-package CHANGELOG entries. Merging that PR cuts
per-package tags + GitHub releases.
CHANGELOG files seeded at v0.1.0 baseline:
- CHANGELOG.md (root)
- packages/<feature>/CHANGELOG.md (5 features)
Subsequent versions are appended by release-please from commit
history. Do not edit manually.
Visibility surfaces updated (every agent entry point):
- CLAUDE.md Read First + new "Versioning is hybrid" Key Conventions
bullet (with bump policy summary)
- AGENTS.md preamble - new "Releases:" callout alongside Commits
- docs/glossary.md - new Releasing section with 8 terms (Conventional
Commits, release-please, Hybrid versioning, Tag prefix, Rolling
release PR, Bump targeting, Pre-1.0 bump policy, Release-As trailer,
CHANGELOG.md)
- docs/README.md - guides tree updated with releasing.md
- .claude/hooks/session-start.sh - one-line release reminder
- .claude/hooks/prompt-context.sh - new keyword group for
release/version/bump/semver/tag prompts
Package.json version bumps:
- root: name "template" -> "template-vertical", version "0.1.0"
- packages/auth, blog, media, marketing-pages, navigation: "0.0.0" -> "0.1.0"
Root rename rationale: release-please tags use the package-name + the
component prefix; "template-vertical" matches the repo identity (and
the user's question preview).
First release-please PR after this lands will sweep all subsequent
post-baseline commits into 0.1.1 / 0.2.0 bumps as appropriate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
151 lines
6.7 KiB
Markdown
151 lines
6.7 KiB
Markdown
# Releasing
|
|
|
|
> **Architecture:** [ADR-021](../decisions/adr-021-versioning-and-changelog.md). **Convention:** [Conventional Commits](https://www.conventionalcommits.org/) — see `CLAUDE.md` Key Conventions.
|
|
|
|
This template uses [release-please](https://github.com/googleapis/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
|
|
|
|
```bash
|
|
# 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](https://github.com/googleapis/release-please/blob/main/docs/manifest-releaser.md#release-as-vs-release-as)).
|
|
|
|
### "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
|
|
|
|
```bash
|
|
# 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](../decisions/adr-021-versioning-and-changelog.md) — the architecture + design rationale
|
|
- [Conventional Commits spec](https://www.conventionalcommits.org/)
|
|
- [release-please docs](https://github.com/googleapis/release-please)
|
|
- `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
|