diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9af7019..b39edf0 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -30,7 +30,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 24 - name: Enable corepack run: corepack enable pnpm diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..d8926a7 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,132 @@ +name: Publish + +on: + workflow_dispatch: + inputs: + bump: + description: "Version bump type" + required: true + type: choice + options: + - patch + - minor + - major + - prepatch + - preminor + - premajor + - prerelease + preid: + description: + "Prerelease identifier (alpha, beta, rc). Only used with pre* bumps." + required: false + type: string + dry_run: + description: "Dry run — skip publish, push, and release" + required: false + type: boolean + default: false + +concurrency: + group: publish + cancel-in-progress: false + +jobs: + checks: + if: github.ref == 'refs/heads/main' + uses: ./.github/workflows/checks.yml + + publish: + if: github.ref == 'refs/heads/main' + needs: checks + runs-on: ubuntu-latest + # Authentication is handled via OIDC trusted publishing (id-token), + # so no NPM_TOKEN secret is needed. + permissions: + contents: write + id-token: write + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 24 + registry-url: "https://registry.npmjs.org" + + - name: Enable corepack + run: corepack enable pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build + run: pnpm build + + - name: Configure git + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + - name: Bump version + id: version + env: + BUMP: ${{ inputs.bump }} + PREID: ${{ inputs.preid }} + run: | + ARGS=("$BUMP") + if [[ "$BUMP" == pre* && -n "$PREID" ]]; then + ARGS+=(--preid "$PREID") + fi + + npm version "${ARGS[@]}" --git-tag-version true + + VERSION=$(node -p "require('./package.json').version") + TAG="v${VERSION}" + + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "tag=${TAG}" >> $GITHUB_OUTPUT + + if [[ "$VERSION" == *-* ]]; then + echo "dist_tag=next" >> $GITHUB_OUTPUT + echo "prerelease=true" >> $GITHUB_OUTPUT + else + echo "dist_tag=latest" >> $GITHUB_OUTPUT + echo "prerelease=false" >> $GITHUB_OUTPUT + fi + + - name: Publish summary + run: | + echo "### Publish Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Version:** ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "- **Tag:** ${{ steps.version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY + echo "- **Dist tag:** ${{ steps.version.outputs.dist_tag }}" >> $GITHUB_STEP_SUMMARY + echo "- **Prerelease:** ${{ steps.version.outputs.prerelease }}" >> $GITHUB_STEP_SUMMARY + echo "- **Dry run:** ${{ inputs.dry_run }}" >> $GITHUB_STEP_SUMMARY + + # Publish before push: npm publish is not retryable (same version + # can't be published twice), while git push is idempotent. If push + # fails after a successful publish, it can simply be retried manually. + - name: Publish to npm + if: ${{ inputs.dry_run == false }} + run: | + npm publish --provenance --tag ${{ steps.version.outputs.dist_tag }} + + - name: Push commit and tag + if: ${{ inputs.dry_run == false }} + run: git push origin HEAD --follow-tags + + - name: Create GitHub Release + if: ${{ inputs.dry_run == false }} + run: | + PRERELEASE_FLAG="" + if [[ "${{ steps.version.outputs.prerelease }}" == "true" ]]; then + PRERELEASE_FLAG="--prerelease" + fi + + gh release create "${{ steps.version.outputs.tag }}" \ + --generate-notes \ + $PRERELEASE_FLAG + env: + GH_TOKEN: ${{ github.token }}