|
| 1 | +--- |
| 2 | +applyTo: 'VERSION,docs/release-notes.md,.github/workflows/release.yml,Makefile' |
| 3 | +--- |
| 4 | + |
| 5 | +# Release Instructions |
| 6 | + |
| 7 | +Releases are driven by `v*` git tags. Pushing a tag triggers |
| 8 | +`.github/workflows/release.yml`, which checks the tag against `VERSION`, builds |
| 9 | +and deploys `example/` as a smoke test, then extracts the matching `## vX.Y.Z` |
| 10 | +section from `docs/release-notes.md` and publishes it as the GitHub Release body |
| 11 | +(re-runs update the existing release instead of failing). Finally it moves the |
| 12 | +floating major tag (`v5` for a `v5.x.y` release) to the released commit, so |
| 13 | +consumers pinned to `@v5` pick the release up. |
| 14 | + |
| 15 | +## Cutting a release |
| 16 | + |
| 17 | +1. Bump `VERSION`. That is the single source of truth — the release workflow |
| 18 | + refuses to publish a tag that does not match it. Note this versions the |
| 19 | + *action*, not the `metablock` client it installs; the client pin lives in the |
| 20 | + `Dockerfile` and moves independently. |
| 21 | +2. Add a `## vX.Y.Z` section at the top of `docs/release-notes.md` with the |
| 22 | + notes for the release. The header text is matched verbatim by the workflow's |
| 23 | + `awk` extractor, so it must be `## vX.Y.Z` exactly (no trailing dash, no |
| 24 | + title after the version). The release workflow fails if this section is |
| 25 | + missing. |
| 26 | +3. Commit and merge to `main`; let the `build` workflow pass. |
| 27 | +4. From `main`, run `make release` — it reads `VERSION`, asks for confirmation, |
| 28 | + then creates an annotated `vX.Y.Z` tag and pushes it. The `release` workflow |
| 29 | + takes it from there. |
| 30 | + |
| 31 | +Do not move the major tag by hand — the workflow owns it, and a manual push |
| 32 | +will be overwritten by the next release. |
| 33 | + |
| 34 | +Note the smoke test deploys the example bundle through the live metablock API, |
| 35 | +so a release needs valid `METABLOCK_API_TOKEN` and `METABLOCK_ORG_ID` secrets |
| 36 | +and will fail if the API is down. |
| 37 | + |
| 38 | +## Release-notes conventions |
| 39 | + |
| 40 | +The `## vX.Y.Z` section in `docs/release-notes.md` is published verbatim as the |
| 41 | +GitHub Release body, so it must follow these conventions: |
| 42 | + |
| 43 | +- Open with a one-paragraph summary describing the theme of the release. If the |
| 44 | + release contains breaking changes, point readers to the **Breaking changes** |
| 45 | + section in that paragraph. A bump of the `metablock` client pin is worth |
| 46 | + naming in that paragraph, since it is what changes the action's behaviour. |
| 47 | +- Group entries under H3 subsections in this order: `### Breaking changes`, |
| 48 | + `### New features`, `### Improvements and fixes`, |
| 49 | + `### Documentation and assets`. Omit any subsection that has no entries. |
| 50 | +- Every PR reference must be a markdown link of the form |
| 51 | + `[#NN](https://github.com/quantmind/metablock-web/pull/NN)` — never a bare |
| 52 | + `(#NN)`. GitHub's auto-linking only works in some contexts, and the explicit |
| 53 | + URL works everywhere. When one entry references multiple PRs, list them |
| 54 | + comma-separated inside one set of parentheses, each as its own link. |
| 55 | +- Build the PR list by running `git log vPREV..HEAD --oneline` against the |
| 56 | + previous release tag and following each squashed-merge commit back to its PR. |
| 57 | + Cross-check with `gh pr list --state merged --base main` for any PRs merged |
| 58 | + since the previous tag. |
| 59 | +- End the section with a |
| 60 | + `[Full changelog](https://github.com/quantmind/metablock-web/compare/vPREV...vX.Y.Z)` |
| 61 | + link comparing the new tag against the previous one. |
0 commit comments