diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e327f4..29d52aa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,6 +95,6 @@ This is why every test in the suite pairs an `expectTypeOf(...)` with an `assert Publishing is CI-only by policy. Local `npm publish` is not supported. The maintainer triggers releases from `main`: 1. All intended changes are merged to `main` and passing CI. -2. The maintainer runs `npm run create:release` — an interactive prompt suggests a version (based on the latest CHANGELOG entry); the maintainer confirms or edits it. -3. `scripts/release.sh` creates a single release commit (changelog + package.json bump, amended into one commit), tags it, and pushes everything to Gitea. +2. The maintainer runs `npm run create:release`. VS Code opens `CHANGELOG.md` to finalize the `[Unreleased]` notes; because pubv refuses a dirty tree, any edit is committed first (then folded into the release commit), and pubv's interactive prompt suggests a version from those notes — the maintainer confirms or edits it. +3. `scripts/release.sh` creates a single release commit (graduated changelog + package.json bump, amended into one commit), tags it, and pushes everything to Gitea. 4. CI runs on the push (the `build` and `maintain` jobs); the `publish` job then fires on the tag, consuming the `dist/` artifact the `build` job produced. The job graph lives in [.gitea/workflows/ci.yml](./.gitea/workflows/ci.yml) — keep that file, not this list, as the source of truth. The publish-tier checks must pass before the artifact is published. The `publish` job also creates the Gitea release page from the matching Keep-a-Changelog section (`scripts/release-notes.sh`); it runs _before_ `npm publish` so a broken page fails CI without consuming a version, and `npm publish` stays the last step. diff --git a/scripts/release.sh b/scripts/release.sh index 9d45cb0..0649ec0 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -13,6 +13,12 @@ set -eu # package.json + the lockfile; `--amend` folds them into pubv's single commit; # tag AFTER the amend (so the tag is never orphaned) and push. # +# The notes are finalized in VS Code *before* pubv: the [Unreleased] body is +# what pubv's bump heuristic reads, so editing afterwards would inform the +# changelog only, not the version choice. pubv refuses a dirty tree, so that +# edit is committed as a staging commit and folded back into the single release +# commit below. +# # Rejected: the conventional-commits family (our history is gitmoji, not # Conventional; and we want hand-written notes); changesets/rtk (config + a # heavier version/publish flow that fights our CI-only publish); knope/kacl/ @@ -52,12 +58,23 @@ if ! git remote set-head origin --auto >/dev/null 2>&1; then exit 1 fi +# The [Unreleased] body drives pubv's bump heuristic, so finalize it first. +echo "Opening ${CHANGELOG} in VS Code to finalize the release notes..." +code --wait "${CHANGELOG}" + +# pubv refuses a dirty tree (its "continue with a dirty tree?" prompt defaults +# to No), so a changed changelog must be committed before it runs. That commit +# is staging only — the fold below rewrites it into the single release commit. +NOTES_MSG=":memo: Finalize release notes" +if [ -n "$(git status --porcelain -- "${CHANGELOG}")" ]; then + echo "Committing finalized release notes..." + git add "${CHANGELOG}" + git commit -m "${NOTES_MSG}" +fi + echo "Running pubv..." pubv --no-tag --no-push --tag-prefix=none -echo "Opening ${CHANGELOG} in VS Code..." -code --wait "${CHANGELOG}" - echo "Reading version from ${CHANGELOG}..." VERSION=$( @@ -75,6 +92,14 @@ echo "Release version: ${VERSION}" echo "Updating package.json and package-lock.json..." npm version "${VERSION}" --no-git-tag-version +# If pubv's graduation commit sits on top of our staging notes commit, drop it +# back into the index so the amend below rewrites the notes commit into the one +# release commit. A message check, not a flag, so a re-run after pubv aborted +# still folds a notes commit left behind by the earlier attempt. +if [ "$(git log -1 --format=%s HEAD~1 2>/dev/null || true)" = "${NOTES_MSG}" ]; then + git reset --soft HEAD~1 +fi + echo "Amending release commit..." git add package.json package-lock.json "${CHANGELOG}" git commit --amend -m ":bookmark: Release ${VERSION}"