Release #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: 'Dry run: package and upload the VSIX artifacts only, skip publishing' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| # A real release may only be dispatched from `main`: `gh workflow run --ref` | |
| # accepts any branch or tag, and publishing plus tagging from anywhere else | |
| # would permanently release the wrong commit. Dry runs are allowed from any | |
| # ref so a branch can rehearse the packaging matrix. Failing here (instead | |
| # of silently skipping the publish steps) makes the mistake visible. | |
| preflight: | |
| name: Preflight | |
| if: github.repository == 'rstackjs/rstack-editor' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Require main for a real release | |
| if: ${{ !inputs.dry_run && github.ref != 'refs/heads/main' }} | |
| run: | | |
| echo "::error::A real release must be dispatched from main (got ${GITHUB_REF}). Re-run with dry run enabled, or dispatch from main." | |
| exit 1 | |
| release_vscode_extension: | |
| name: Release VS Code Extension (${{ matrix.vsce-target }}) | |
| needs: preflight | |
| runs-on: ${{ matrix.runner }} | |
| environment: vscode-marketplace | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-latest | |
| vsce-target: linux-x64 | |
| arch: x64 | |
| - runner: ubuntu-22.04 | |
| vsce-target: linux-arm64 | |
| arch: arm64 | |
| - runner: macos-15 | |
| vsce-target: darwin-x64 | |
| arch: x64 | |
| - runner: macos-15 | |
| vsce-target: darwin-arm64 | |
| arch: arm64 | |
| - runner: windows-2022 | |
| vsce-target: win32-x64 | |
| arch: x64 | |
| - runner: windows-latest | |
| vsce-target: win32-arm64 | |
| arch: arm64 | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| # rslib.config.mts keys the staged `@yuku-parser/binding-*` napi payload | |
| # off this variable (Linux targets get a `-gnu` suffix appended there). | |
| VSCE_TARGET: ${{ matrix.vsce-target }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| fetch-depth: 1 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | |
| with: | |
| node-version: 22 | |
| cache: 'pnpm' | |
| cache-dependency-path: pnpm-lock.yaml | |
| # `supportedArchitectures` must be set BEFORE `pnpm install` so pnpm also | |
| # fetches the cross-target optional `@yuku-parser/binding-*` package (the | |
| # Linux runners' current libc is glibc, matching the `-gnu` bindings the | |
| # linux-* VSIX targets need). | |
| - name: Install Dependencies | |
| run: | | |
| pnpm config set --location=project --json supportedArchitectures '{"cpu":["current","${{ matrix.arch }}"]}' | |
| pnpm install | |
| - name: Build | |
| run: pnpm run build | |
| - name: Package VS Code Extension | |
| working-directory: packages/vscode | |
| run: pnpm exec vsce package --target ${{ matrix.vsce-target }} -o rstack-${{ matrix.vsce-target }}.vsix | |
| - name: Upload VSIX Artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: rstack-${{ matrix.vsce-target }} | |
| path: packages/vscode/rstack-${{ matrix.vsce-target }}.vsix | |
| if-no-files-found: error | |
| - name: Publish VS Code Extension | |
| if: ${{ !inputs.dry_run }} | |
| working-directory: packages/vscode | |
| env: | |
| VSCE_PAT: ${{ secrets.VSCE_PAT }} | |
| run: pnpm exec vsce publish --target ${{ matrix.vsce-target }} --skip-duplicate | |
| - name: Publish OVSX Extension | |
| if: ${{ !inputs.dry_run }} | |
| working-directory: packages/vscode | |
| env: | |
| OVSX_PAT: ${{ secrets.OVSX_PAT }} | |
| run: pnpm exec ovsx publish --target ${{ matrix.vsce-target }} --skip-duplicate | |
| # Runs only for a real release: a dry run must leave no tag behind. The tag | |
| # points at the commit that was actually published (github.sha), the release | |
| # notes come from the conventional commits since the previous tag, and the | |
| # VSIX of every matrix target is attached as an asset so a release can be | |
| # installed by hand (`code --install-extension`) without either marketplace. | |
| github_release: | |
| name: Tag and GitHub Release | |
| needs: release_vscode_extension | |
| if: ${{ !inputs.dry_run }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| # changelogithub needs the tags and history to find the previous | |
| # release and list the commits since it; the tag step compares an | |
| # existing tag's target against this commit. | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | |
| with: | |
| node-version: 22 | |
| - name: Download VSIX Artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: rstack-* | |
| path: vsix | |
| merge-multiple: true | |
| - name: Read Version | |
| id: version | |
| run: echo "tag=v$(node -p "require('./packages/vscode/package.json').version")" >> "$GITHUB_OUTPUT" | |
| # Idempotent for a re-run of the same commit (e.g. after one marketplace | |
| # publish flaked and `--skip-duplicate` covered the rest), but a tag that | |
| # already points at a *different* commit means the version was never | |
| # bumped after the last release: fail instead of attaching VSIX files | |
| # built from this commit to a release tagged at another one. | |
| - name: Push Tag | |
| env: | |
| TAG: ${{ steps.version.outputs.tag }} | |
| run: | | |
| existing=$(git rev-parse --verify --quiet "refs/tags/$TAG^{commit}" || true) | |
| if [ -z "$existing" ]; then | |
| git tag "$TAG" "$GITHUB_SHA" | |
| git push origin "refs/tags/$TAG" | |
| elif [ "$existing" = "$GITHUB_SHA" ]; then | |
| echo "tag $TAG already points at $GITHUB_SHA, leaving it as is" | |
| else | |
| echo "::error::tag $TAG already exists at $existing but this run is at $GITHUB_SHA — bump the version (pnpm bump) before releasing again." | |
| exit 1 | |
| fi | |
| - name: GitHub Release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAG: ${{ steps.version.outputs.tag }} | |
| run: | | |
| npx changelogithub@15.0.4 --to "$TAG" --assets 'vsix/*.vsix' |