From 877056a59160052fc2eabdf694f775222c136d93 Mon Sep 17 00:00:00 2001 From: Ryan Anderson Date: Tue, 23 Dec 2025 12:25:00 -0600 Subject: [PATCH 1/2] feat: auto-version and publish on merge to main - Automatically bumps patch version on merge to main - Creates git tag and pushes it - Tag push triggers ci.yml to publish to npm - Skips workflow on version bump commits to prevent loops --- .github/workflows/release.yml | 78 ++++++++++++++--------------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9159a55..5c72d56 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,30 +9,53 @@ on: permissions: contents: write pull-requests: write + id-token: write jobs: - version-packages: + auto-version-and-publish: runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: + - name: Check if should skip + id: skip + run: | + if [[ "${{ github.event.head_commit.message }}" == *"[skip ci]"* ]] || [[ "${{ github.event.head_commit.message }}" == *"chore: bump version"* ]]; then + echo "should_skip=true" >> $GITHUB_OUTPUT + else + echo "should_skip=false" >> $GITHUB_OUTPUT + fi + - uses: actions/checkout@v4 + if: steps.skip.outputs.should_skip != 'true' with: fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/setup-node@v4 with: node-version: '24' cache: 'npm' + registry-url: 'https://registry.npmjs.org' - name: Install dependencies run: npm ci - - name: Create or update version PR - uses: changesets/action@v1 - with: - version: npm run version-packages - commit: "chore: version packages" - title: "chore: version packages" + - name: Auto-version patch + run: | + npm version patch --no-git-tag-version + VERSION=$(node -p "require('./package.json').version") + echo "NEW_VERSION=$VERSION" >> $GITHUB_ENV + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add package.json package-lock.json + git commit -m "chore: bump version to $VERSION [skip ci]" + git push + + - name: Create and push tag + run: | + VERSION=$(node -p "require('./package.json').version") + git tag -a "v$VERSION" -m "Release v$VERSION" + git push origin "v$VERSION" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -83,44 +106,3 @@ jobs: merge_method: 'squash' }); - tag-on-version: - runs-on: ubuntu-latest - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - steps: - - name: Check if version commit - id: check - run: | - if [[ "${{ github.event.head_commit.message }}" == *"chore: version packages"* ]]; then - echo "is_version=true" >> $GITHUB_OUTPUT - else - echo "is_version=false" >> $GITHUB_OUTPUT - fi - - - uses: actions/checkout@v4 - if: steps.check.outputs.is_version == 'true' - with: - fetch-depth: 0 - - - uses: actions/setup-node@v4 - if: steps.check.outputs.is_version == 'true' - with: - node-version: '24' - cache: 'npm' - - - name: Install dependencies - if: steps.check.outputs.is_version == 'true' - run: npm ci - - - name: Create tags from Changesets - if: steps.check.outputs.is_version == 'true' - run: npx changeset tag - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Push tags - if: steps.check.outputs.is_version == 'true' - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git push --follow-tags - From 4c89b88e965a8b6383ca88e7cdedf90d3ec0eea6 Mon Sep 17 00:00:00 2001 From: Ryan Anderson Date: Tue, 23 Dec 2025 12:26:22 -0600 Subject: [PATCH 2/2] feat: create GitHub Release when tag is created - Automatically creates a GitHub Release with the tag - Generates release notes from recent commits - Excludes version bump commits from release notes --- .github/workflows/release.yml | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c72d56..12ec88c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,13 +52,50 @@ jobs: git push - name: Create and push tag + if: steps.skip.outputs.should_skip != 'true' + id: tag run: | VERSION=$(node -p "require('./package.json').version") git tag -a "v$VERSION" -m "Release v$VERSION" git push origin "v$VERSION" + echo "version=$VERSION" >> $GITHUB_OUTPUT env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create GitHub Release + if: steps.skip.outputs.should_skip != 'true' + uses: actions/github-script@v7 + with: + script: | + const version = '${{ steps.tag.outputs.version }}'; + const tagName = `v${version}`; + + // Get the latest commits for release notes + const { data: commits } = await github.rest.repos.listCommits({ + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 10 + }); + + // Generate release notes from recent commits (excluding version bumps) + const releaseNotes = commits + .filter(commit => !commit.commit.message.includes('chore: bump version')) + .slice(0, 5) + .map(commit => `- ${commit.commit.message.split('\n')[0]}`) + .join('\n'); + + const body = `## Changes\n\n${releaseNotes || 'See commit history for details.'}`; + + await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: tagName, + name: `Release ${tagName}`, + body: body, + draft: false, + prerelease: false + }); + auto-merge-version: runs-on: ubuntu-latest if: |