Release #84
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: | |
| push: | |
| tags: | |
| - 'v*' | |
| branches-ignore: | |
| - '**' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Existing tag to publish (for backfill), e.g. v0.4.2' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| jobs: | |
| publish-release: | |
| if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - name: Resolve tag | |
| id: tag | |
| shell: bash | |
| run: | | |
| if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then | |
| TAG="${{ inputs.tag }}" | |
| else | |
| TAG="${GITHUB_REF_NAME}" | |
| fi | |
| if [[ -z "${TAG}" ]]; then | |
| echo "Tag could not be resolved." >&2 | |
| exit 1 | |
| fi | |
| echo "value=${TAG}" >> "$GITHUB_OUTPUT" | |
| - name: Verify tag | |
| shell: bash | |
| run: | | |
| TAG="${{ steps.tag.outputs.value }}" | |
| if [[ ! "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Invalid tag format: ${TAG}. Expected v<major>.<minor>.<patch>" >&2 | |
| exit 1 | |
| fi | |
| if [[ "${GITHUB_EVENT_NAME}" == "push" ]]; then | |
| PKG_VERSION="$(node -p "require('./packages/cli/package.json').version")" | |
| EXPECTED_TAG="v${PKG_VERSION}" | |
| if [[ "${TAG}" != "${EXPECTED_TAG}" ]]; then | |
| echo "Tag/version mismatch on push: got ${TAG}, expected ${EXPECTED_TAG}" >&2 | |
| exit 1 | |
| fi | |
| else | |
| if ! git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then | |
| echo "Tag not found in repository: ${TAG}" >&2 | |
| exit 1 | |
| fi | |
| fi | |
| - name: Build release notes from CHANGELOG | |
| shell: bash | |
| run: | | |
| TAG="${{ steps.tag.outputs.value }}" | |
| VERSION="${TAG#v}" | |
| awk -v version="${VERSION}" ' | |
| BEGIN { in_section=0 } | |
| $0 ~ "^## \\[" version "\\]" { in_section=1; print; next } | |
| in_section && $0 ~ "^## \\[" { exit } | |
| in_section { print } | |
| ' CHANGELOG.md > release_notes.md | |
| if [[ ! -s release_notes.md ]]; then | |
| echo "## ${TAG}" > release_notes.md | |
| echo >> release_notes.md | |
| echo "See CHANGELOG.md for release details." >> release_notes.md | |
| fi | |
| - name: Create or update GitHub Release | |
| uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.value }} | |
| name: ${{ steps.tag.outputs.value }} | |
| body_path: release_notes.md | |
| generate_release_notes: true | |
| publish-npm: | |
| if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ inputs.tag || github.ref }} | |
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 | |
| - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version: '20' | |
| cache: 'pnpm' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build | |
| run: pnpm run build | |
| # Enforces unified workspace versioning — every packages/*/package.json must match the tag. | |
| - name: Verify workspace versions match tag | |
| shell: bash | |
| run: | | |
| TAG="${{ github.event.inputs.tag || github.ref_name }}" | |
| EXPECTED="${TAG#v}" | |
| FAIL=0 | |
| for p in packages/*/package.json; do | |
| V=$(node -p "require('./$p').version") | |
| N=$(node -p "require('./$p').name") | |
| if [[ "$V" != "$EXPECTED" ]]; then | |
| echo "::error::$N version $V does not match tag $EXPECTED" | |
| FAIL=1 | |
| fi | |
| done | |
| if [[ $FAIL -ne 0 ]]; then exit 1; fi | |
| - name: Publish to npm | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: npm publish --workspaces --access public --provenance |