commands.yml 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. name: Trigger actions on PR comments
  2. on:
  3. issue_comment:
  4. types: [created]
  5. permissions:
  6. contents: write
  7. pull-requests: write
  8. issues: write
  9. jobs:
  10. fix-all:
  11. if: |
  12. github.event.issue.pull_request != null &&
  13. github.event.comment.body == '/fix-all' &&
  14. (
  15. github.event.comment.author_association == 'OWNER' ||
  16. github.event.comment.author_association == 'MEMBER' ||
  17. (github.event.comment.user != null && github.event.comment.user.login == github.event.issue.user.login)
  18. )
  19. runs-on: ubuntu-latest
  20. steps:
  21. - name: Post acknowledgment comment
  22. uses: actions/github-script@v8
  23. with:
  24. script: |
  25. await github.rest.issues.createComment({
  26. owner: context.repo.owner,
  27. repo: context.repo.repo,
  28. issue_number: context.issue.number,
  29. body: '🤖 Command `/fix-all` received. Running…'
  30. });
  31. - name: Get PR details
  32. uses: actions/github-script@v8
  33. id: pr
  34. with:
  35. script: |
  36. const pr = await github.rest.pulls.get({
  37. owner: context.repo.owner,
  38. repo: context.repo.repo,
  39. pull_number: context.issue.number
  40. });
  41. if (pr.data.state !== 'open') {
  42. await github.rest.issues.createComment({
  43. owner: context.repo.owner,
  44. repo: context.repo.repo,
  45. issue_number: context.issue.number,
  46. body: '⚠️ Command `/fix-all` can only be run on open pull requests.'
  47. });
  48. core.setFailed('PR is not open');
  49. return;
  50. }
  51. return pr.data.head;
  52. - name: Checkout PR branch
  53. uses: actions/checkout@v5
  54. with:
  55. token: ${{ secrets.GITHUB_TOKEN }}
  56. repository: ${{ fromJSON(steps.pr.outputs.result).repo.full_name }}
  57. ref: ${{ fromJSON(steps.pr.outputs.result).ref }}
  58. - name: Use Composer cache
  59. id: composer-cache
  60. uses: actions/cache@v4
  61. with:
  62. path: vendor
  63. key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
  64. restore-keys: |
  65. ${{ runner.os }}-php-
  66. - name: Run Composer install
  67. run: composer install --prefer-dist --no-progress
  68. if: steps.composer-cache.outputs.cache-hit != 'true'
  69. - name: Uses Node.js
  70. uses: actions/setup-node@v5
  71. with:
  72. node-version: lts/*
  73. cache: npm
  74. - run: npm ci
  75. - name: Run make fix-all
  76. id: fix
  77. run: |
  78. set -e
  79. make fix-all || {
  80. echo "make_failed=true" >> $GITHUB_OUTPUT
  81. exit 1
  82. }
  83. echo "make_failed=false" >> $GITHUB_OUTPUT
  84. - name: Commit and push changes
  85. id: commit
  86. if: success()
  87. env:
  88. GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  89. HEAD_REPO: ${{ fromJSON(steps.pr.outputs.result).repo.full_name }}
  90. HEAD_BRANCH: ${{ fromJSON(steps.pr.outputs.result).ref }}
  91. run: |
  92. git add -A
  93. if git diff --cached --quiet; then
  94. echo "no_changes=true" >> $GITHUB_OUTPUT
  95. echo "No changes to commit."
  96. else
  97. echo "no_changes=false" >> $GITHUB_OUTPUT
  98. git config user.name "github-actions[bot]"
  99. git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
  100. echo "Head repo: $HEAD_REPO"
  101. echo "Head branch: $HEAD_BRANCH"
  102. # Create commit
  103. git commit -m "chore: make fix-all"
  104. COMMIT_SHA=$(git rev-parse HEAD)
  105. echo "commit_sha=$COMMIT_SHA" >> $GITHUB_OUTPUT
  106. # Try to push
  107. if git push https://x-access-token:${GH_TOKEN}@github.com/${HEAD_REPO}.git HEAD:${HEAD_BRANCH}; then
  108. echo "pushed=true" >> $GITHUB_OUTPUT
  109. echo "Successfully pushed to $HEAD_REPO"
  110. else
  111. echo "pushed=false" >> $GITHUB_OUTPUT
  112. echo "Failed to push!"
  113. exit 1
  114. fi
  115. fi
  116. - name: Post completion comment
  117. uses: actions/github-script@v8
  118. if: always()
  119. with:
  120. script: |
  121. const makeFailed = '${{ steps.fix.outputs.make_failed }}' === 'true';
  122. const noChanges = '${{ steps.commit.outputs.no_changes || 'false' }}' === 'true';
  123. const pushed = '${{ steps.commit.outputs.pushed || 'false' }}' === 'true';
  124. const commitSha = '${{ steps.commit.outputs.commit_sha }}';
  125. const jobStatus = '${{ job.status }}';
  126. let message;
  127. if (jobStatus === 'success') {
  128. if (noChanges) {
  129. message = '✅ Command `/fix-all` completed with no change.';
  130. } else if (pushed) {
  131. message = `🔧 Command \`/fix-all\` made some fixes and committed as ${commitSha}`;
  132. } else {
  133. // Should not happen
  134. message = 'ℹ️ Command `/fix-all` completed, but strangely.';
  135. }
  136. } else if (makeFailed) {
  137. message = `❌ Command \`/fix-all\` failed. Check the [workflow run](${context.payload.repository.html_url}/actions/runs/${context.runId}) for details.`;
  138. } else {
  139. message = `⚠️ Command \`/fix-all\` ran successfully, but changes could not be pushed.\n\n`;
  140. message += `* Please check that your PR settings “Allow edits from maintainers” is enabled.\n`;
  141. message += `* Or run \`make fix-all\` locally and push to your branch.`;
  142. }
  143. await github.rest.issues.createComment({
  144. owner: context.repo.owner,
  145. repo: context.repo.repo,
  146. issue_number: context.issue.number,
  147. body: message
  148. });