snapshot of c000b74a5b09c433f96a69fa102c5c8f6583dff0 Annotations about the code that implements koment.

docs/guides/release-koment.md

1 # Cutting a release
2
3 **This procedure is mandatory. Follow it in order. Do not improvise a release.**
4
5 A release publishes signed artifacts to GitHub, GHCR, the MCP Registry, the VS
6 Code Marketplace and Open VSX. Marketplace versions are permanent: a version
7 number cannot be reused, replaced or withdrawn. A mistake here is not
8 recoverable by editing a file, so every step below exists because skipping it
9 produces something a user installs and cannot undo.
10
11 Agents may prepare steps 0–3, perform the read-only verification in step 6 and
12 prepare the development-pin change in step 8. **Steps 4, 5 and 7 change the
13 outside world and require explicit human approval in the conversation.**
14
15 ---
16
17 ## 0. Preconditions
18
19 Verify all of these before starting. If any fails, stop and report it.
20
21 Before a release that promises Zed registry support, verify that
22 `integrations/editors/zed/LICENSE` is the GPLv3 text and that the crate declares
23 `GPL-3.0-or-later`. Zed requires an accepted license inside an extension
24 subdirectory; `mise run layout-check` enforces both files as part of ADR 0145.
25
26 ```sh
27 mise run fmt-check && mise run vet && mise run tidy-check && mise run generate-check
28 mise run lint && mise run test
29 mise run annotations && mise run comments && mise run agent-policy
30 mise run workflow-lint && mise run release-helper-test
31 mise run helm-lint && mise run helm-template && mise run vulncheck
32 mise run extension-test && mise run layout-check
33 mise --cd integrations/editors/zed run check
34 mise --cd integrations/editors/zed run build
35 ```
36
37 All eighteen must pass. `koment check` failing means a release would ship
38 annotations that no longer describe the code.
39
40 The read-only publication verification in step 6 also needs authenticated
41 `gh`, a current supported `cosign`, `curl`, `docker` with Buildx, `helm`, `npm`
42 and `sha256sum` on `PATH`:
43
44 ```sh
45 for command in gh cosign curl docker helm npm sha256sum; do command -v "$command"; done
46 gh auth status
47 ```
48
49 `main` is protected by a ruleset — pull request required, signed commits,
50 linear history, and one required status check: **`ci`**. That is the
51 aggregating job in `.github/workflows/ci.yml`; it depends on every gating job,
52 so adding a gating job to CI does not require a ruleset edit. The setup-action
53 and Windows archive jobs are advisory because they test the last published
54 release rather than the pull request. `cla`, `codeql` and `scorecard` also
55 report separately, and `cla` cannot be required because a release pull request
56 opened by `GITHUB_TOKEN` never gets a `cla` run. The classic
57 branch-protection API returns 404 for this repository; that means the rules
58 live in a ruleset, not that the branch is unprotected. Check with:
59
60 ```sh
61 gh api repos/koment-dev/koment/rulesets
62 ```
63
64 ## 1. Land the work
65
66 Merge every change through a pull request with a conventional subject. The
67 subject decides the version, so it is a release decision, not a formatting one:
68
69 | Subject | Effect |
70 |---|---|
71 | `feat:` | minor bump — 1.0.0 → 1.1.0 |
72 | `fix:`, `perf:`, `refactor:` | patch bump |
73 | `docs:`, `test:`, `build:`, `ci:` | patch bump, listed in the changelog |
74 | `chore:` | no release on its own |
75 | any `!` or `BREAKING CHANGE:` | major bump — 1.4.2 → 2.0.0 |
76
77 `bump-minor-pre-major` was turned off when 1.0.0 shipped (ADR 0120), so a `!`
78 is a major version and not a quiet minor one. Before writing `!`, check whether
79 the change is breaking at all: a claim of backward compatibility needs a
80 migration the binary performs or an ADR naming the version the old shape was
81 cut off at. Without either, it is breaking, and the subject has to say so.
82
83 ## 2. Let release-please open the release pull request
84
85 Pushing to `main` runs the `release` workflow, whose first job opens or updates
86 a pull request titled `chore(release): <version>`. It edits the changelog, the
87 manifest, and every file that carries the version:
88
89 - `.release-please-manifest.json`
90 - `distribution/helm/koment/Chart.yaml`
91 - `integrations/editors/vscode/package.json`
92 - `integrations/editors/vscode/package-lock.json`
93 - `integrations/editors/zed/extension.toml`
94 - `integrations/agent-plugins/claude/.claude-plugin/plugin.json`
95 - `integrations/agent-plugins/hermes/plugin.yaml`
96 - `integrations/agent-plugins/opencode/plugin.json`
97 - `integrations/agent-plugins/opencode/package.json`
98 - `server.json` — the top-level `.version`; OCI packages are versioned by tag
99
100 Do not edit these by hand and do not bump a version in a feature branch.
101 The package-manager parity tests fail the build when they disagree.
102
103 ## 3. Unblock that pull request's checks
104
105 **Expect its CI to sit at `action_required` with a 0s duration.** GitHub does
106 not run workflows for events created by `GITHUB_TOKEN`, so the required checks
107 never start and the pull request cannot merge on its own. This is normal and is
108 not a failure.
109
110 ```sh
111 gh run list --branch release-please--branches--main --limit 5
112 gh api -X POST repos/koment-dev/koment/actions/runs/<run-id>/approve
113 ```
114
115 Then wait for `commit-lint`, `container`, `editor`, `helm`, `lint`, `plugins`,
116 `quality`, `test` and `zed` to pass and for the aggregate `ci` job to pass.
117 Never merge a release pull request whose checks did not run—an unapproved run
118 is not a passing run. Quote `gh pr checks <number>` before asking to merge.
119
120 ## 4. Merge the release pull request — human approval required
121
122 Merging tags the release and starts publication. Everything after this point is
123 public and permanent.
124
125 Before merging, confirm:
126
127 - the version in the title is the one you intend;
128 - the changelog describes real changes;
129 - `ci` is green and not skipped, and every job it aggregates ran.
130
131 ## 5. Watch publication — human approval required to retry anything
132
133 Merging runs the rest of the `release` workflow in this order. The order is a
134 decision, not an accident (ADR 0109): canonical artifacts first, downstream
135 channels second.
136
137 ```
138 please ──┬─> binaries ──┬─> editor
139 │ ├─> tap
140 │ └─> verify ──> alias
141 └─> image
142
143 binaries + image ──┬─> plugins
144 ├─> mcp-registry
145 └─> chart
146 ```
147
148 | Job | Publishes |
149 |---|---|
150 | `binaries` | six archives, `koment_<version>_checksums.txt`, a cosign signature, and rendered Homebrew/Scoop/WinGet metadata |
151 | `plugins` | Four self-contained plugin archives (Claude, Codex, Hermes and OpenCode), per-archive cosign signatures, a combined `koment-plugins_<version>_checksums.txt`, and its cosign signature; the OpenCode package also goes to npm |
152 | `image` | `ghcr.io/koment-dev/koment:<version>`, multi-arch, SBOM and provenance, cosign-signed |
153 | `editor` | seven VSIX — six carrying that platform's released binary, one universal — signed, attached, then pushed to both marketplaces |
154 | `tap` | the rendered formula in `koment-dev/homebrew-tap` after the binary assets exist |
155 | `verify` | installs the new GitHub release through this repository's setup Action on Linux and macOS |
156 | `alias` | moves the floating major tag only after both setup-Action verification jobs pass |
157 | — | the Zed extension is **not** built or attached by the release. Zed builds it from the submodule, so step 7 publishes it by hand |
158 | `mcp-registry` | MCP Registry metadata via GitHub OIDC |
159 | `chart` | `oci://ghcr.io/koment-dev/charts/koment`, cosign-signed |
160
161 `plugins` waits for both `binaries` and `image`. Its source archives do not
162 consume either artifact, but ADRs 0109 and 0129 require canonical artifacts to
163 exist before a downstream npm package or agent integration is published.
164 The chart and MCP Registry metadata use the same gate so a missing GitHub
165 release asset cannot leave them as the only completed distribution channels.
166
167 ```sh
168 gh run watch "$(gh run list --workflow=release --limit 1 --json databaseId --jq '.[0].databaseId')"
169 ```
170
171 If `binaries` fails, `editor` does not run. That is deliberate: the extension
172 bundles the released binary, so an extension built without one would ship
173 something that was never signed (ADR 0113).
174
175 ## 6. Verify the release, do not assume it
176
177 ```sh
178 tag=v<version>
179 gh release view "$tag" --json assets --jq '.assets[].name' | sort
180 curl -fsSLI -o /dev/null -w '%{http_code}\n' "https://open-vsx.org/api/koment/koment-dev"
181 curl -fsSLI -o /dev/null -w '%{http_code}\n' "https://marketplace.visualstudio.com/items?itemName=koment.koment-dev"
182 ```
183
184 Expect six platform archives, the WinGet submission bundle, the binary checksum
185 manifest and its signature, rendered Homebrew and Scoop metadata, three plugin
186 archives and their three signatures, the plugin checksum manifest and its
187 signature, the chart and its signature, and seven VSIX files with seven
188 signatures. A release missing the archives breaks
189 every workflow using `koment-dev/koment@v<version>`, because the setup action
190 downloads them.
191
192 Download and verify the immutable assets rather than relying on their names:
193
194 ```sh
195 mkdir "koment-release-<version>"
196 cd "koment-release-<version>"
197 gh release download "$tag" --repo koment-dev/koment
198 sha256sum --check "koment_<version>_checksums.txt"
199 sha256sum --check "koment-plugins_<version>_checksums.txt"
200 certificate_identity="https://github.com/koment-dev/koment/.github/workflows/release.yml@refs/heads/main"
201 certificate_issuer="https://token.actions.githubusercontent.com"
202 cosign verify-blob \
203 --bundle "koment_<version>_checksums.sigstore.json" \
204 --certificate-identity "$certificate_identity" \
205 --certificate-oidc-issuer "$certificate_issuer" \
206 "koment_<version>_checksums.txt"
207 cosign verify-blob \
208 --bundle "koment-plugins_<version>_checksums.sigstore.json" \
209 --certificate-identity "$certificate_identity" \
210 --certificate-oidc-issuer "$certificate_issuer" \
211 "koment-plugins_<version>_checksums.txt"
212 for artifact in koment-plugin-*.tar.gz koment-vscode_*.vsix koment-<version>.tgz; do
213 cosign verify-blob \
214 --bundle "${artifact}.sigstore.json" \
215 --certificate-identity "$certificate_identity" \
216 --certificate-oidc-issuer "$certificate_issuer" \
217 "$artifact"
218 done
219 npm view "@koment/opencode-koment@<version>" version
220 cosign verify \
221 --certificate-identity "$certificate_identity" \
222 --certificate-oidc-issuer "$certificate_issuer" \
223 "ghcr.io/koment-dev/koment:<version>"
224 cosign verify \
225 --certificate-identity "$certificate_identity" \
226 --certificate-oidc-issuer "$certificate_issuer" \
227 "ghcr.io/koment-dev/charts/koment:<version>"
228 docker buildx imagetools inspect "ghcr.io/koment-dev/koment:<version>"
229 helm show chart "oci://ghcr.io/koment-dev/charts/koment" --version "<version>"
230 curl -fsSL "https://raw.githubusercontent.com/koment-dev/homebrew-tap/main/Formula/koment.rb" \
231 | grep -F 'version "<version>"'
232 ```
233
234 Run these in a new temporary directory and remove it after recording the real
235 output. Do not run `gh release download` into the repository checkout.
236
237 ## 7. Publish the Zed extension — human approval required
238
239 Zed's registry is not driven by this repository's release workflow. It builds the
240 extension from a git submodule, so publishing is a pull request in another
241 organisation's repository and a person opens it (ADR 0139).
242
243 Do not start this step until the GPLv3 boundary required by step 0 passes the
244 local layout check.
245
246 Nothing else in this procedure waits on it, and the release is not fully
247 published until it merges.
248
249 1. Fork or update your fork of `zed-industries/extensions`.
250 2. Point the `koment` submodule at the release tag, and set the version in the
251 top-level `extensions.toml` to the version just released:
252
253 ```toml
254 [koment]
255 submodule = "extensions/koment"
256 path = "integrations/editors/zed"
257 version = "<version>"
258 ```
259
260 3. Run `pnpm sort-extensions` so `extensions.toml` and `.gitmodules` stay
261 sorted. A pull request that skips this is rejected.
262 4. Open the pull request. The submodule commit must be reachable on a branch,
263 not detached, and the submodule URL must be HTTPS rather than SSH.
264
265 On the first publication the entry and the submodule are both new; afterwards
266 only the submodule commit and the `version` field change.
267
268 Verify after it merges:
269
270 ```sh
271 curl -fsSLI -o /dev/null -w '%{http_code}\n' "https://zed.dev/extensions/koment"
272 ```
273
274 ## 8. Bump the development pin
275
276 `.mise/config.toml` pins `github:koment-dev/koment` to a released version, which is
277 the `koment` a contributor gets in their shell. It is not what any gate runs —
278 every `mise run` task uses `go run ./cmd/koment` — so it lags a release rather
279 than blocking one. It still has to be caught up, because a pinned binary older
280 than the record shape in `.koment/` cannot read this repository at all.
281
282 ```sh
283 mise use "github:koment-dev/koment@<version>"
284 mise run annotations
285 ```
286
287 Land it as `chore:`, which release-please does not turn into a release of its
288 own.
289
290 ---
291
292 ## When something goes wrong
293
294 **Never delete a tag or a published release to "redo" it.** Republish nothing.
295 Cut the next patch version instead. A tag that once existed has been fetched by
296 someone.
297
298 | Symptom | Cause | Action |
299 |---|---|---|
300 | release pull request checks show `action_required`, 0s | `GITHUB_TOKEN` created the pull request | approve the run (step 3) |
301 | release asset upload returns an HTTP error | the create-release response or publishing token cannot upload to its exact asset endpoint | do not rerun a published registry version; inspect the response, fix the cause, and cut the next patch |
302 | `editor` job skipped | `binaries` failed | fix the binaries, cut a new patch version |
303 | `ovsx publish` fails on the first ever publish | the namespace did not exist | the workflow now creates it; if it still fails, the token lacks the Publisher Agreement |
304 | `vsce publish` rejects the version | that version already exists on the marketplace | cut the next version, never reuse one |
305 | a marketplace publish times out after earlier packages succeeded | the service response is ambiguous and the version may be partial | do not rerun a historical workflow or publish by hand; current releases retry each package three times with `--skip-duplicate`, and an exhausted or older run recovers in the next patch (ADR 0150) |
306 | `Windows Archive (advisory)` is red | advisory by decision (ADR 0111) | it does not block; read it and file a task |
307 | version files disagree | someone hand-edited one | revert the edit, let release-please own them |
308
309 ## What an agent must never do
310
311 - Publish a VSIX, image, chart or binary by hand, outside this workflow.
312 ADR 0112 rejected out-of-band publishing: a marketplace would carry a version
313 the release never produced.
314 - Hand-edit any version-bearing file listed in step 2.
315 - Merge a release pull request whose checks did not run.
316 - Delete, move or re-point a tag, or force-push `main`.
317 - Re-run a publish job hoping it works the second time, without first
318 establishing why it failed.
319 - Claim a release succeeded without running step 6 and quoting its output.

Find an annotation

Search file paths, rationale, kinds, and authors.

moveEnter openEsc close