Push a tag, the extension publishes itself
Publishing was a manual vsce publish. This adds one workflow: on a v* tag it verifies the tag matches the version, runs the tests, builds a production VSIX, publishes to the VS Code Marketplace and Open VSX, and cuts a GitHub Release with the .vsix attached. Releasing becomes: bump the version, commit, git tag v2.1.1 && git push origin v2.1.1.
The whole workflow — header documents the release flow and the two secrets.
.github/workflows/release.yml · 66 lines
.github/workflows/release.yml
1# Release Vibe Themer to the VS Code Marketplace (and Open VSX) on a version tag.
2#
3# Cutting a release:
4# 1. Bump "version" in package.json and update CHANGELOG.md; commit to main.
5# 2. Tag that commit and push the tag: git tag v2.1.1 && git push origin v2.1.1
6# 3. This workflow verifies the tag matches the version, builds a production VSIX,
7# publishes it, and creates a GitHub Release with the .vsix attached.
8#
9# Required repository secrets:
10# VSCE_PAT — Azure DevOps PAT for the "mseeks" Marketplace publisher (required)
11# OVSX_PAT — Open VSX access token (optional; the Open VSX step self-skips if unset)
12name: Release
14on:
15 push:
16 tags: ['v*']
18permissions:
19 contents: write # create the GitHub Release and upload the .vsix asset
21jobs:
22 release:
23 name: publish (marketplace · open vsx · gh release)
24 runs-on: ubuntu-latest
25 env:
26 # Exposed as an env var (not referenced as a secret directly) so the Open VSX
27 # step can self-skip with `if: env.OVSX_PAT != ''` when the token isn't set.
28 OVSX_PAT: ${{ secrets.OVSX_PAT }}
29 steps:
30 - uses: actions/checkout@v4
31 - uses: actions/setup-node@v4
32 with:
33 node-version: '22'
34 cache: npm
35 - run: npm ci
37 - name: Verify tag matches package.json version
38 run: |
39 PKG="$(node -p "require('./package.json').version")"
40 TAG="${GITHUB_REF_NAME#v}"
41 echo "package.json=$PKG tag=$TAG"
42 [ "$PKG" = "$TAG" ] || { echo "::error::tag v$TAG does not match package.json $PKG — bump the version, commit, then tag"; exit 1; }
44 # Don't publish a red build. vsce:prepublish already covers types/lint/bundle;
45 # this adds the node:test suite, which a tag push wouldn't otherwise run.
46 - run: npm test
48 - name: Package production VSIX
49 run: |
50 VSIX="vibe-themer-${GITHUB_REF_NAME}.vsix"
51 npx --yes @vscode/vsce package --out "$VSIX"
52 echo "VSIX=$VSIX" >> "$GITHUB_ENV"
54 - name: Publish to the VS Code Marketplace
55 run: npx --yes @vscode/vsce publish --packagePath "$VSIX"
56 env:
57 VSCE_PAT: ${{ secrets.VSCE_PAT }}
59 - name: Publish to Open VSX
60 if: ${{ env.OVSX_PAT != '' }}
61 run: npx --yes ovsx publish "$VSIX" -p "$OVSX_PAT"
63 - name: Create GitHub Release
64 run: gh release create "$GITHUB_REF_NAME" "$VSIX" --title "$GITHUB_REF_NAME" --generate-notes
65 env:
66 GH_TOKEN: ${{ github.token }}