From ac78060a15352b7a32e4e62871ecd1c7f0a419db Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 19 Aug 2026 01:01:38 +0800 Subject: [PATCH 1/7] chore: add bumpp and tag + GitHub Release to the release workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `pnpm bump` (bumpp) bumps packages/vscode/package.json and commits `chore(vscode): release vX.Y.Z`; no tag, no push — the release workflow tags the commit it actually published from. - release.yml gains a final job that, after every target published, pushes the `vX.Y.Z` tag (idempotent) and creates the GitHub Release through changelogithub with notes from the conventional commits since the previous tag and the six VSIX files attached. Skipped on dry runs. - Document the flow in CONTRIBUTING.md and point to it from AGENTS.md. --- .github/workflows/release.yml | 59 ++++++++++++++++++++++ AGENTS.md | 1 + CONTRIBUTING.md | 10 ++++ bump.config.ts | 21 ++++++++ package.json | 2 + pnpm-lock.yaml | 94 ++++++++++++++++++++++++++++++++++- 6 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 bump.config.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f74128f..18d4449 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,3 +100,62 @@ jobs: env: OVSX_PAT: ${{ secrets.OVSX_PAT }} run: pnpm exec ovsx publish --target ${{ matrix.vsce-target }} --skip-duplicate + + # ======== tag + GitHub Release, once, after every target published ======== + # Runs only for a real release: a dry run must leave no tag behind. The tag + # points at the commit that was actually published (github.sha), the release + # notes come from the conventional commits since the previous tag, and the + # six VSIX files are attached as assets so a release can be installed by hand + # (`code --install-extension`) without either marketplace. + github_release: + name: Tag and GitHub Release + needs: release_vscode_extension + if: ${{ !inputs.dry_run }} + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + # changelogithub needs the tags and history to find the previous + # release and list the commits since it. + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 22 + + - name: Download VSIX Artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: rstack-* + path: vsix + merge-multiple: true + + - name: Read Version + id: version + run: echo "tag=v$(node -p "require('./packages/vscode/package.json').version")" >> "$GITHUB_OUTPUT" + + # Idempotent: re-running a release (e.g. after one marketplace publish + # flaked and `--skip-duplicate` covered the rest) must not fail here. + - name: Push Tag + env: + TAG: ${{ steps.version.outputs.tag }} + run: | + if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null; then + echo "tag $TAG already exists, leaving it as is" + else + git tag "$TAG" "$GITHUB_SHA" + git push origin "refs/tags/$TAG" + fi + + - name: GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ steps.version.outputs.tag }} + run: | + ls -la vsix + npx changelogithub@15.0.4 --to "$TAG" --assets 'vsix/*.vsix' diff --git a/AGENTS.md b/AGENTS.md index 3debf2b..c7af58e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,6 +16,7 @@ Unified editor support for the [Rstack](https://rstack.rs) toolchain. pnpm works - If extension source changed, also run the E2E slice covering the change (see `packages/vscode/AGENTS.md`). E2E launches a real VS Code and is the ground truth for editor behavior — unit tests are not a substitute. - Never delete `packages/vscode/.vscode-test/` — it caches the VS Code download the E2E suites reuse. - Report real command results only; never claim green without running. +- Releases: `pnpm bump` on a branch → PR → merge → run the **Release** workflow on `main`. The workflow publishes to both marketplaces, tags `vX.Y.Z` and creates the GitHub Release; never tag or publish by hand. Details in CONTRIBUTING.md → Releasing. ## Agent skills diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 601a0ab..6ae4e25 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,3 +28,13 @@ To try the extension: press F5 in VS Code at the repo root — the playground la - The pre-commit hook formats and lints staged files (`rs staged`). - CI runs build, lint, format check, unit tests and the E2E suites on Linux and Windows — please run `pnpm lint && pnpm test:unit` locally before pushing. - Keep PRs focused; fill in the PR template. + +## Releasing + +The VS Code extension is the only versioned artifact; its version lives in `packages/vscode/package.json`. + +1. On a branch, run `pnpm bump` (interactive; or `pnpm bump --release minor`) — [bumpp](https://github.com/antfu-collective/bumpp) bumps the manifest and commits `chore(vscode): release vX.Y.Z`. It does not tag or push. +2. Open a PR with that commit and merge it into `main`. +3. Run the **Release** workflow (`Actions → Release → Run workflow`, branch `main`; `gh workflow run release.yml`). Tick **dry run** to only build the six VSIX artifacts. A real run publishes every platform target to the VS Code Marketplace and Open VSX, then tags `main` as `vX.Y.Z` and creates the GitHub Release with notes generated from the conventional commits since the previous tag and the VSIX files attached. + +Re-running a release is safe: both marketplaces skip an already-published version and the tag step leaves an existing tag alone. diff --git a/bump.config.ts b/bump.config.ts new file mode 100644 index 0000000..5c27222 --- /dev/null +++ b/bump.config.ts @@ -0,0 +1,21 @@ +import { readFileSync } from 'node:fs'; +import { defineConfig } from 'bumpp'; + +// The VS Code extension is the only versioned artifact in this repo: its +// manifest version is what the release workflow publishes and tags. The root +// package.json carries no version on purpose. +const manifest = new URL('./packages/vscode/package.json', import.meta.url); +const { version } = JSON.parse(readFileSync(manifest, 'utf8')) as { + version: string; +}; + +export default defineConfig({ + files: ['packages/vscode/package.json'], + currentVersion: version, + commit: 'chore(vscode): release v%s', + // Tagging and pushing belong to the release workflow, which tags the commit + // it actually published from. `pnpm bump` only prepares the release commit + // for a PR. + tag: false, + push: false, +}); diff --git a/package.json b/package.json index 0ad79dc..3226b23 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "type": "module", "scripts": { "build": "pnpm -r run build", + "bump": "bumpp", "fmt": "rs fmt", "fmt:check": "rs fmt --check", "lint": "rs lint --type-check", @@ -14,6 +15,7 @@ "test:unit": "pnpm -r run test:unit" }, "devDependencies": { + "bumpp": "^12.2.1", "rstack": "^0.3.2" }, "packageManager": "pnpm@11.20.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bfa8d0..3420133 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: devDependencies: + bumpp: + specifier: ^12.2.1 + version: 12.2.1 rstack: specifier: ^0.3.2 version: 0.3.2(jiti@2.7.0)(typescript@5.9.3) @@ -571,6 +574,9 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + '@rsbuild/core@2.1.9': resolution: {integrity: sha512-yqf1hFZ3wbMYI431LqsxLH3r0VZkfyarVKTf7kMeIiGe0YLwsrgsfp+sKpIyVkQkq60J0qyp6l/CoqqsQZqEwQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1065,6 +1071,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + args-tokenizer@0.3.0: + resolution: {integrity: sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1128,10 +1137,19 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + bumpp@12.2.1: + resolution: {integrity: sha512-8inGPx8PC/BaEOWhzfxrNHGj/x5Srt0EeJatAcTJ9N7AZpQG/HlH4kGp5JWbEL8zffYXI5iBkMjG8SHnJ9e/6g==} + engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} + hasBin: true + bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} + cac@7.0.0: + resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} + engines: {node: '>=20.19.0'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -1279,6 +1297,9 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -1876,6 +1897,9 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@1.8.0: + resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==} + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -1965,6 +1989,9 @@ packages: resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} engines: {node: '>=0.6'} + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2213,6 +2240,10 @@ packages: resolution: {integrity: sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==} engines: {node: '>=4'} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} + engines: {node: '>=18'} + tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} @@ -2258,6 +2289,12 @@ packages: uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + unconfig-core@7.5.0: + resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} + + unconfig@7.5.0: + resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} + underscore@1.13.8: resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==} @@ -2297,6 +2334,10 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + verkit@0.3.2: + resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} + engines: {node: '>=18.12.0'} + version-range@4.15.0: resolution: {integrity: sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==} engines: {node: '>=4'} @@ -2366,6 +2407,11 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -2848,6 +2894,10 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@quansync/fs@1.0.0': + dependencies: + quansync: 1.0.0 + '@rsbuild/core@2.1.9': dependencies: '@rspack/core': 2.1.7(@swc/helpers@0.5.23) @@ -3312,6 +3362,8 @@ snapshots: argparse@2.0.1: {} + args-tokenizer@0.3.0: {} + assertion-error@2.0.1: {} astral-regex@2.0.0: {} @@ -3371,10 +3423,24 @@ snapshots: ieee754: 1.2.1 optional: true + bumpp@12.2.1: + dependencies: + args-tokenizer: 0.3.0 + cac: 7.0.0 + jsonc-parser: 3.3.1 + package-manager-detector: 1.8.0 + tinyexec: 1.3.0 + tinyglobby: 0.2.17 + unconfig: 7.5.0 + verkit: 0.3.2 + yaml: 2.9.0 + bundle-name@4.1.0: dependencies: run-applescript: 7.1.0 + cac@7.0.0: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -3528,6 +3594,8 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + defu@6.1.7: {} + delayed-stream@1.0.0: {} detect-libc@2.1.2: @@ -3861,8 +3929,7 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jiti@2.7.0: - optional: true + jiti@2.7.0: {} js-tokens@4.0.0: {} @@ -4141,6 +4208,8 @@ snapshots: package-json-from-dist@1.0.1: {} + package-manager-detector@1.8.0: {} + pako@1.0.11: {} parse-json@8.3.0: @@ -4229,6 +4298,8 @@ snapshots: es-define-property: 1.0.1 side-channel: 1.1.1 + quansync@1.0.0: {} + queue-microtask@1.2.3: {} randombytes@2.1.0: @@ -4524,6 +4595,8 @@ snapshots: dependencies: editions: 6.22.0 + tinyexec@1.3.0: {} + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.5) @@ -4560,6 +4633,19 @@ snapshots: uc.micro@2.1.0: {} + unconfig-core@7.5.0: + dependencies: + '@quansync/fs': 1.0.0 + quansync: 1.0.0 + + unconfig@7.5.0: + dependencies: + '@quansync/fs': 1.0.0 + defu: 6.1.7 + jiti: 2.7.0 + quansync: 1.0.0 + unconfig-core: 7.5.0 + underscore@1.13.8: {} undici-types@6.21.0: {} @@ -4585,6 +4671,8 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + verkit@0.3.2: {} + version-range@4.15.0: {} vscode-jsonrpc@8.2.0: {} @@ -4650,6 +4738,8 @@ snapshots: yallist@4.0.0: {} + yaml@2.9.0: {} + yargs-parser@21.1.1: {} yargs-unparser@2.0.0: From f3e6fea013ac08743ef0967fdbf38c3e8d21c511 Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 19 Aug 2026 01:04:11 +0800 Subject: [PATCH 2/7] chore: bump commit message is the bare version, like storybook-rsbuild --- CONTRIBUTING.md | 2 +- bump.config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6ae4e25..68a63be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,7 +33,7 @@ To try the extension: press F5 in VS Code at the repo root — the playground la The VS Code extension is the only versioned artifact; its version lives in `packages/vscode/package.json`. -1. On a branch, run `pnpm bump` (interactive; or `pnpm bump --release minor`) — [bumpp](https://github.com/antfu-collective/bumpp) bumps the manifest and commits `chore(vscode): release vX.Y.Z`. It does not tag or push. +1. On a branch, run `pnpm bump` (interactive; or `pnpm bump --release minor`) — [bumpp](https://github.com/antfu-collective/bumpp) bumps the manifest and commits `vX.Y.Z`. It does not tag or push. 2. Open a PR with that commit and merge it into `main`. 3. Run the **Release** workflow (`Actions → Release → Run workflow`, branch `main`; `gh workflow run release.yml`). Tick **dry run** to only build the six VSIX artifacts. A real run publishes every platform target to the VS Code Marketplace and Open VSX, then tags `main` as `vX.Y.Z` and creates the GitHub Release with notes generated from the conventional commits since the previous tag and the VSIX files attached. diff --git a/bump.config.ts b/bump.config.ts index 5c27222..21c05fb 100644 --- a/bump.config.ts +++ b/bump.config.ts @@ -12,7 +12,7 @@ const { version } = JSON.parse(readFileSync(manifest, 'utf8')) as { export default defineConfig({ files: ['packages/vscode/package.json'], currentVersion: version, - commit: 'chore(vscode): release v%s', + commit: 'v%s', // Tagging and pushing belong to the release workflow, which tags the commit // it actually published from. `pnpm bump` only prepares the release commit // for a PR. From 64c77ed96ce2135554b7cb19d474e8a861de388d Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 19 Aug 2026 01:08:34 +0800 Subject: [PATCH 3/7] chore(vscode): reset the manifest version to 0.0.1 ahead of the first bump The first release lands through `pnpm bump` so main keeps an explicit `v0.1.0` bump commit. --- packages/vscode/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 66b5a5c..283ce3a 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -1,7 +1,7 @@ { "name": "rstack", "displayName": "Rstack", - "version": "0.1.0", + "version": "0.0.1", "private": true, "description": "All Rstack tool integrations for VS Code.", "categories": [ From 695fbe9007375a2a28a0a9639f1e290335979d9a Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 19 Aug 2026 01:12:19 +0800 Subject: [PATCH 4/7] chore: route pnpm bump through the vscode package Root scripts are pnpm -r fan-outs and must not reach into a package (AGENTS.md); bumpp and its config now live in packages/vscode and the root `bump` script is `pnpm -r run bump`. Verified the interactive prompt still gets a TTY through the fan-out for a single package. --- bump.config.ts | 21 --------------------- package.json | 3 +-- packages/vscode/bump.config.ts | 12 ++++++++++++ packages/vscode/package.json | 2 ++ pnpm-lock.yaml | 6 +++--- 5 files changed, 18 insertions(+), 26 deletions(-) delete mode 100644 bump.config.ts create mode 100644 packages/vscode/bump.config.ts diff --git a/bump.config.ts b/bump.config.ts deleted file mode 100644 index 21c05fb..0000000 --- a/bump.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { readFileSync } from 'node:fs'; -import { defineConfig } from 'bumpp'; - -// The VS Code extension is the only versioned artifact in this repo: its -// manifest version is what the release workflow publishes and tags. The root -// package.json carries no version on purpose. -const manifest = new URL('./packages/vscode/package.json', import.meta.url); -const { version } = JSON.parse(readFileSync(manifest, 'utf8')) as { - version: string; -}; - -export default defineConfig({ - files: ['packages/vscode/package.json'], - currentVersion: version, - commit: 'v%s', - // Tagging and pushing belong to the release workflow, which tags the commit - // it actually published from. `pnpm bump` only prepares the release commit - // for a PR. - tag: false, - push: false, -}); diff --git a/package.json b/package.json index 3226b23..53eb703 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "build": "pnpm -r run build", - "bump": "bumpp", + "bump": "pnpm -r run bump", "fmt": "rs fmt", "fmt:check": "rs fmt --check", "lint": "rs lint --type-check", @@ -15,7 +15,6 @@ "test:unit": "pnpm -r run test:unit" }, "devDependencies": { - "bumpp": "^12.2.1", "rstack": "^0.3.2" }, "packageManager": "pnpm@11.20.0", diff --git a/packages/vscode/bump.config.ts b/packages/vscode/bump.config.ts new file mode 100644 index 0000000..f33ac45 --- /dev/null +++ b/packages/vscode/bump.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'bumpp'; + +// Invoked through the root `pnpm bump` fan-out; bumps this package's manifest +// only. Tagging and pushing belong to the release workflow, which tags the +// commit it actually published from — `pnpm bump` only prepares the release +// commit for a PR. +export default defineConfig({ + files: ['package.json'], + commit: 'v%s', + tag: false, + push: false, +}); diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 283ce3a..67ad279 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -30,6 +30,7 @@ "scripts": { "build": "rslib build", "build:local": "cross-env SOURCEMAP=true rslib build", + "bump": "bumpp", "package": "pnpm run build && vsce package", "package:targets": "node scripts/packageTargets.mjs", "test": "pnpm run test:unit && pnpm run test:e2e", @@ -439,6 +440,7 @@ "@vscode/test-electron": "^3.1.0", "@vscode/vsce": "^3.9.2", "birpc": "^4.0.0", + "bumpp": "^12.2.1", "core-js-pure": "^3.49.0", "cross-env": "^7.0.3", "mocha": "^11.7.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3420133..14943f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,6 @@ importers: .: devDependencies: - bumpp: - specifier: ^12.2.1 - version: 12.2.1 rstack: specifier: ^0.3.2 version: 0.3.2(jiti@2.7.0)(typescript@5.9.3) @@ -59,6 +56,9 @@ importers: birpc: specifier: ^4.0.0 version: 4.0.0 + bumpp: + specifier: ^12.2.1 + version: 12.2.1 core-js-pure: specifier: ^3.49.0 version: 3.49.0 From 6dacd14d16c44e42ea780ee9fb3ba2d3d7e21b75 Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 19 Aug 2026 01:14:41 +0800 Subject: [PATCH 5/7] chore(release): guard real releases to main, verify tag target, bumpp 11 - preflight job fails a non-dry dispatch from any ref but main (gh workflow run --ref accepts branches and tags); dry runs stay allowed anywhere. - The tag step is idempotent only when the existing tag points at this commit; a tag on another commit means the version was never bumped, and the run fails instead of attaching mismatched VSIX assets. - bumpp ^11.1.0 (engines >=20.19) instead of 12 (^22.18 || ^24.11 || >=26), matching the root Node floor of >=22.12. --- .github/workflows/release.yml | 42 +++++++++++++++++++++++++++++------ CONTRIBUTING.md | 2 +- packages/vscode/package.json | 2 +- pnpm-lock.yaml | 20 ++++++----------- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 18d4449..3fc12b6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,9 +13,28 @@ permissions: contents: read jobs: + # A real release may only be dispatched from `main`: `gh workflow run --ref` + # accepts any branch or tag, and publishing plus tagging from anywhere else + # would permanently release the wrong commit. Dry runs are allowed from any + # ref so a branch can rehearse the packaging matrix. Failing here (instead + # of silently skipping the publish steps) makes the mistake visible. + preflight: + name: Preflight + if: github.repository == 'rstackjs/rstack-editor' && github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Require main for a real release + if: ${{ !inputs.dry_run && github.ref != 'refs/heads/main' }} + run: | + echo "::error::A real release must be dispatched from main (got ${GITHUB_REF}). Re-run with dry run enabled, or dispatch from main." + exit 1 + - name: Report + run: echo "ref=${GITHUB_REF} sha=${GITHUB_SHA} dry_run=${{ inputs.dry_run }}" + release_vscode_extension: name: Release VS Code Extension (${{ matrix.vsce-target }}) - if: github.repository == 'rstackjs/rstack-editor' && github.event_name == 'workflow_dispatch' + needs: preflight runs-on: ${{ matrix.runner }} environment: vscode-marketplace timeout-minutes: 30 @@ -120,8 +139,10 @@ jobs: uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 with: # changelogithub needs the tags and history to find the previous - # release and list the commits since it. + # release and list the commits since it; the tag step compares an + # existing tag's target against this commit. fetch-depth: 0 + fetch-tags: true - name: Setup Node.js uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 @@ -139,17 +160,24 @@ jobs: id: version run: echo "tag=v$(node -p "require('./packages/vscode/package.json').version")" >> "$GITHUB_OUTPUT" - # Idempotent: re-running a release (e.g. after one marketplace publish - # flaked and `--skip-duplicate` covered the rest) must not fail here. + # Idempotent for a re-run of the same commit (e.g. after one marketplace + # publish flaked and `--skip-duplicate` covered the rest), but a tag that + # already points at a *different* commit means the version was never + # bumped after the last release: fail instead of attaching VSIX files + # built from this commit to a release tagged at another one. - name: Push Tag env: TAG: ${{ steps.version.outputs.tag }} run: | - if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null; then - echo "tag $TAG already exists, leaving it as is" - else + existing=$(git rev-parse --verify --quiet "refs/tags/$TAG^{commit}" || true) + if [ -z "$existing" ]; then git tag "$TAG" "$GITHUB_SHA" git push origin "refs/tags/$TAG" + elif [ "$existing" = "$GITHUB_SHA" ]; then + echo "tag $TAG already points at $GITHUB_SHA, leaving it as is" + else + echo "::error::tag $TAG already exists at $existing but this run is at $GITHUB_SHA — bump the version (pnpm bump) before releasing again." + exit 1 fi - name: GitHub Release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68a63be..69e7fb7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,4 +37,4 @@ The VS Code extension is the only versioned artifact; its version lives in `pack 2. Open a PR with that commit and merge it into `main`. 3. Run the **Release** workflow (`Actions → Release → Run workflow`, branch `main`; `gh workflow run release.yml`). Tick **dry run** to only build the six VSIX artifacts. A real run publishes every platform target to the VS Code Marketplace and Open VSX, then tags `main` as `vX.Y.Z` and creates the GitHub Release with notes generated from the conventional commits since the previous tag and the VSIX files attached. -Re-running a release is safe: both marketplaces skip an already-published version and the tag step leaves an existing tag alone. +Re-running a release for the same commit is safe: both marketplaces skip an already-published version and the tag step leaves a tag that already points at that commit alone. A real (non-dry) run is rejected unless dispatched from `main`, and fails if the version's tag already exists on a different commit — bump first. diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 67ad279..3ae0183 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -440,7 +440,7 @@ "@vscode/test-electron": "^3.1.0", "@vscode/vsce": "^3.9.2", "birpc": "^4.0.0", - "bumpp": "^12.2.1", + "bumpp": "^11.1.0", "core-js-pure": "^3.49.0", "cross-env": "^7.0.3", "mocha": "^11.7.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14943f1..5cf0fbe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,8 +57,8 @@ importers: specifier: ^4.0.0 version: 4.0.0 bumpp: - specifier: ^12.2.1 - version: 12.2.1 + specifier: ^11.1.0 + version: 11.1.0 core-js-pure: specifier: ^3.49.0 version: 3.49.0 @@ -1137,9 +1137,9 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - bumpp@12.2.1: - resolution: {integrity: sha512-8inGPx8PC/BaEOWhzfxrNHGj/x5Srt0EeJatAcTJ9N7AZpQG/HlH4kGp5JWbEL8zffYXI5iBkMjG8SHnJ9e/6g==} - engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} + bumpp@11.1.0: + resolution: {integrity: sha512-jdwOGMyX8JIqpQ0N2RMRR87DHZaoJnUtui5lU9LqFfFK5JC0H8qY9uWqXoa+dEWt/K7rOmmsoyiZB8RBM7RPBQ==} + engines: {node: '>=20.19.0'} hasBin: true bundle-name@4.1.0: @@ -2334,10 +2334,6 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - verkit@0.3.2: - resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} - engines: {node: '>=18.12.0'} - version-range@4.15.0: resolution: {integrity: sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==} engines: {node: '>=4'} @@ -3423,16 +3419,16 @@ snapshots: ieee754: 1.2.1 optional: true - bumpp@12.2.1: + bumpp@11.1.0: dependencies: args-tokenizer: 0.3.0 cac: 7.0.0 jsonc-parser: 3.3.1 package-manager-detector: 1.8.0 + semver: 7.8.5 tinyexec: 1.3.0 tinyglobby: 0.2.17 unconfig: 7.5.0 - verkit: 0.3.2 yaml: 2.9.0 bundle-name@4.1.0: @@ -4671,8 +4667,6 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - verkit@0.3.2: {} - version-range@4.15.0: {} vscode-jsonrpc@8.2.0: {} From 95df0c3eb3b0ba648f401be3de4d38336d943a7c Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 19 Aug 2026 01:20:31 +0800 Subject: [PATCH 6/7] chore: bump every package in lockstep from the root All packages share one version (as in rspack-contrib/storybook-rsbuild), so bumpp lives at the root with files: packages/*/package.json and the VS Code manifest as the reference version. AGENTS.md records this as the one repo-level exception to the fan-out rule: no per-package script can bump several packages to the same version in one commit. --- AGENTS.md | 4 ++-- CONTRIBUTING.md | 4 ++-- bump.config.ts | 23 +++++++++++++++++++++++ package.json | 3 ++- packages/vscode/bump.config.ts | 12 ------------ packages/vscode/package.json | 2 -- pnpm-lock.yaml | 6 +++--- 7 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 bump.config.ts delete mode 100644 packages/vscode/bump.config.ts diff --git a/AGENTS.md b/AGENTS.md index c7af58e..31ff933 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,7 @@ Unified editor support for the [Rstack](https://rstack.rs) toolchain. pnpm works ## Conventions - All code, comments, commit messages, PRs and docs are in English, regardless of the conversation language. -- Root scripts are thin `pnpm -r run` fan-outs. Never make a root script reach into a package's internals — add the script to the package instead. +- Root scripts are thin `pnpm -r run` fan-outs. Never make a root script reach into a package's internals — add the script to the package instead. The one repo-level exception is `pnpm bump` (bumpp, `bump.config.ts`): all packages share one version and are bumped in lockstep, which no per-package script can guarantee. - READMEs are user-facing only. Contributor/agent material goes in AGENTS.md files, not READMEs. - Sibling checkouts of rslint / rstest / rstack-cli (`../rslint` etc.) are read-only references. Their working trees may be stale: `git fetch origin` and read via `git show origin/main:`. - Verify claims about upstream behavior or published packages against the actual source or registry — do not answer from memory. @@ -16,7 +16,7 @@ Unified editor support for the [Rstack](https://rstack.rs) toolchain. pnpm works - If extension source changed, also run the E2E slice covering the change (see `packages/vscode/AGENTS.md`). E2E launches a real VS Code and is the ground truth for editor behavior — unit tests are not a substitute. - Never delete `packages/vscode/.vscode-test/` — it caches the VS Code download the E2E suites reuse. - Report real command results only; never claim green without running. -- Releases: `pnpm bump` on a branch → PR → merge → run the **Release** workflow on `main`. The workflow publishes to both marketplaces, tags `vX.Y.Z` and creates the GitHub Release; never tag or publish by hand. Details in CONTRIBUTING.md → Releasing. +- Releases: `pnpm bump` on a branch (bumps every package to the same version) → PR → merge → run the **Release** workflow on `main`. The workflow publishes to both marketplaces, tags `vX.Y.Z` and creates the GitHub Release; never tag or publish by hand. Details in CONTRIBUTING.md → Releasing. ## Agent skills diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69e7fb7..3aca9af 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,9 +31,9 @@ To try the extension: press F5 in VS Code at the repo root — the playground la ## Releasing -The VS Code extension is the only versioned artifact; its version lives in `packages/vscode/package.json`. +All packages share one version and are bumped in lockstep; the root `package.json` carries no version. Today the VS Code extension (`packages/vscode`) is the only published artifact. -1. On a branch, run `pnpm bump` (interactive; or `pnpm bump --release minor`) — [bumpp](https://github.com/antfu-collective/bumpp) bumps the manifest and commits `vX.Y.Z`. It does not tag or push. +1. On a branch, run `pnpm bump` (interactive; or `pnpm bump --release minor`) — [bumpp](https://github.com/antfu-collective/bumpp) bumps every `packages/*/package.json` and commits `vX.Y.Z`. It does not tag or push. 2. Open a PR with that commit and merge it into `main`. 3. Run the **Release** workflow (`Actions → Release → Run workflow`, branch `main`; `gh workflow run release.yml`). Tick **dry run** to only build the six VSIX artifacts. A real run publishes every platform target to the VS Code Marketplace and Open VSX, then tags `main` as `vX.Y.Z` and creates the GitHub Release with notes generated from the conventional commits since the previous tag and the VSIX files attached. diff --git a/bump.config.ts b/bump.config.ts new file mode 100644 index 0000000..389c555 --- /dev/null +++ b/bump.config.ts @@ -0,0 +1,23 @@ +import { readFileSync } from 'node:fs'; +import { defineConfig } from 'bumpp'; + +// Every package in this repo shares one version (lockstep, like +// rspack-contrib/storybook-rsbuild). `pnpm bump` is therefore a repo-level +// operation, not a per-package script: it rewrites every packages/*/package.json +// in one commit. The VS Code extension is the reference package whose version +// seeds the prompt; the root package.json carries no version on purpose. +const manifest = new URL('./packages/vscode/package.json', import.meta.url); +const { version } = JSON.parse(readFileSync(manifest, 'utf8')) as { + version: string; +}; + +export default defineConfig({ + files: ['packages/*/package.json'], + currentVersion: version, + commit: 'v%s', + // Tagging and pushing belong to the release workflow, which tags the commit + // it actually published from. `pnpm bump` only prepares the release commit + // for a PR. + tag: false, + push: false, +}); diff --git a/package.json b/package.json index 53eb703..3db0a89 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "build": "pnpm -r run build", - "bump": "pnpm -r run bump", + "bump": "bumpp", "fmt": "rs fmt", "fmt:check": "rs fmt --check", "lint": "rs lint --type-check", @@ -15,6 +15,7 @@ "test:unit": "pnpm -r run test:unit" }, "devDependencies": { + "bumpp": "^11.1.0", "rstack": "^0.3.2" }, "packageManager": "pnpm@11.20.0", diff --git a/packages/vscode/bump.config.ts b/packages/vscode/bump.config.ts deleted file mode 100644 index f33ac45..0000000 --- a/packages/vscode/bump.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineConfig } from 'bumpp'; - -// Invoked through the root `pnpm bump` fan-out; bumps this package's manifest -// only. Tagging and pushing belong to the release workflow, which tags the -// commit it actually published from — `pnpm bump` only prepares the release -// commit for a PR. -export default defineConfig({ - files: ['package.json'], - commit: 'v%s', - tag: false, - push: false, -}); diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 3ae0183..283ce3a 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -30,7 +30,6 @@ "scripts": { "build": "rslib build", "build:local": "cross-env SOURCEMAP=true rslib build", - "bump": "bumpp", "package": "pnpm run build && vsce package", "package:targets": "node scripts/packageTargets.mjs", "test": "pnpm run test:unit && pnpm run test:e2e", @@ -440,7 +439,6 @@ "@vscode/test-electron": "^3.1.0", "@vscode/vsce": "^3.9.2", "birpc": "^4.0.0", - "bumpp": "^11.1.0", "core-js-pure": "^3.49.0", "cross-env": "^7.0.3", "mocha": "^11.7.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cf0fbe..c54b45c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: devDependencies: + bumpp: + specifier: ^11.1.0 + version: 11.1.0 rstack: specifier: ^0.3.2 version: 0.3.2(jiti@2.7.0)(typescript@5.9.3) @@ -56,9 +59,6 @@ importers: birpc: specifier: ^4.0.0 version: 4.0.0 - bumpp: - specifier: ^11.1.0 - version: 11.1.0 core-js-pure: specifier: ^3.49.0 version: 3.49.0 From 9e89ddc196a2d958ffd3899dcfc53254f1acb0cd Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 19 Aug 2026 11:11:19 +0800 Subject: [PATCH 7/7] chore: trim the release tooling to its load-bearing parts bumpp derives currentVersion from the globbed files, so reading packages/vscode/package.json to seed it was redundant and hard-coded a reference package the lockstep policy says does not exist. fetch-tags is dead config under fetch-depth: 0 (checkout takes the all-history refspec and never reads it), the event_name guard was tautological against a dispatch-only trigger, and the Report step, the ls -la and the banner comment were noise. Docs: CONTRIBUTING is the single place the release procedure is described. --- .github/workflows/release.yml | 11 +++-------- AGENTS.md | 4 ++-- CONTRIBUTING.md | 4 ++-- bump.config.ts | 13 +------------ 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3fc12b6..7dcb353 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: # of silently skipping the publish steps) makes the mistake visible. preflight: name: Preflight - if: github.repository == 'rstackjs/rstack-editor' && github.event_name == 'workflow_dispatch' + if: github.repository == 'rstackjs/rstack-editor' runs-on: ubuntu-latest timeout-minutes: 5 steps: @@ -29,8 +29,6 @@ jobs: run: | echo "::error::A real release must be dispatched from main (got ${GITHUB_REF}). Re-run with dry run enabled, or dispatch from main." exit 1 - - name: Report - run: echo "ref=${GITHUB_REF} sha=${GITHUB_SHA} dry_run=${{ inputs.dry_run }}" release_vscode_extension: name: Release VS Code Extension (${{ matrix.vsce-target }}) @@ -120,12 +118,11 @@ jobs: OVSX_PAT: ${{ secrets.OVSX_PAT }} run: pnpm exec ovsx publish --target ${{ matrix.vsce-target }} --skip-duplicate - # ======== tag + GitHub Release, once, after every target published ======== # Runs only for a real release: a dry run must leave no tag behind. The tag # points at the commit that was actually published (github.sha), the release # notes come from the conventional commits since the previous tag, and the - # six VSIX files are attached as assets so a release can be installed by hand - # (`code --install-extension`) without either marketplace. + # VSIX of every matrix target is attached as an asset so a release can be + # installed by hand (`code --install-extension`) without either marketplace. github_release: name: Tag and GitHub Release needs: release_vscode_extension @@ -142,7 +139,6 @@ jobs: # release and list the commits since it; the tag step compares an # existing tag's target against this commit. fetch-depth: 0 - fetch-tags: true - name: Setup Node.js uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 @@ -185,5 +181,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ steps.version.outputs.tag }} run: | - ls -la vsix npx changelogithub@15.0.4 --to "$TAG" --assets 'vsix/*.vsix' diff --git a/AGENTS.md b/AGENTS.md index 31ff933..1169f8b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,7 @@ Unified editor support for the [Rstack](https://rstack.rs) toolchain. pnpm works ## Conventions - All code, comments, commit messages, PRs and docs are in English, regardless of the conversation language. -- Root scripts are thin `pnpm -r run` fan-outs. Never make a root script reach into a package's internals — add the script to the package instead. The one repo-level exception is `pnpm bump` (bumpp, `bump.config.ts`): all packages share one version and are bumped in lockstep, which no per-package script can guarantee. +- Root scripts either fan out (`pnpm -r run`) or act on the whole workspace at once (`pnpm bump`). Never make a root script reach into one named package's internals — add the script to that package instead. - READMEs are user-facing only. Contributor/agent material goes in AGENTS.md files, not READMEs. - Sibling checkouts of rslint / rstest / rstack-cli (`../rslint` etc.) are read-only references. Their working trees may be stale: `git fetch origin` and read via `git show origin/main:`. - Verify claims about upstream behavior or published packages against the actual source or registry — do not answer from memory. @@ -16,7 +16,7 @@ Unified editor support for the [Rstack](https://rstack.rs) toolchain. pnpm works - If extension source changed, also run the E2E slice covering the change (see `packages/vscode/AGENTS.md`). E2E launches a real VS Code and is the ground truth for editor behavior — unit tests are not a substitute. - Never delete `packages/vscode/.vscode-test/` — it caches the VS Code download the E2E suites reuse. - Report real command results only; never claim green without running. -- Releases: `pnpm bump` on a branch (bumps every package to the same version) → PR → merge → run the **Release** workflow on `main`. The workflow publishes to both marketplaces, tags `vX.Y.Z` and creates the GitHub Release; never tag or publish by hand. Details in CONTRIBUTING.md → Releasing. +- Releases: never tag or publish by hand — the **Release** workflow does both. See CONTRIBUTING.md → Releasing. ## Agent skills diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3aca9af..2172752 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,10 +31,10 @@ To try the extension: press F5 in VS Code at the repo root — the playground la ## Releasing -All packages share one version and are bumped in lockstep; the root `package.json` carries no version. Today the VS Code extension (`packages/vscode`) is the only published artifact. +All packages share one version and are bumped in lockstep. Today the VS Code extension (`packages/vscode`) is the only published artifact. 1. On a branch, run `pnpm bump` (interactive; or `pnpm bump --release minor`) — [bumpp](https://github.com/antfu-collective/bumpp) bumps every `packages/*/package.json` and commits `vX.Y.Z`. It does not tag or push. 2. Open a PR with that commit and merge it into `main`. -3. Run the **Release** workflow (`Actions → Release → Run workflow`, branch `main`; `gh workflow run release.yml`). Tick **dry run** to only build the six VSIX artifacts. A real run publishes every platform target to the VS Code Marketplace and Open VSX, then tags `main` as `vX.Y.Z` and creates the GitHub Release with notes generated from the conventional commits since the previous tag and the VSIX files attached. +3. Run the **Release** workflow (`Actions → Release → Run workflow`, branch `main`; `gh workflow run release.yml`). Tick **dry run** to only build the VSIX artifacts (one per platform target). A real run publishes every platform target to the VS Code Marketplace and Open VSX, then tags `main` as `vX.Y.Z` and creates the GitHub Release with notes generated from the conventional commits since the previous tag and the VSIX files attached. Re-running a release for the same commit is safe: both marketplaces skip an already-published version and the tag step leaves a tag that already points at that commit alone. A real (non-dry) run is rejected unless dispatched from `main`, and fails if the version's tag already exists on a different commit — bump first. diff --git a/bump.config.ts b/bump.config.ts index 389c555..781ff97 100644 --- a/bump.config.ts +++ b/bump.config.ts @@ -1,19 +1,8 @@ -import { readFileSync } from 'node:fs'; import { defineConfig } from 'bumpp'; -// Every package in this repo shares one version (lockstep, like -// rspack-contrib/storybook-rsbuild). `pnpm bump` is therefore a repo-level -// operation, not a per-package script: it rewrites every packages/*/package.json -// in one commit. The VS Code extension is the reference package whose version -// seeds the prompt; the root package.json carries no version on purpose. -const manifest = new URL('./packages/vscode/package.json', import.meta.url); -const { version } = JSON.parse(readFileSync(manifest, 'utf8')) as { - version: string; -}; - +// All packages share one version; see CONTRIBUTING.md → Releasing. export default defineConfig({ files: ['packages/*/package.json'], - currentVersion: version, commit: 'v%s', // Tagging and pushing belong to the release workflow, which tags the commit // it actually published from. `pnpm bump` only prepares the release commit