feat(status): show bot version in /status #274
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: Publish | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| id-token: write | |
| concurrency: | |
| group: publish-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| publish: | |
| name: Publish from main version bump | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| registry-url: "https://registry.npmjs.org" | |
| cache: npm | |
| - name: Show tool versions | |
| run: | | |
| node --version | |
| npm --version | |
| - name: Determine release state | |
| id: determine | |
| run: | | |
| set -euo pipefail | |
| PACKAGE_NAME=$(node -p "require('./package.json').name") | |
| CURRENT_VERSION=$(node -p "require('./package.json').version") | |
| echo "package_name=$PACKAGE_NAME" >> "$GITHUB_OUTPUT" | |
| echo "current_version=$CURRENT_VERSION" >> "$GITHUB_OUTPUT" | |
| STABLE_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+$' | |
| RC_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$' | |
| if [[ "$CURRENT_VERSION" =~ $STABLE_PATTERN ]]; then | |
| echo "dist_tag=latest" >> "$GITHUB_OUTPUT" | |
| echo "is_prerelease=false" >> "$GITHUB_OUTPUT" | |
| elif [[ "$CURRENT_VERSION" =~ $RC_PATTERN ]]; then | |
| echo "dist_tag=next" >> "$GITHUB_OUTPUT" | |
| echo "is_prerelease=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Unsupported version format: $CURRENT_VERSION" | |
| echo "Allowed formats: X.Y.Z and X.Y.Z-rc.N" | |
| exit 1 | |
| fi | |
| git fetch --tags --force | |
| TAG_NAME="v$CURRENT_VERSION" | |
| if git tag -l "$TAG_NAME" | grep -q "$TAG_NAME"; then | |
| echo "Tag already exists: $TAG_NAME" | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "Release candidate detected: tag is missing for current package version" | |
| echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT" | |
| echo "should_release=true" >> "$GITHUB_OUTPUT" | |
| - name: No release needed | |
| if: steps.determine.outputs.should_release != 'true' | |
| run: 'echo "Skipping publish: no eligible version bump detected"' | |
| - name: Ensure npm version is not already published | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: | | |
| set -euo pipefail | |
| PACKAGE_NAME="${{ steps.determine.outputs.package_name }}" | |
| CURRENT_VERSION="${{ steps.determine.outputs.current_version }}" | |
| if npm view "$PACKAGE_NAME@$CURRENT_VERSION" version >/dev/null 2>&1; then | |
| echo "Version already exists on npm: $PACKAGE_NAME@$CURRENT_VERSION" | |
| exit 1 | |
| fi | |
| - name: Install dependencies | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: npm ci | |
| - name: Lint | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: npm run lint | |
| - name: Typecheck | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: npm run typecheck | |
| - name: Build | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: npm run build | |
| - name: Test | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: npm run test | |
| - name: Generate release notes | |
| if: steps.determine.outputs.should_release == 'true' | |
| id: notes | |
| run: | | |
| set -euo pipefail | |
| CURRENT_VERSION="${{ steps.determine.outputs.current_version }}" | |
| BODY_FILE="$RUNNER_TEMP/release-notes.md" | |
| CURATED_FILE="docs/release-notes/v${CURRENT_VERSION}.md" | |
| # Prefer curated release notes committed alongside the version bump; | |
| # fall back to generating them from the commit log when absent. | |
| if [[ -f "$CURATED_FILE" ]]; then | |
| echo "Using curated release notes: $CURATED_FILE" | |
| cp "$CURATED_FILE" "$BODY_FILE" | |
| else | |
| echo "No curated release notes found; generating from commit log" | |
| node scripts/generate-release-notes.mjs \ | |
| --version "$CURRENT_VERSION" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --output "$BODY_FILE" | |
| fi | |
| echo "body_file=$BODY_FILE" >> "$GITHUB_OUTPUT" | |
| - name: Publish to npm | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: | | |
| if [ "${{ github.event.repository.private }}" = "true" ]; then | |
| echo "Private repository detected: publishing without provenance" | |
| npm publish --access public --tag ${{ steps.determine.outputs.dist_tag }} | |
| else | |
| echo "Public repository detected: publishing with provenance" | |
| npm publish --access public --tag ${{ steps.determine.outputs.dist_tag }} --provenance | |
| fi | |
| - name: Create and push git tag | |
| if: steps.determine.outputs.should_release == 'true' | |
| run: | | |
| set -euo pipefail | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git tag "${{ steps.determine.outputs.tag_name }}" | |
| git push origin "${{ steps.determine.outputs.tag_name }}" | |
| - name: Create GitHub release | |
| if: steps.determine.outputs.should_release == 'true' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.determine.outputs.tag_name }} | |
| name: ${{ steps.determine.outputs.tag_name }} | |
| body_path: ${{ steps.notes.outputs.body_file }} | |
| prerelease: ${{ steps.determine.outputs.is_prerelease == 'true' }} |