From 9b032b98f442dc48ba9c2cd220eebb7bac97022e Mon Sep 17 00:00:00 2001 From: Jimisola Laursen Date: Mon, 24 Aug 2026 00:11:31 +0200 Subject: [PATCH] feat(ci): publish VS Code extensions with the registries' own CLIs Replaces HaaLeo/publish-vscode-extension with vsce and ovsx, run directly. The forcing issue is authentication, not the action itself. Azure DevOps retires global Personal Access Tokens on 2026-12-01, and the action declares `pat` as a required input with no Entra ID support -- so it cannot follow us onto the thing that replaces the token it depends on. vsce 3.9.2 already carries --azure-credential. Two other things fall out for free. The action still declares node20, which is what emits the "Node 20 is being deprecated" warning on every publish; a `run:` step uses the job's own Node, so there is no `using:` to be deprecated. And the action has had no commit since 2025-06, while both CLIs are first-party and shipped a release this month. The CLIs come from the extension's own devDependencies -- vsce already builds the VSIX -- so `--no-install` makes a missing one a clear failure rather than a silent unpinned fetch, and Renovate tracks their versions in the consuming repo's lockfile. Auth is unchanged for now: VSCE_PAT still, with a new azure-credential input defaulting off, so switching to Entra is one line once the Azure side exists. See #98. Signed-off-by: Jimisola Laursen --- .../typescript-publish-to-vscode.yml | 69 +++++++++++++++---- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/.github/workflows/typescript-publish-to-vscode.yml b/.github/workflows/typescript-publish-to-vscode.yml index 69e9384..e386e7e 100644 --- a/.github/workflows/typescript-publish-to-vscode.yml +++ b/.github/workflows/typescript-publish-to-vscode.yml @@ -38,6 +38,15 @@ on: required: false type: string default: "open-vsx,vscode-marketplace" + azure-credential: + description: > + Authenticate to the VS Code Marketplace with Microsoft Entra ID instead of + VSCE_PAT. Azure DevOps retires global PATs on 2026-12-01 -- see + reqstool/.github#98. Enabling this needs Entra set up for the publisher first, + and likely an azure/login step and id-token: write on this job. + required: false + type: boolean + default: false secrets: OPEN_VSX_TOKEN: required: false @@ -111,19 +120,53 @@ jobs: id: vsix run: echo "path=$(find . -maxdepth 1 -name '*.vsix' | head -1)" >> "$GITHUB_OUTPUT" + # Published with each registry's own CLI rather than a third-party action. + # HaaLeo/publish-vscode-extension declares `pat` as required, so it cannot + # reach Entra ID -- which is what replaces the PAT Azure DevOps retires on + # 2026-12-01. It also still declares node20 and has had no commit since + # 2025-06. See reqstool/.github#98. + # + # Both CLIs come from the extension's own devDependencies via `npm ci` + # above -- `vsce` already builds the VSIX -- so their versions are pinned + # in its lockfile and tracked by Renovate rather than floating here. + # + # A `run:` step also uses the job's Node, so there is no `using:` + # declaration to be deprecated out from under us. + - name: Dry-run — report what would be published + if: ${{ inputs.dry-run }} + env: + VSIX_PATH: ${{ steps.vsix.outputs.path }} + REGISTRIES: ${{ inputs.registries }} + run: | + set -euo pipefail + if [ ! -s "$VSIX_PATH" ]; then + echo "::error::No VSIX was produced at '$VSIX_PATH'." + exit 1 + fi + echo "Would publish $VSIX_PATH ($(du -h "$VSIX_PATH" | cut -f1)) to: $REGISTRIES" + - name: Publish to Open VSX Registry - if: ${{ contains(inputs.registries, 'open-vsx') }} - uses: HaaLeo/publish-vscode-extension@ca5561daa085dee804bf9f37fe0165785a9b14db # v2.0.0 - with: - pat: ${{ secrets.OPEN_VSX_TOKEN }} - extensionFile: ${{ steps.vsix.outputs.path }} - dryRun: ${{ inputs.dry-run }} + if: ${{ contains(inputs.registries, 'open-vsx') && !inputs.dry-run }} + env: + # ovsx reads the token from OVSX_PAT; passing it as an argument would + # put it in the process list. Open VSX is Eclipse-run and unaffected + # by the Azure DevOps PAT retirement. + OVSX_PAT: ${{ secrets.OPEN_VSX_TOKEN }} + VSIX_PATH: ${{ steps.vsix.outputs.path }} + run: npx --no-install ovsx publish "$VSIX_PATH" - name: Publish to VS Code Marketplace - if: ${{ contains(inputs.registries, 'vscode-marketplace') }} - uses: HaaLeo/publish-vscode-extension@ca5561daa085dee804bf9f37fe0165785a9b14db # v2.0.0 - with: - pat: ${{ secrets.VSCE_PAT }} - registryUrl: https://marketplace.visualstudio.com - extensionFile: ${{ steps.vsix.outputs.path }} - dryRun: ${{ inputs.dry-run }} + if: ${{ contains(inputs.registries, 'vscode-marketplace') && !inputs.dry-run }} + env: + # vsce reads the token from VSCE_PAT, and ignores it under + # --azure-credential. + VSCE_PAT: ${{ secrets.VSCE_PAT }} + VSIX_PATH: ${{ steps.vsix.outputs.path }} + AZURE_CREDENTIAL: ${{ inputs.azure-credential }} + run: | + set -euo pipefail + if [ "$AZURE_CREDENTIAL" = "true" ]; then + npx --no-install vsce publish --azure-credential --packagePath "$VSIX_PATH" + else + npx --no-install vsce publish --packagePath "$VSIX_PATH" + fi