feat(release): make release tooling + versioning ritual (WHYNOT-WP-0003 T01)
- scripts/release.mjs + `make release VERSION=x.y.z`: guarded release cut — bumps package.json, relabels CHANGELOG [Unreleased] → [x.y.z], commits, and creates the annotated git tag. Refuses on dirty tree, existing tag, duplicate section, or empty [Unreleased]. Never pushes (outward step stays manual). - DesignSystemIntroduction.md §6: document the release ritual; §9: fix the stale bootstrap host + tag note. - README: bump the install pin to the first real tag (v0.3.0). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -286,6 +286,27 @@ Stay in `0.x.x` until something built with this system is in production. While i
|
||||
|
||||
Promotion past `1.0.0` should appear in `whynot-control/DECISIONS.md`. Same rule as promotion to Helix or Coulomb: it's a deliberate act, not a release-script side-effect.
|
||||
|
||||
### Release ritual
|
||||
|
||||
A release is a **git tag** (`vX.Y.Z`) — the immutable anchor a consuming repo pins
|
||||
(`pnpm add …#vX.Y.Z`, or the published package version). Tags are cut from
|
||||
`CHANGELOG.md`'s running `[Unreleased]` section:
|
||||
|
||||
1. Land all the work for the release on `main`, each change adding a `CHANGELOG.md`
|
||||
`[Unreleased]` entry (the `pnpm check` gate enforces this).
|
||||
2. Pick the bump per the table above (`patch`/`minor`/`major`).
|
||||
3. Run **`make release VERSION=x.y.z`** (`scripts/release.mjs`). It:
|
||||
- guards — refuses if the tree is dirty, if `vx.y.z` is already tagged, if a
|
||||
`[x.y.z]` section already exists, or if `[Unreleased]` is empty;
|
||||
- bumps `package.json`, relabels `[Unreleased]` → `[x.y.z] — <date>` and opens a
|
||||
fresh empty `[Unreleased]`;
|
||||
- commits `release: vx.y.z` and creates the annotated tag.
|
||||
4. `git push --follow-tags origin main`.
|
||||
5. Publish the package (see WHYNOT-WP-0003 T02) so consumers can `npm i` the version.
|
||||
|
||||
The script never half-applies and never pushes — pushing the tag is the one explicit,
|
||||
outward step you take by hand.
|
||||
|
||||
---
|
||||
|
||||
## 7. Where Claude fits
|
||||
@@ -324,8 +345,8 @@ This staging is exactly the *"low-cost learning first"* posture in `whynot-contr
|
||||
|
||||
For whoever is bootstrapping this repo right now:
|
||||
|
||||
- [ ] Push the seed contents to `gitea.example.com/whynot/whynot-design`.
|
||||
- [ ] Tag `v0.2.0` immediately so consumers can pin.
|
||||
- [ ] Push the seed contents to `gitea.coulomb.social/coulomb/whynot-design`.
|
||||
- [ ] Cut the first real tag with `make release VERSION=x.y.z` (see §6 — *Release ritual*) so consumers can pin.
|
||||
- [ ] Add the repo as a remote dependency in **one** consuming app (the Django one) and verify imports work end-to-end. Follow [`MultiFrameworkSupport.md` §Django](./MultiFrameworkSupport.md#django-server-rendered-templates--htmx).
|
||||
- [ ] Open one trivial PR against `whynot-design` (e.g. a CHANGELOG typo) to confirm CI passes end-to-end.
|
||||
- [ ] Record this bootstrap in `whynot-control/DECISIONS.md` as DEC-004 — *"Established whynot-design as the implementation surface, three-layer architecture, Lit web components as the canonical component layer."*
|
||||
|
||||
Reference in New Issue
Block a user