post-merge-pr.yml 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. name: Post-Merge Version Bump
  2. on:
  3. push:
  4. branches: [main]
  5. workflow_dispatch:
  6. inputs:
  7. skip_version_bump:
  8. description: 'Skip version bump'
  9. required: false
  10. type: boolean
  11. default: false
  12. permissions:
  13. contents: write
  14. pull-requests: write
  15. jobs:
  16. check-trigger:
  17. name: Check if Version Bump Needed
  18. runs-on: ubuntu-latest
  19. outputs:
  20. should_bump: ${{ steps.check.outputs.should_bump }}
  21. bump_type: ${{ steps.check.outputs.bump_type }}
  22. steps:
  23. - name: Checkout code
  24. uses: actions/checkout@v4
  25. with:
  26. fetch-depth: 2
  27. - name: Check if this was a version bump PR
  28. id: check_pr_labels
  29. uses: actions/github-script@v7
  30. with:
  31. script: |
  32. // Get the commit that triggered this workflow
  33. const commit = context.sha;
  34. // Find PRs that were merged with this commit
  35. const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
  36. owner: context.repo.owner,
  37. repo: context.repo.repo,
  38. commit_sha: commit
  39. });
  40. // Check if any of these PRs had the version-bump or automated label
  41. const hasVersionBumpLabel = prs.some(pr =>
  42. pr.labels.some(label =>
  43. label.name === 'version-bump' ||
  44. label.name === 'automated'
  45. )
  46. );
  47. core.setOutput('skip_version_bump', hasVersionBumpLabel);
  48. if (hasVersionBumpLabel) {
  49. console.log('This PR had version-bump or automated label - skipping to prevent loop');
  50. }
  51. - name: Determine if sync needed
  52. id: check
  53. run: |
  54. # Skip if the merged PR was a version bump PR
  55. if [ "${{ steps.check_pr_labels.outputs.skip_version_bump }}" = "true" ]; then
  56. echo "should_bump=false" >> $GITHUB_OUTPUT
  57. echo "Version bump PR detected - skipping to prevent loops"
  58. exit 0
  59. fi
  60. # Check commit title (first line only) for skip patterns
  61. COMMIT_TITLE=$(git log -1 --pretty=%s)
  62. # Skip if this is an automated version bump commit to prevent loops
  63. # Only check the title, not the full body to avoid false positives
  64. if echo "$COMMIT_TITLE" | grep -qE "^chore: bump version to v"; then
  65. echo "should_bump=false" >> $GITHUB_OUTPUT
  66. echo "Automated version bump commit detected - skipping to prevent loops"
  67. exit 0
  68. fi
  69. # Get full commit message for version bump type detection
  70. COMMIT_MSG=$(git log -1 --pretty=%B)
  71. # Determine version bump type from commit message
  72. if echo "$COMMIT_MSG" | grep -qiE "^(feat|feature)\(.*\)!:|^BREAKING CHANGE:|^[a-z]+!:"; then
  73. echo "bump_type=major" >> $GITHUB_OUTPUT
  74. elif echo "$COMMIT_MSG" | grep -qiE "^(feat|feature)(\(.*\))?:"; then
  75. echo "bump_type=minor" >> $GITHUB_OUTPUT
  76. elif echo "$COMMIT_MSG" | grep -qiE "^(fix|bugfix)(\(.*\))?:"; then
  77. echo "bump_type=patch" >> $GITHUB_OUTPUT
  78. else
  79. echo "bump_type=patch" >> $GITHUB_OUTPUT
  80. fi
  81. echo "should_bump=true" >> $GITHUB_OUTPUT
  82. echo "Will create version bump PR"
  83. create-version-bump-pr:
  84. name: Create Version Bump PR
  85. runs-on: ubuntu-latest
  86. needs: check-trigger
  87. if: |
  88. needs.check-trigger.outputs.should_bump == 'true' &&
  89. github.event.inputs.skip_version_bump != 'true'
  90. steps:
  91. - name: Checkout code
  92. uses: actions/checkout@v4
  93. with:
  94. fetch-depth: 0
  95. - name: Setup Node.js
  96. uses: actions/setup-node@v4
  97. with:
  98. node-version: '20'
  99. - name: Configure Git
  100. run: |
  101. git config user.name "github-actions[bot]"
  102. git config user.email "github-actions[bot]@users.noreply.github.com"
  103. - name: Create version bump branch
  104. id: create_branch
  105. run: |
  106. BRANCH_NAME="chore/version-bump-$(date +%Y%m%d-%H%M%S)"
  107. echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
  108. git checkout -b "$BRANCH_NAME"
  109. - name: Bump version
  110. id: bump_version
  111. run: |
  112. BUMP_TYPE="${{ needs.check-trigger.outputs.bump_type }}"
  113. # Get current version
  114. CURRENT_VERSION=$(cat VERSION)
  115. echo "Current version: $CURRENT_VERSION"
  116. # Bump version
  117. npm run version:bump:$BUMP_TYPE
  118. # Get new version
  119. NEW_VERSION=$(cat VERSION)
  120. echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
  121. echo "New version: $NEW_VERSION"
  122. - name: Update CHANGELOG
  123. run: |
  124. NEW_VERSION="${{ steps.bump_version.outputs.new_version }}"
  125. DATE=$(date +%Y-%m-%d)
  126. COMMIT_TITLE=$(git log -1 --pretty=%s)
  127. # Create changelog entry
  128. printf "## [%s] - %s\n\n### Changes\n- %s\n\n" "$NEW_VERSION" "$DATE" "$COMMIT_TITLE" > /tmp/changelog_entry.md
  129. # Prepend to CHANGELOG.md (after the header)
  130. if [ -f CHANGELOG.md ]; then
  131. awk '/^## \[/ && !found {print; system("cat /tmp/changelog_entry.md"); found=1; next} 1' CHANGELOG.md > /tmp/changelog_new.md
  132. mv /tmp/changelog_new.md CHANGELOG.md
  133. fi
  134. - name: Commit version bump
  135. run: |
  136. NEW_VERSION="${{ steps.bump_version.outputs.new_version }}"
  137. git add VERSION package.json CHANGELOG.md
  138. git commit -m "chore: bump version to v$NEW_VERSION"
  139. - name: Push branch
  140. run: |
  141. BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
  142. git push -u origin "$BRANCH_NAME"
  143. - name: Create Pull Request
  144. id: create_pr
  145. run: |
  146. NEW_VERSION="${{ steps.bump_version.outputs.new_version }}"
  147. BUMP_TYPE="${{ needs.check-trigger.outputs.bump_type }}"
  148. BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
  149. # Create PR body
  150. cat > /tmp/pr_body.md << 'EOFPR'
  151. ## 🤖 Automated Version Bump
  152. ### Version Update
  153. - **New Version:** v$NEW_VERSION
  154. - **Bump Type:** $BUMP_TYPE
  155. ### Changes Included
  156. - ✅ VERSION file updated
  157. - ✅ package.json version updated
  158. - ✅ CHANGELOG.md updated with latest changes
  159. ### Next Steps
  160. 1. Review the version bump is correct
  161. 2. Merge this PR to apply the version bump
  162. ---
  163. **Note:** This PR was created automatically by the post-merge workflow.
  164. **Documentation updates:** If registry or component changes require documentation updates, the separate "Sync Documentation" workflow will handle that automatically when `registry.json` or `.opencode/` files are modified.
  165. EOFPR
  166. # Replace variables
  167. sed -i "s/\$NEW_VERSION/$NEW_VERSION/g" /tmp/pr_body.md
  168. sed -i "s/\$BUMP_TYPE/$BUMP_TYPE/g" /tmp/pr_body.md
  169. # Create PR
  170. gh pr create \
  171. --title "chore: bump version to v$NEW_VERSION" \
  172. --body-file /tmp/pr_body.md \
  173. --base main \
  174. --head "$BRANCH_NAME" \
  175. --label "automated,version-bump"
  176. env:
  177. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}