commands.yml 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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: Run make fix-all
  59. id: fix
  60. run: |
  61. set -e
  62. make fix-all || {
  63. echo "make_failed=true" >> $GITHUB_OUTPUT
  64. exit 1
  65. }
  66. echo "make_failed=false" >> $GITHUB_OUTPUT
  67. - name: Commit and push changes
  68. id: commit
  69. if: success()
  70. env:
  71. GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  72. run: |
  73. git add -A
  74. if git diff --cached --quiet; then
  75. echo "no_changes=true" >> $GITHUB_OUTPUT
  76. echo "No changes to commit."
  77. else
  78. echo "no_changes=false" >> $GITHUB_OUTPUT
  79. git config user.name "github-actions[bot]"
  80. git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
  81. # Get PR info
  82. PR_JSON=$(gh pr view ${{ github.event.issue.number }} --json headRepository,headRefName,maintainerCanModify)
  83. HEAD_REPO=$(echo "$PR_JSON" | jq -r '.headRepository.nameWithOwner')
  84. HEAD_BRANCH=$(echo "$PR_JSON" | jq -r '.headRefName')
  85. CAN_MODIFY=$(echo "$PR_JSON" | jq -r '.maintainerCanModify')
  86. echo "Head repo: $HEAD_REPO"
  87. echo "Head branch: $HEAD_BRANCH"
  88. echo "Maintainer can modify: $CAN_MODIFY"
  89. # Create commit
  90. git commit -m "chore: make fix-all"
  91. COMMIT_SHA=$(git rev-parse HEAD)
  92. echo "commit_sha=$COMMIT_SHA" >> $GITHUB_OUTPUT
  93. # Try to push
  94. if git push https://x-access-token:${GH_TOKEN}@github.com/${HEAD_REPO}.git HEAD:${HEAD_BRANCH}; then
  95. echo "pushed=true" >> $GITHUB_OUTPUT
  96. echo "Successfully pushed to $HEAD_REPO"
  97. else
  98. echo "pushed=false" >> $GITHUB_OUTPUT
  99. echo "Failed to push!"
  100. exit 1
  101. fi
  102. fi
  103. - name: Post completion comment
  104. uses: actions/github-script@v8
  105. if: always()
  106. with:
  107. script: |
  108. const makeFailed = '${{ steps.fix.outputs.make_failed }}' === 'true';
  109. const noChanges = '${{ steps.commit.outputs.no_changes || 'false' }}' === 'true';
  110. const pushed = '${{ steps.commit.outputs.pushed || 'false' }}' === 'true';
  111. const commitSha = '${{ steps.commit.outputs.commit_sha }}';
  112. const jobStatus = '${{ job.status }}';
  113. let message;
  114. if (jobStatus === 'success') {
  115. if (noChanges) {
  116. message = '✅ Command `/fix-all` completed with no change.';
  117. } else if (pushed) {
  118. message = `🔧 Command \`/fix-all\` made some fixes and committed as ${commitSha}`;
  119. } else {
  120. // Should not happen
  121. message = 'ℹ️ Command `/fix-all` completed, but strangely.';
  122. }
  123. } else if (makeFailed) {
  124. message = `❌ Command \`/fix-all\` failed. Check the [workflow run](${context.payload.repository.html_url}/actions/runs/${context.runId}) for details.`;
  125. } else {
  126. message = `⚠️ Command \`/fix-all\` ran successfully, but changes could not be pushed.\n\n`;
  127. message += `* Please check that your PR settings “Allow edits from maintainers” is enabled.\n`;
  128. message += `* Or run \`make fix-all\` locally and push to your branch.`;
  129. }
  130. await github.rest.issues.createComment({
  131. owner: context.repo.owner,
  132. repo: context.repo.repo,
  133. issue_number: context.issue.number,
  134. body: message
  135. });