diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f61299d..b79ec08 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,3 @@ jobs: - name: Build and Test run: npm run build - - - name: Publish to NPM - if: startsWith(github.ref, 'refs/tags/v') - run: npm publish diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a8787b..db4bd27 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,124 +3,55 @@ name: Release on: push: branches: [ main ] - pull_request: - types: [opened, synchronize, closed] permissions: contents: write - pull-requests: write + packages: write id-token: write jobs: - create-version-pr: + release: runs-on: ubuntu-latest + # Skip if this is a version bump commit if: | - github.event_name == 'push' && - github.ref == 'refs/heads/main' && - !contains(github.event.head_commit.message, '[skip ci]') && - !contains(github.event.head_commit.message, 'chore: bump version') + !contains(github.event.head_commit.message, 'chore: bump version') && + !contains(github.event.head_commit.message, '[skip release]') steps: - uses: actions/checkout@v4 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: Bump version + - name: Get current version and bump id: version run: | - npm version patch --no-git-tag-version - VERSION=$(node -p "require('./package.json').version") - echo "version=$VERSION" >> $GITHUB_OUTPUT + CURRENT_VERSION=$(node -p "require('./package.json').version") + NEW_VERSION=$(node -e " + const v = '$CURRENT_VERSION'.split('.'); + v[2] = parseInt(v[2]) + 1; + console.log(v.join('.')); + ") + echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT + echo "Current: $CURRENT_VERSION → New: $NEW_VERSION" - - name: Create version PR - uses: peter-evans/create-pull-request@v6 - with: - token: ${{ secrets.GITHUB_TOKEN }} - branch: chore/version-bump-${{ steps.version.outputs.version }} - title: "chore: bump version to ${{ steps.version.outputs.version }}" - body: | - Automated version bump to **${{ steps.version.outputs.version }}** - - This PR will be automatically merged to trigger the release process. - commit-message: "chore: bump version to ${{ steps.version.outputs.version }}" - labels: | - automated - version-bump - - auto-merge-version-pr: - runs-on: ubuntu-latest - if: | - github.event_name == 'pull_request' && - startsWith(github.event.pull_request.title, 'chore: bump version to') && - github.event.pull_request.head.repo.full_name == github.repository && - (github.event.action == 'opened' || github.event.action == 'synchronize') - steps: - - name: Wait for checks and merge - uses: actions/github-script@v7 - with: - script: | - const maxWait = 300; - const checkInterval = 10; - let waited = 0; - - while (waited < maxWait) { - const { data: pr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number, - }); - - if (pr.mergeable === true && pr.mergeable_state === 'clean') { - await github.rest.pulls.merge({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number, - merge_method: 'squash' - }); - return; - } - - await new Promise(resolve => setTimeout(resolve, checkInterval * 1000)); - waited += checkInterval; - } - - throw new Error('Timeout waiting for PR to be mergeable'); - - create-tag-and-release: - runs-on: ubuntu-latest - if: | - github.event_name == 'pull_request' && - startsWith(github.event.pull_request.title, 'chore: bump version to') && - github.event.pull_request.merged == true - steps: - - name: Extract version from PR title - id: version + - name: Update package.json version (in memory only) run: | - VERSION=$(echo "${{ github.event.pull_request.title }}" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') - echo "version=$VERSION" >> $GITHUB_OUTPUT + npm version ${{ steps.version.outputs.version }} --no-git-tag-version --no-commit-hooks - - name: Create tag - uses: actions/github-script@v7 - with: - script: | - const version = '${{ steps.version.outputs.version }}'; - const tagName = `v${version}`; - - // Create tag via API (doesn't require checkout) - await github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: `refs/tags/${tagName}`, - sha: context.payload.pull_request.merge_commit_sha - }); + - name: Create tag from current commit + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "v${{ steps.version.outputs.version }}" -m "Release v${{ steps.version.outputs.version }}" + git push origin "v${{ steps.version.outputs.version }}" - name: Generate release notes id: release-notes @@ -130,14 +61,14 @@ jobs: const { data: commits } = await github.rest.repos.listCommits({ owner: context.repo.owner, repo: context.repo.repo, - per_page: 20, + per_page: 15, sha: 'main' }); const notes = commits .filter(c => !c.commit.message.includes('chore: bump version') && - !c.commit.message.includes('[skip ci]') + !c.commit.message.includes('[skip release]') ) .slice(0, 10) .map(c => `- ${c.commit.message.split('\n')[0]}`) @@ -145,7 +76,7 @@ jobs: core.setOutput('body', notes || 'See commit history for details.'); - - name: Create Release + - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: v${{ steps.version.outputs.version }} @@ -158,5 +89,6 @@ jobs: **Full Changelog**: https://github.com/${{ github.repository }}/compare/v${{ steps.version.outputs.version }}^...v${{ steps.version.outputs.version }} draft: false prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to npm + run: npm publish