diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 9e86520..815aec4 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -5,7 +5,8 @@ name: Prepare release # a `release/vX.Y.Z` branch, stamps the version into the shipped package.json # files (lockstep: extension + gateway share one version), commits, and opens a # PR to main. Review + merge, then cut the release by tagging: -# git tag vX.Y.Z && git push origin vX.Y.Z # → release.yml publishes +# git tag -s vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z +# Sign with a key registered on GitHub so the release tag shows Verified. # # The release branch is a durable record of each cut (not just the tag). on: @@ -54,5 +55,5 @@ jobs: echo "" echo "1. **Open the PR:** [$URL]($URL)" echo "2. Review + merge it into \`main\`." - echo "3. Cut the release: \`git tag v$VERSION && git push origin v$VERSION\` → the Release workflow verifies the tag matches the committed version, then builds and publishes to the gated targets." + echo "3. On a machine with a GitHub-registered signing key, cut the release: \`git tag -s v$VERSION -m 'v$VERSION' && git push origin v$VERSION\` → the Release workflow verifies the tag matches the committed version, then builds and publishes to the gated targets." } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3194aa3..8dd2889 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ name: Release -# Fires on a version tag (e.g. `git tag v0.1.0 && git push origin v0.1.0`). +# Fires on a version tag (prefer `git tag -s v0.1.0 -m "v0.1.0"` for a Verified tag). # Builds + tests, then packages and PUBLISHES to the MVP targets: # • extension .vsix → GitHub Release (+ VS Code Marketplace when VSCE_PAT is set) # • gateway → GitHub Release tarball (+ npm when NPM_TOKEN is set) diff --git a/docs/05-roadmap-and-open-questions.md b/docs/05-roadmap-and-open-questions.md index ed1228c..93e6eeb 100644 --- a/docs/05-roadmap-and-open-questions.md +++ b/docs/05-roadmap-and-open-questions.md @@ -244,10 +244,13 @@ strings. A pre-release _extension_ lane (Microsoft's odd-minor convention / `vsc your own PR, so a solo maintainer merges the (mechanical, CI-green) release PR with **`gh pr merge --admin --merge`** — `enforce_admins` is deliberately off for exactly this. That is also why the release merges are merge commits despite `required_linear_history`. -3. Tag and push: `git tag vX.Y.Z && git push origin vX.Y.Z`. `release.yml` **verifies the tag matches - the committed version** (fails on drift), then builds → tests → packages the `.vsix` + gateway - tarball → GitHub Release (always) → gated Marketplace / npm / Docker publishes. Docker/tarball are - named from the tag; the `.vsix`/npm version come from `package.json`. +3. On a machine with a signing key registered with GitHub, update `main` after the merge, then + **sign and push** the tag: `git tag -s vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z`. + Confirm GitHub reports the tag as Verified; a Verified merge commit does **not** verify an + unsigned tag. `release.yml` **verifies the tag matches the committed version** (fails on drift), + then builds → tests → packages the `.vsix` + gateway tarball → GitHub Release (always) → gated + Marketplace / npm / Docker publishes. Docker/tarball are named from the tag; the `.vsix`/npm + version come from `package.json`. **If a publish step fails, re-run it — don't re-tag.** All the publishes are sequential steps of one job, so a flaky Marketplace (it fronts Azure DevOps and does go down; the failure surfaces as a raw `Azure DevOps Services Unavailable` HTML page in the log) takes npm and Docker with it. diff --git a/docs/06-field-notes.md b/docs/06-field-notes.md index 7ef792b..d767f84 100644 --- a/docs/06-field-notes.md +++ b/docs/06-field-notes.md @@ -108,6 +108,12 @@ Base: `~/.vscode-server/data/User/` ## Build, tooling & agent gotchas (durable — the committed home; `/memories/` is ephemeral) +- **Release tag verification (2026-09-30).** `v1.0.0` points to a Verified merge commit, but its + annotated tag itself reports `verification.reason=unsigned`, so the release tag has no Verified + badge. `git tag -a` alone does not sign. For future cuts, use `git tag -s vX.Y.Z -m "vX.Y.Z"` on + a machine with a GPG/SSH signing key registered on GitHub, then verify the tag's signature + status after pushing. Never replace a published release tag just to change its badge. + > Non-obvious traps that cost real time. This is the **committed** replacement for the assistant's > ephemeral `/memories/` store (a container rebuild wipes that). Add a bullet here whenever a > rediscovery would waste someone's time. diff --git a/scripts/release.mjs b/scripts/release.mjs index d9335ae..039b8f8 100644 --- a/scripts/release.mjs +++ b/scripts/release.mjs @@ -94,7 +94,9 @@ try { console.log( `\nNext:\n` + ` 1. Review + merge the release/v${version} PR it opens.\n` + - ` 2. git tag v${version} && git push origin v${version} → the Release workflow publishes.`, + ` 2. On a machine with a GitHub-registered signing key:\n` + + ` git tag -s v${version} -m "v${version}" && git push origin v${version}\n` + + ` → the Release workflow publishes.`, ); /** @returns {string} the committed root package.json version (fallback 0.0.0). */