Skip to content

Let the tag choose whether the extension is a pre-release - #4

Merged
lwrage merged 2 commits into
mainfrom
vscode-pre-release-tags
Sep 2, 2026
Merged

Let the tag choose whether the extension is a pre-release#4
lwrage merged 2 commits into
mainfrom
vscode-pre-release-tags

Conversation

@lwrage

@lwrage lwrage commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

vscode-v0.0.2 publishes a stable release; vscode-v0.0.2-pre publishes a pre-release of the same version.

Why the suffix goes on the tag, and why it can't be publish-time only

VS Code extension versions must stay major.minor.patch, so a pre-release isn't a different version string — it's a property recorded inside the package. That property is written by vsce package --pre-release, and vsce publish refuses to add it afterwards:

Cannot use '--pre-release' flag with a package that was not packaged as
pre-release. Please package it using the '--pre-release' flag and publish again.

I found that in @vscode/vsce/out/publish.js before wiring anything, which is what determined the design: the decision belongs at build time, so the tag has to drive the whole chain rather than just the final publish call.

Layer Change
package.json new package:pre-release script — a sibling script, not shell interpolation in the existing one, which wouldn't work under cmd.exe
vscode-extension/pom.xml selects it via a vsce.package.script property
scripts/build-test-release --extension-pre-release sets that property
build.yml extension-pre-release input mapped onto the flag
release-vscode.yml parses -pre, passes it down, adds --pre-release to both vsce publish and ovsx publish, marks the GitHub Release as prerelease

Before publishing, the workflow re-reads the built VSIX manifest and fails if the marker disagrees with the tag. Without that check the two could drift: vsce rejects one direction loudly, but the other would quietly ship a pre-release as stable.

Verified locally

  • The flag reaches npm run package:pre-release and produces Microsoft.VisualStudio.Code.PreRelease" Value="true" in the manifest; a default build has no marker (checked both directions, so the flag can't leak).
  • Tag parsing: vscode-v0.0.2 → stable, vscode-v0.0.2-pre → pre-release, vscode-v0.0.3 → rejected, vscode-v0.0.2-beta → rejected rather than silently treated as stable.
  • vsce and ovsx both accept --pre-release (checked --help for each rather than assuming).

Documented in RELEASING.md and vscode-extension/AGENTS.md.

Also carries your icon

"icon": "images/icon.png" at 128×128 registers as Microsoft.VisualStudio.Services.Icons.Default in the VSIX, with the SVG source excluded via .vscodeignore. Confirmed in a rebuilt package — the VSIX I'd built earlier predated it, so it's worth knowing a rebuild was needed.

🤖 Generated with Claude Code

`vscode-v0.0.2` publishes a stable release; `vscode-v0.0.2-pre` publishes a
pre-release of the same version. VS Code keeps users on the newest stable build
unless they opt that extension into the pre-release channel, so this is how a
build reaches willing testers without being pushed at everyone.

The suffix has to live on the tag: VS Code extension versions must stay
major.minor.patch, so a pre-release is not a different version string but a
property inside the package. That property is written by
`vsce package --pre-release`, and vsce refuses to publish a package as a
pre-release unless it was built as one:

  Cannot use '--pre-release' flag with a package that was not packaged as
  pre-release. Please package it using the '--pre-release' flag and publish again.

Which means the choice belongs at build time, and the tag has to drive the whole
chain rather than only the final publish call:

- package.json gains a `package:pre-release` script. A sibling script rather than
  shell interpolation inside the existing one, which would not work under cmd.exe.
- vscode-extension/pom.xml selects it through a `vsce.package.script` property.
- scripts/build-test-release gains `--extension-pre-release`, which sets that
  property.
- build.yml gains an `extension-pre-release` input mapped onto the flag.
- release-vscode.yml parses the `-pre` suffix, passes it down, adds
  `--pre-release` to both `vsce publish` and `ovsx publish`, and marks the GitHub
  Release as a prerelease.

Before publishing, the workflow re-reads the built VSIX manifest and fails if the
marker disagrees with the tag, so the two cannot drift: vsce would reject one
direction, and the other would quietly ship a pre-release as stable.

Verified end to end locally: the flag reaches `npm run package:pre-release` and
produces `Microsoft.VisualStudio.Code.PreRelease" Value="true"` in the manifest,
while a default build has no marker. Tag parsing accepts `vscode-v0.0.2` and
`vscode-v0.0.2-pre`, and rejects a wrong version or an unrecognized suffix rather
than treating it as stable.

Documented in RELEASING.md and vscode-extension/AGENTS.md. Also carries the icon
you added, which registers as Icons.Default in the VSIX with the SVG source
excluded.
Language server, osate-cli and the VS Code extension were at three unrelated
versions (1.0.0-SNAPSHOT, 0.1.3, 0.0.2). Nothing has been tagged or released
yet, so the CLI moving down from 0.1.3 affects no published artifact.

The language server keeps the Tycho development form, 0.1.0-SNAPSHOT paired with
Bundle-Version 0.1.0.qualifier, so each build still stamps a timestamp and p2 can
tell rebuilds apart. Tycho requires the pom and manifest versions to agree, so
both manifests moved with the poms. Releasing ls-v0.1.0 still means dropping
-SNAPSHOT first, which release-server.yml already enforces.

The root aggregator moved to 0.1.0-SNAPSHOT as well. It ships nothing, but it is
what build-provenance.properties records as tooling.version, which would otherwise
report 1.0.0-SNAPSHOT for a build of three 0.1.0 components. Its parent reference
in vscode-extension/pom.xml moved with it.

The extension version was bumped with `npm version` so package.json and
package-lock.json stay in step, and CHANGELOG.md promotes [Unreleased] to [0.1.0].
The RELEASING.md tag examples now use the real versions.

Verified by a full build rather than inspection, since Tycho rejects a pom and
manifest that disagree: language server 0.1.0 with 35 tests, extension 0.1.0,
CLI 0.1.0, and all five test-count assertions passing. The artifacts carry it
through — org.osate.aadl.ls_0.1.0.v20260902-1313.jar, aadl2-0.1.0.vsix,
`osate-cli --version` reporting 0.1.0, and provenance recording
tooling.version=0.1.0-SNAPSHOT with cli.version=0.1.0.
@lwrage
lwrage merged commit 602290b into main Sep 2, 2026
3 checks passed
@lwrage
lwrage deleted the vscode-pre-release-tags branch September 2, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants