From 7961bc74cffe172973ab5fddb7dc70f069b1cd05 Mon Sep 17 00:00:00 2001 From: Ahnaf An Nafee Date: Sat, 29 Aug 2026 23:08:03 -0400 Subject: [PATCH] fix(release): publish Open VSX-compatible package Open VSX rejects the release VSIX because mxschmitt.postscript is unavailable in its registry. Generate a separate manifest and package that omit only unavailable Open VSX dependencies while leaving the canonical manifest and standard VSIX unchanged for Visual Studio Marketplace dependency installation. Validate both registry artifacts in the workflow and cover the manifest transformation, source immutability, and preservation of other dependencies with Node unit tests. Verified with yarn lint, yarn npm audit --all --recursive, yarn test, and actionlint. --- .github/workflows/release.yml | 21 +++++++++++- .vscodeignore | 1 + CHANGELOG.md | 1 + package.json | 5 +-- scripts/prepare-open-vsx-manifest.mjs | 40 ++++++++++++++++++++++ scripts/prepare-open-vsx-manifest.test.mjs | 37 ++++++++++++++++++++ 6 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 scripts/prepare-open-vsx-manifest.mjs create mode 100644 scripts/prepare-open-vsx-manifest.test.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e762060..682cccf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,6 +100,25 @@ jobs: - name: Build extension if: env.VS_EXISTS == 'false' || env.OVSX_EXISTS == 'false' run: vsce package --no-dependencies -o postscript-preview-${{ steps.package-version.outputs.current-version }}.vsix + - name: Build Open VSX extension + if: env.OVSX_EXISTS == 'false' + run: | + cp package.json "$RUNNER_TEMP/postscript-preview-package.json" + trap 'cp "$RUNNER_TEMP/postscript-preview-package.json" package.json' EXIT + node scripts/prepare-open-vsx-manifest.mjs package.json + vsce package --no-dependencies -o postscript-preview-${{ steps.package-version.outputs.current-version }}-open-vsx.vsix + - name: Validate registry packages + if: env.OVSX_EXISTS == 'false' + run: | + unzip -p postscript-preview-${{ steps.package-version.outputs.current-version }}.vsix extension/package.json | + jq -e '.extensionDependencies | index("mxschmitt.postscript") != null' + unzip -p postscript-preview-${{ steps.package-version.outputs.current-version }}-open-vsx.vsix extension/package.json | + jq -e '(.extensionDependencies // []) | index("mxschmitt.postscript") == null' + if unzip -p postscript-preview-${{ steps.package-version.outputs.current-version }}-open-vsx.vsix extension.vsixmanifest | + grep --fixed-strings --quiet 'mxschmitt.postscript'; then + echo "Open VSX package still declares the unavailable dependency" >&2 + exit 1 + fi - name: Upload a Build Artifact if: env.VS_EXISTS == 'false' || env.OVSX_EXISTS == 'false' uses: actions/upload-artifact@v7 @@ -136,7 +155,7 @@ jobs: if: env.OVSX_EXISTS == 'false' env: OVSX_PAT: ${{ secrets.OPEN_VSX_TOKEN }} - run: ovsx publish "postscript-preview-${{ steps.package-version.outputs.current-version }}.vsix" --pat "$OVSX_PAT" + run: ovsx publish "postscript-preview-${{ steps.package-version.outputs.current-version }}-open-vsx.vsix" --pat "$OVSX_PAT" - name: Publish to Visual Studio Marketplace if: env.VS_EXISTS == 'false' env: diff --git a/.vscodeignore b/.vscodeignore index 41155b2..2b15376 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -28,6 +28,7 @@ ANTIGRAVITY.md TESTING.md docs/** examples/** +scripts/** CODE_OF_CONDUCT.md CONTRIBUTING.md generateEmojiShortcodeMap.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 64b024e..fef4af2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Fixes +- Published an Open VSX-specific package without the unavailable PostScript language dependency while preserving automatic dependency installation in the Visual Studio Marketplace. - Made Windows PostScript conversion use the native Ghostscript executable without a command shell. - Escaped filenames rendered in the preview and improved single-page and accessible pagination layouts. diff --git a/package.json b/package.json index 641f79c..4046cb0 100644 --- a/package.json +++ b/package.json @@ -76,8 +76,9 @@ "compile": "yarn clean && tsc -p ./", "lint": "eslint src", "watch": "tsc -watch -p ./", - "test": "yarn compile && mocha --ui tdd --color --timeout 10000 \"out/test/unit/**/*.test.js\" && node ./out/test/runTest.js", - "test:unit": "yarn compile && mocha --ui tdd --color --timeout 10000 \"out/test/unit/**/*.test.js\"", + "test": "yarn compile && yarn test:tools && mocha --ui tdd --color --timeout 10000 \"out/test/unit/**/*.test.js\" && node ./out/test/runTest.js", + "test:tools": "node --test scripts/prepare-open-vsx-manifest.test.mjs", + "test:unit": "yarn compile && yarn test:tools && mocha --ui tdd --color --timeout 10000 \"out/test/unit/**/*.test.js\"", "test:integration": "yarn compile && node ./out/test/runTest.js" }, "devDependencies": { diff --git a/scripts/prepare-open-vsx-manifest.mjs b/scripts/prepare-open-vsx-manifest.mjs new file mode 100644 index 0000000..ffb2237 --- /dev/null +++ b/scripts/prepare-open-vsx-manifest.mjs @@ -0,0 +1,40 @@ +import { readFile, writeFile } from "node:fs/promises"; +import { pathToFileURL } from "node:url"; + +const unavailableOpenVsxDependencies = new Set(["mxschmitt.postscript"]); + +export function createOpenVsxManifest(manifest) { + const openVsxManifest = { ...manifest }; + const availableDependencies = manifest.extensionDependencies?.filter( + (dependency) => !unavailableOpenVsxDependencies.has(dependency) + ); + + if (availableDependencies?.length) { + openVsxManifest.extensionDependencies = availableDependencies; + } else { + delete openVsxManifest.extensionDependencies; + } + + return openVsxManifest; +} + +async function prepareOpenVsxManifest(manifestPath) { + const manifest = JSON.parse(await readFile(manifestPath, "utf8")); + const openVsxManifest = createOpenVsxManifest(manifest); + await writeFile( + manifestPath, + `${JSON.stringify(openVsxManifest, null, "\t")}\n`, + "utf8" + ); +} + +if ( + process.argv[1] && + import.meta.url === pathToFileURL(process.argv[1]).href +) { + const manifestPath = process.argv[2]; + if (!manifestPath) { + throw new Error("Usage: prepare-open-vsx-manifest.mjs "); + } + await prepareOpenVsxManifest(manifestPath); +} diff --git a/scripts/prepare-open-vsx-manifest.test.mjs b/scripts/prepare-open-vsx-manifest.test.mjs new file mode 100644 index 0000000..a7a3f8e --- /dev/null +++ b/scripts/prepare-open-vsx-manifest.test.mjs @@ -0,0 +1,37 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { createOpenVsxManifest } from "./prepare-open-vsx-manifest.mjs"; + +test("removes unavailable extension dependencies from the Open VSX manifest", () => { + const marketplaceManifest = { + name: "postscript-preview", + version: "0.6.1", + extensionDependencies: ["mxschmitt.postscript"], + }; + + const openVsxManifest = createOpenVsxManifest(marketplaceManifest); + + assert.deepEqual(openVsxManifest, { + name: "postscript-preview", + version: "0.6.1", + }); + assert.deepEqual(marketplaceManifest.extensionDependencies, [ + "mxschmitt.postscript", + ]); +}); + +test("preserves dependencies that can be resolved by Open VSX", () => { + const marketplaceManifest = { + name: "postscript-preview", + extensionDependencies: [ + "mxschmitt.postscript", + "example.available-extension", + ], + }; + + const openVsxManifest = createOpenVsxManifest(marketplaceManifest); + + assert.deepEqual(openVsxManifest.extensionDependencies, [ + "example.available-extension", + ]); +});