diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1aaef44..2e95015 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,6 +20,10 @@ on: description: Build the VS Code extension. type: boolean default: true + extension-pre-release: + description: Mark the VSIX as a pre-release. + type: boolean + default: false test-extension: description: Run the VS Code extension test suites. type: boolean @@ -212,6 +216,9 @@ jobs: if [ "${{ inputs.build-cli }}" != "true" ]; then args+=(--skip-cli) fi + if [ "${{ inputs.extension-pre-release }}" = "true" ]; then + args+=(--extension-pre-release) + fi printf 'build-test-release %s\n' "${args[*]}" ./scripts/build-test-release "${args[@]}" diff --git a/.github/workflows/release-vscode.yml b/.github/workflows/release-vscode.yml index 7cd92b9..b0f4d48 100644 --- a/.github/workflows/release-vscode.yml +++ b/.github/workflows/release-vscode.yml @@ -1,8 +1,13 @@ # Releases the VS Code extension when a vscode-v* tag is pushed. # -# package.json holds the version; the tag is validated against it. The Marketplace -# and Open VSX steps skip cleanly until their tokens are configured, so the -# workflow is usable for GitHub Releases before those accounts exist. +# package.json holds the version; the tag is validated against it. A `-pre` suffix +# on the tag publishes a pre-release: vscode-v0.0.2 is stable, vscode-v0.0.2-pre is +# not. The suffix lives on the tag rather than in the version because VS Code +# extension versions must stay major.minor.patch; what marks a pre-release is a +# property inside the package. +# +# The Marketplace and Open VSX steps skip cleanly until their tokens are +# configured, so the workflow is usable for GitHub Releases before that. name: Release VS Code extension @@ -23,14 +28,25 @@ jobs: timeout-minutes: 5 outputs: version: ${{ steps.check.outputs.version }} + pre-release: ${{ steps.check.outputs.pre-release }} steps: - uses: actions/checkout@v5 - id: check run: | manifest=$(node -p "require('./vscode-extension/package.json').version") + pre_release=false + if [ "${GITHUB_REF_TYPE}" = "tag" ]; then tag_version="${GITHUB_REF_NAME#vscode-v}" + # A -pre suffix selects a pre-release and is not part of the version. + case "$tag_version" in + *-pre) + pre_release=true + tag_version="${tag_version%-pre}" + ;; + esac + if [ "$tag_version" != "$manifest" ]; then echo "Tag $GITHUB_REF_NAME implies version $tag_version," >&2 echo "but vscode-extension/package.json declares $manifest." >&2 @@ -38,8 +54,14 @@ jobs: exit 1 fi fi + echo "version=$manifest" >> "$GITHUB_OUTPUT" - echo "extension version $manifest" >> "$GITHUB_STEP_SUMMARY" + echo "pre-release=$pre_release" >> "$GITHUB_OUTPUT" + if [ "$pre_release" = "true" ]; then + echo "extension version $manifest (pre-release)" >> "$GITHUB_STEP_SUMMARY" + else + echo "extension version $manifest (stable)" >> "$GITHUB_STEP_SUMMARY" + fi build: needs: verify-version @@ -51,6 +73,9 @@ jobs: build-extension: true test-extension: true upload-artifacts: true + # Decided at build time: vsce refuses to publish a package as a pre-release + # unless the marker is already in its manifest. + extension-pre-release: ${{ needs.verify-version.outputs.pre-release == 'true' }} publish: name: Publish @@ -61,6 +86,7 @@ jobs: contents: write env: VERSION: ${{ needs.verify-version.outputs.version }} + PRE_RELEASE: ${{ needs.verify-version.outputs.pre-release }} # Job-level so the publish steps' `if` expressions can test them. VSCE_PAT: ${{ secrets.VSCE_PAT }} OVSX_PAT: ${{ secrets.OVSX_PAT }} @@ -94,6 +120,21 @@ jobs: echo "Too few server plug-ins; the symlink did not resolve." >&2 exit 1 fi + + # The marker is baked in at package time, so confirm the package matches + # what the tag asked for. vsce would reject a mismatch in one direction + # and silently publish a pre-release as stable in the other. + if unzip -p "$vsix" extension.vsixmanifest | grep -q 'Microsoft.VisualStudio.Code.PreRelease'; then + marked=true + else + marked=false + fi + echo "packaged as pre-release: $marked (tag asked for $PRE_RELEASE)" + if [ "$marked" != "$PRE_RELEASE" ]; then + echo "VSIX pre-release marker does not match the tag." >&2 + exit 1 + fi + echo "VSIX=$vsix" >> "$GITHUB_ENV" - name: Create the GitHub release @@ -101,10 +142,15 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | + args=() + if [ "$PRE_RELEASE" = "true" ]; then + args+=(--prerelease) + fi gh release create "$GITHUB_REF_NAME" \ --repo "$GITHUB_REPOSITORY" \ --title "AADL2 VS Code extension $VERSION" \ --generate-notes \ + "${args[@]+"${args[@]}"}" \ "$VSIX" - name: Install publishing tools @@ -117,7 +163,12 @@ jobs: - name: Publish to the VS Code Marketplace if: github.ref_type == 'tag' && env.VSCE_PAT != '' working-directory: vscode-extension - run: npx --no-install vsce publish --packagePath "../$VSIX" + run: | + args=() + if [ "$PRE_RELEASE" = "true" ]; then + args+=(--pre-release) + fi + npx --no-install vsce publish --packagePath "../$VSIX" "${args[@]+"${args[@]}"}" # Requires the "osate" namespace claimed at open-vsx.org and its token # stored as OVSX_PAT. @@ -126,7 +177,12 @@ jobs: working-directory: vscode-extension # --yes because ovsx is not a devDependency, so npx must fetch it and # would otherwise wait for a confirmation that never comes in CI. - run: npx --yes ovsx publish "../$VSIX" --pat "$OVSX_PAT" + run: | + args=() + if [ "$PRE_RELEASE" = "true" ]; then + args+=(--pre-release) + fi + npx --yes ovsx publish "../$VSIX" --pat "$OVSX_PAT" "${args[@]+"${args[@]}"}" - name: Note skipped publications if: github.ref_type == 'tag' diff --git a/RELEASING.md b/RELEASING.md index 65cd330..b5b62b2 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -6,7 +6,7 @@ by pushing a component-prefixed tag; nothing is published from `main`. | Component | Tag | Version source | | --- | --- | --- | | `osate-cli` | `osate-cli-v` | `` in [`osate-cli/pom.xml`](osate-cli/pom.xml) | -| VS Code extension | `vscode-v` | `version` in [`vscode-extension/package.json`](vscode-extension/package.json) | +| VS Code extension | `vscode-v` or `vscode-v-pre` | `version` in [`vscode-extension/package.json`](vscode-extension/package.json) | | Language server | `ls-v` | `aadl.ls.parent` version in [`aadl-language-server/pom.xml`](aadl-language-server/pom.xml) | The tag does not set the version. Each release workflow reads the version out of @@ -23,8 +23,8 @@ of truth. Bump the version in a normal commit first, then tag that commit. # 2. Tag the merged commit and push the tag. git switch main && git pull -git tag osate-cli-v0.1.4 -git push origin osate-cli-v0.1.4 +git tag osate-cli-v0.1.0 +git push origin osate-cli-v0.1.0 ``` Watch it with `gh run watch`. Each workflow also accepts `workflow_dispatch`, @@ -49,6 +49,51 @@ Code Marketplace and Open VSX. The VSIX is checked for a plausible number of bundled server plug-ins first, because the server reaches it through a symlink that would otherwise fail silently. +### Stable or pre-release + +A `-pre` suffix on the tag publishes a pre-release; without it the release is +stable. The version itself is identical either way: + +```bash +git tag vscode-v0.1.0-pre # pre-release: users must opt in +git tag vscode-v0.1.0 # stable: offered to everyone +``` + +A pre-release is marked as such on the Marketplace and on Open VSX, and the +GitHub Release gets the pre-release badge. VS Code keeps users on the newest +*stable* version unless they explicitly switch that extension to the pre-release +channel, so this is the way to put a build in front of willing testers without +pushing it at everyone. + +The suffix belongs on the tag rather than in the version because VS Code +extension versions must stay `major.minor.patch` — a pre-release is not a +different version string, it is a property recorded inside the package. That +property is written by `vsce package --pre-release`, and `vsce publish` **refuses** +to publish a package as a pre-release unless it was built as one: + +```text +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. +``` + +So the decision is made at build time, not publish time. The tag drives it all +the way down: `release-vscode.yml` parses the suffix, passes +`extension-pre-release` to the build workflow, which passes +`--extension-pre-release` to `scripts/build-test-release`, which sets +`-Dvsce.package.script=package:pre-release` so Maven runs the npm script that adds +the flag. Before publishing, the workflow re-reads the built VSIX manifest and +fails if the marker disagrees with the tag, so the two cannot drift apart. + +Marketplace and Open VSX both treat a published version as permanent — you can +unpublish an extension but not an individual version. Choosing pre-release does +not change that; it only changes who is offered the build. + +To produce a pre-release VSIX locally: + +```bash +./scripts/build-test-release --skip-osate --extension-pre-release +``` + **`ls-v*`** — [`release-server.yml`](.github/workflows/release-server.yml) The p2 repository archive plus `build-provenance.properties`, attached to a diff --git a/aadl-language-server/org.osate.aadl.ls/META-INF/MANIFEST.MF b/aadl-language-server/org.osate.aadl.ls/META-INF/MANIFEST.MF index c56b8e9..6529f3d 100644 --- a/aadl-language-server/org.osate.aadl.ls/META-INF/MANIFEST.MF +++ b/aadl-language-server/org.osate.aadl.ls/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: AADL Language Server Bundle-SymbolicName: org.osate.aadl.ls;singleton:=true -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 0.1.0.qualifier Bundle-Vendor: CMU-SEI Automatic-Module-Name: org.osate.aadl.ls Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/aadl-language-server/org.osate.aadl.ls/pom.xml b/aadl-language-server/org.osate.aadl.ls/pom.xml index cc3a5e0..11c8dff 100644 --- a/aadl-language-server/org.osate.aadl.ls/pom.xml +++ b/aadl-language-server/org.osate.aadl.ls/pom.xml @@ -31,13 +31,13 @@ org.osate aadl.ls.parent - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT .. org.osate org.osate.aadl.ls - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT eclipse-plugin diff --git a/aadl-language-server/plugins/org.osate.aadl.ls.tests/META-INF/MANIFEST.MF b/aadl-language-server/plugins/org.osate.aadl.ls.tests/META-INF/MANIFEST.MF index a4128a9..0138f88 100644 --- a/aadl-language-server/plugins/org.osate.aadl.ls.tests/META-INF/MANIFEST.MF +++ b/aadl-language-server/plugins/org.osate.aadl.ls.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: AADL Language Server Tests Bundle-SymbolicName: org.osate.aadl.ls.tests;singleton:=true -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 0.1.0.qualifier Bundle-Vendor: CMU-SEI Fragment-Host: org.osate.aadl.ls Automatic-Module-Name: org.osate.aadl.ls.tests diff --git a/aadl-language-server/plugins/org.osate.aadl.ls.tests/pom.xml b/aadl-language-server/plugins/org.osate.aadl.ls.tests/pom.xml index 27778ed..5c19fd1 100644 --- a/aadl-language-server/plugins/org.osate.aadl.ls.tests/pom.xml +++ b/aadl-language-server/plugins/org.osate.aadl.ls.tests/pom.xml @@ -31,13 +31,13 @@ org.osate aadl.ls.parent - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT ../.. org.osate org.osate.aadl.ls.tests - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT eclipse-test-plugin diff --git a/aadl-language-server/pom.xml b/aadl-language-server/pom.xml index 6e4915b..e3c6f40 100644 --- a/aadl-language-server/pom.xml +++ b/aadl-language-server/pom.xml @@ -37,7 +37,7 @@ aadl.ls.parent - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT pom diff --git a/aadl-language-server/releng/org.osate.aadl.ls.repository/pom.xml b/aadl-language-server/releng/org.osate.aadl.ls.repository/pom.xml index 236f83a..2637c12 100644 --- a/aadl-language-server/releng/org.osate.aadl.ls.repository/pom.xml +++ b/aadl-language-server/releng/org.osate.aadl.ls.repository/pom.xml @@ -31,7 +31,7 @@ org.osate aadl.ls.parent - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT ../.. diff --git a/osate-cli/pom.xml b/osate-cli/pom.xml index eba354b..9c86e65 100644 --- a/osate-cli/pom.xml +++ b/osate-cli/pom.xml @@ -45,7 +45,7 @@ the tarball, deb, rpm, and Homebrew package versions. Keep it a plain release version: rpm forbids '-' in Version, so a '-SNAPSHOT' suffix would not survive packaging. --> - 0.1.3 + 0.1.0 21 UTF-8 2.11.0 diff --git a/pom.xml b/pom.xml index 5356789..04ba777 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.osate aadl-language-server-aggregator - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT pom diff --git a/scripts/build-test-release b/scripts/build-test-release index 33c318b..80664a2 100755 --- a/scripts/build-test-release +++ b/scripts/build-test-release @@ -36,6 +36,7 @@ skip_osate=false skip_extension=false skip_extension_tests=false skip_cli=false +extension_pre_release=false usage() { cat <<'EOF' @@ -57,6 +58,10 @@ Options: integration tests download VS Code and need a display, which is not always available. --skip-cli Do not build the osate-cli reactor. + --extension-pre-release Mark the VSIX as a pre-release. vsce writes this into + the package manifest and refuses to publish a package + as a pre-release unless it was built as one, so this + has to be decided at build time. -h, --help Show this help. EOF } @@ -76,6 +81,9 @@ while [[ $# -gt 0 ]]; do --skip-cli) skip_cli=true ;; + --extension-pre-release) + extension_pre_release=true + ;; -h | --help) usage exit 0 @@ -174,12 +182,19 @@ mvn \ if [[ "${skip_extension}" == true ]]; then echo "Skipping VS Code extension" else - echo "Building VS Code extension" + extension_args=() + if [[ "${extension_pre_release}" == true ]]; then + echo "Building VS Code extension (pre-release)" + extension_args+=(-Dvsce.package.script=package:pre-release) + else + echo "Building VS Code extension" + fi mvn \ -T6 \ -f "${repo_root}/vscode-extension/pom.xml" \ -Dtycho.localArtifacts=ignore \ + "${extension_args[@]+"${extension_args[@]}"}" \ clean verify fi diff --git a/vscode-extension/.vscodeignore b/vscode-extension/.vscodeignore index 88c70ca..afbff4a 100644 --- a/vscode-extension/.vscodeignore +++ b/vscode-extension/.vscodeignore @@ -11,6 +11,7 @@ src/** .gitignore .yarnrc vsc-extension-quickstart.md +images/*.svg **/tsconfig.json **/tsconfig.test.json **/.eslintrc.json diff --git a/vscode-extension/AGENTS.md b/vscode-extension/AGENTS.md index 1ad8347..8b882b8 100644 --- a/vscode-extension/AGENTS.md +++ b/vscode-extension/AGENTS.md @@ -58,9 +58,16 @@ tests. Package the extension with: ```bash -npm run package +npm run package # stable +npm run package:pre-release # marked as a pre-release ``` +The pre-release marker is written into the VSIX manifest at package time, and +`vsce publish` refuses to publish a package as a pre-release unless it was built +as one, so it cannot be added later. `vscode-extension/pom.xml` selects the script +through the `vsce.package.script` property, which is how a tagged release drives +it. See [../RELEASING.md](../RELEASING.md). + For a server plus extension build, first build OSATE, then run these from the repository root in this order: diff --git a/vscode-extension/CHANGELOG.md b/vscode-extension/CHANGELOG.md index 8af8a5c..256bcf9 100644 --- a/vscode-extension/CHANGELOG.md +++ b/vscode-extension/CHANGELOG.md @@ -29,6 +29,10 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how ## [Unreleased] +## [0.1.0] - 2026-09-02 + +- Align the extension version with the language server and osate-cli at 0.1.0. +- Add the AADL vector mark as the extension icon. - Add bus load analysis command for instance models. - Initial release diff --git a/vscode-extension/images/icon.png b/vscode-extension/images/icon.png new file mode 100644 index 0000000..2c81592 Binary files /dev/null and b/vscode-extension/images/icon.png differ diff --git a/vscode-extension/images/icon.svg b/vscode-extension/images/icon.svg new file mode 100644 index 0000000..e630875 --- /dev/null +++ b/vscode-extension/images/icon.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/vscode-extension/package-lock.json b/vscode-extension/package-lock.json index ce30274..6fbf210 100644 --- a/vscode-extension/package-lock.json +++ b/vscode-extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "aadl2", - "version": "0.0.2", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aadl2", - "version": "0.0.2", + "version": "0.1.0", "license": "LicenseRef-BSD-SEI", "dependencies": { "vscode-languageclient": "^9.0.1" diff --git a/vscode-extension/package.json b/vscode-extension/package.json index da6ffa2..48b7d58 100644 --- a/vscode-extension/package.json +++ b/vscode-extension/package.json @@ -3,8 +3,9 @@ "displayName": "AADL2", "publisher": "osate", "description": "Support for AADL2 modeling", - "version": "0.0.2", + "version": "0.1.0", "license": "LicenseRef-BSD-SEI", + "icon": "images/icon.png", "repository": { "type": "git", "url": "https://github.com/osate/aadl-tooling.git" @@ -196,6 +197,7 @@ "watch": "node esbuild.js --watch", "package-bundle": "node esbuild.js --production", "package": "npm run package-bundle && vsce package --no-dependencies --follow-symlinks", + "package:pre-release": "npm run package-bundle && vsce package --no-dependencies --follow-symlinks --pre-release", "check-types": "tsc -b ./ --noEmit", "compile-tests": "tsc -p tsconfig.test.json", "test:unit": "npm run compile-tests && mocha --ui tdd \"out/test/unit/**/*.test.js\"", diff --git a/vscode-extension/pom.xml b/vscode-extension/pom.xml index a2787f4..e6914cd 100644 --- a/vscode-extension/pom.xml +++ b/vscode-extension/pom.xml @@ -30,7 +30,7 @@ org.osate aadl-language-server-aggregator - 1.0.0-SNAPSHOT + 0.1.0-SNAPSHOT ../pom.xml @@ -40,6 +40,11 @@ 1.15.1 v22.22.3 + + package ${project.basedir}/../aadl-language-server/releng/org.osate.aadl.ls.repository/target/repository/plugins @@ -124,7 +129,7 @@ package - run package + run ${vsce.package.script}