Skip to content

Release

Release #5

Workflow file for this run

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'