From 3584eaf99b73912d4e1b509a0c9982bc97b339a6 Mon Sep 17 00:00:00 2001 From: madhur310 Date: Mon, 9 Nov 2026 16:17:02 -0800 Subject: [PATCH] feat(vscode): add OIDC-compatible publish-release-vsix composite action - W-24756661 vscode-publish-release-vsix.yml is a job-level reusable workflow, so vsce publish --oidc inside it always exchanges against job_workflow_ref pointing at this repo rather than the caller's -- confirmed via a live test in forcedotcom/salesforcedx-vscode, where every --oidc attempt through that nested workflow got a 401 ("token could not be exchanged for the specified publisher") despite a Trusted Publishing policy registered for the caller's own repo + workflow filename. A composite action runs as a step inside the caller's own job instead, so job_workflow_ref matches what's registered. Adds vscode/publish-release-vsix as the OIDC-safe equivalent of the existing PAT-based reusable workflow, following the same pattern as the already inline-called vscode/publish-vsix action. Co-Authored-By: Claude Sonnet 5 --- .../vscode/publish-release-vsix/action.yml | 86 +++++++++++++++++++ README.md | 20 ++++- 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 .github/actions/vscode/publish-release-vsix/action.yml diff --git a/.github/actions/vscode/publish-release-vsix/action.yml b/.github/actions/vscode/publish-release-vsix/action.yml new file mode 100644 index 0000000..7d2adc4 --- /dev/null +++ b/.github/actions/vscode/publish-release-vsix/action.yml @@ -0,0 +1,86 @@ +name: Publish Release VSIXs (OIDC) +description: >- + Downloads every VSIX asset from a GitHub release and publishes it to the VS Code + Marketplace via vsce --oidc trusted publishing, with per-VSIX retry. Composite action + (not a reusable workflow) -- the Marketplace's OIDC trust check keys off + job_workflow_ref, which for a nested reusable *workflow* always points at this repo + rather than the caller's, so OIDC publishing only works when this logic runs as a step + inside the caller's own job. The calling job must declare `permissions: id-token: + write` and have a Trusted Publishing policy registered for its repo + workflow + filename on the Marketplace. Use vscode-publish-release-vsix.yml instead when + publishing with a VSCE_PERSONAL_ACCESS_TOKEN PAT, where job_workflow_ref doesn't matter. + +inputs: + release-tag: + description: GitHub release tag containing the VSIX assets + required: true + dry-run: + description: Download and inspect VSIXs without publishing + required: false + default: 'false' + vsix-name-pattern: + description: Glob of downloaded VSIX file names to publish + required: false + default: '*.vsix' + exclude-web-vsix: + description: Exclude *-web-* VSIXs from publishing + required: false + default: 'false' + +runs: + using: composite + steps: + - name: Download release VSIXs + id: release + uses: salesforcecli/github-workflows/.github/actions/vscode/download-release-vsix@main + with: + release-tag: ${{ inputs.release-tag }} + + - name: Publish VSIXs + shell: bash + env: + DRY_RUN: ${{ inputs.dry-run }} + PRE_RELEASE: ${{ steps.release.outputs.pre-release }} + VSIX_PATTERN: ${{ inputs.vsix-name-pattern }} + EXCLUDE_WEB: ${{ inputs.exclude-web-vsix }} + run: | + # Marketplace gallery requests can sit until typed-rest-client's 180s + # socket timeout. vsce has no timeout flag; retry per VSIX. + # --skip-duplicate makes a retry a no-op if the first attempt committed. + publish_with_retry() { + local attempt + for attempt in 1 2 3; do + echo "Publish attempt ${attempt}/3" + if "$@"; then + return 0 + fi + if [ "$attempt" -lt 3 ]; then + echo "Publish failed; retrying in 15s..." + sleep 15 + fi + done + return 1 + } + + while IFS= read -r -d '' vsix; do + args=(--packagePath "$vsix" --oidc --skip-duplicate) + if [ "$PRE_RELEASE" = true ]; then + args+=(--pre-release) + fi + + if [ "$DRY_RUN" = true ]; then + echo "Would publish $vsix to the VS Code Marketplace with --skip-duplicate: @vscode/vsce publish ${args[*]}" + continue + fi + + if ! publish_with_retry npx @vscode/vsce publish "${args[@]}"; then + echo "::error::Failed to publish $vsix after 3 attempts" + exit 1 + fi + done < <( + if [ "$EXCLUDE_WEB" = "true" ]; then + find extensions -type f -name "$VSIX_PATTERN" ! -iname '*-web-*' -print0 + else + find extensions -type f -name "$VSIX_PATTERN" -print0 + fi + ) diff --git a/README.md b/README.md index 6db4eaa..17da627 100644 --- a/README.md +++ b/README.md @@ -767,7 +767,7 @@ jobs: ### vscode-publish-release-vsix -Downloads every VSIX asset from a GitHub release in the calling repository and publishes it to the VS Code Marketplace. VSIX files are found recursively, the release's pre-release state is preserved, and already-published versions are skipped. +Downloads every VSIX asset from a GitHub release in the calling repository and publishes it to the VS Code Marketplace using a `VSCE_PERSONAL_ACCESS_TOKEN` PAT. VSIX files are found recursively, the release's pre-release state is preserved, and already-published versions are skipped. ```yaml jobs: @@ -779,6 +779,24 @@ jobs: secrets: inherit ``` +**Publishing via Marketplace OIDC trusted publishing instead of a PAT?** Use the `vscode/publish-release-vsix` composite action directly in your own job instead of this reusable workflow. The Marketplace's OIDC trust check keys off `job_workflow_ref`, which for a nested reusable *workflow* always points at this repo rather than the caller's -- so OIDC publishing only works when the publish step runs inside the caller's own job: + +```yaml +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # vsce exchanges this job's OIDC token for a Marketplace publishing token + steps: + - uses: salesforcecli/github-workflows/.github/actions/vscode/publish-release-vsix@main + with: + release-tag: v67.10.0 + dry-run: true # Download and inspect without publishing +``` + +This requires a Trusted Publishing policy registered for the calling repo + this exact workflow filename on the Marketplace publisher management page. + ### openvsx-publish-release-vsix Downloads every VSIX asset from a GitHub release in the calling repository and publishes it to Open VSX. VSIX files are found recursively, the release's pre-release state is preserved, and already-published versions are skipped.