pr_format_bot.yml 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. name: PR Format Notification
  2. on:
  3. pull_request_target:
  4. types: [opened]
  5. concurrency:
  6. group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  7. cancel-in-progress: true
  8. permissions:
  9. pull-requests: write
  10. contents: read
  11. jobs:
  12. notify-format:
  13. if: github.repository_owner == 'RT-Thread'
  14. runs-on: ubuntu-latest
  15. steps:
  16. - name: Check if first commit and add comment
  17. env:
  18. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  19. PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
  20. PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
  21. PR_NUMBER: ${{ github.event.pull_request.number }}
  22. PR_ACTION: ${{ github.event.action }}
  23. REPO_FULL_NAME: ${{ github.repository }}
  24. run: |
  25. echo "Event action: $PR_ACTION"
  26. # 获取 PR 的提交信息
  27. commits=$(curl -s \
  28. -H "Accept: application/vnd.github.v3+json" \
  29. -H "Authorization: Bearer $GITHUB_TOKEN" \
  30. "https://api.github.com/repos/${REPO_FULL_NAME}/pulls/${PR_NUMBER}/commits")
  31. # 检查 API 响应是否为数组
  32. if echo "$commits" | jq -e 'type == "array"' > /dev/null; then
  33. commit_count=$(echo "$commits" | jq '. | length')
  34. echo "PR commit count: $commit_count"
  35. should_comment=false
  36. if [ "$PR_ACTION" = "opened" ]; then
  37. should_comment=true
  38. elif [ "$PR_ACTION" = "synchronize" ] && [ "$commit_count" -eq 1 ]; then
  39. should_comment=true
  40. fi
  41. if [ "$should_comment" = true ]; then
  42. echo "Adding format notification comment..."
  43. # 构建工作流链接
  44. branch="$PR_HEAD_REF"
  45. fork_repo="$PR_HEAD_REPO"
  46. workflow_url="https://github.com/${fork_repo}/actions/workflows/pr_clang_format.yml"
  47. direct_link="${workflow_url}?branch=${branch}"
  48. # 使用数组存储多行消息
  49. message_lines=(
  50. "<!-- PR Format Notification Comment -->"
  51. "**👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!**"
  52. ""
  53. "为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。"
  54. "To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run)."
  55. ""
  56. "---"
  57. ""
  58. "### 🛠 操作步骤 | Steps"
  59. ""
  60. "1. **前往 Actions 页面 | Go to the Actions page**"
  61. "[点击进入工作流 → | Click to open workflow →](${direct_link})"
  62. ""
  63. "2. **点击 \`Run workflow\` | Click \`Run workflow\`**"
  64. "- 设置需排除的文件/目录(目录请以\"/\"结尾)"
  65. "Set files/directories to exclude (directories should end with \"/\")"
  66. "- 将目标分支设置为 \ Set the target branch to:**\`${branch}\`**"
  67. "- 设置PR number为 \ Set the PR number to:**\`${PR_NUMBER}\`**"
  68. ""
  69. "3. **等待工作流完成 | Wait for the workflow to complete**"
  70. "格式化后的代码将自动推送至你的分支。"
  71. "The formatted code will be automatically pushed to your branch."
  72. ""
  73. "完成后,提交将自动更新至 \`${branch}\` 分支,关联的 Pull Request 也会同步更新。"
  74. "Once completed, commits will be pushed to the \`${branch}\` branch automatically, and the related Pull Request will be updated."
  75. ""
  76. "如有问题欢迎联系我们,再次感谢您的贡献!💐"
  77. "If you have any questions, feel free to reach out. Thanks again for your contribution!"
  78. )
  79. # 拼接数组为多行字符串
  80. message=$(printf "%s\n" "${message_lines[@]}")
  81. echo "Message content:"
  82. echo "$message"
  83. # 查找现有的 bot 评论
  84. existing_comment=$(curl -s \
  85. -H "Accept: application/vnd.github.v3+json" \
  86. -H "Authorization: Bearer $GITHUB_TOKEN" \
  87. "https://api.github.com/repos/${REPO_FULL_NAME}/issues/${PR_NUMBER}/comments" | \
  88. jq -r '.[] | select(.user.login == "github-actions[bot]" and (.body | contains("<!-- PR Format Notification Comment -->"))) | {id: .id, body: .body} | @base64')
  89. # 使用 jq 安全地构建 JSON 负载
  90. json_payload=$(jq -n --arg body "$message" '{"body": $body}')
  91. if [[ -n "$existing_comment" ]]; then
  92. # 更新现有评论
  93. comment_id=$(echo "$existing_comment" | head -1 | base64 -d | jq -r .id)
  94. echo "Updating existing comment $comment_id"
  95. response=$(curl -s -w "\n%{http_code}" \
  96. -X PATCH \
  97. -H "Accept: application/vnd.github.v3+json" \
  98. -H "Authorization: Bearer $GITHUB_TOKEN" \
  99. -d "$json_payload" \
  100. "https://api.github.com/repos/${REPO_FULL_NAME}/issues/comments/$comment_id")
  101. else
  102. # 创建新评论
  103. echo "Creating new comment"
  104. response=$(curl -s -w "\n%{http_code}" \
  105. -X POST \
  106. -H "Accept: application/vnd.github.v3+json" \
  107. -H "Authorization: Bearer $GITHUB_TOKEN" \
  108. -d "$json_payload" \
  109. "https://api.github.com/repos/${REPO_FULL_NAME}/issues/${PR_NUMBER}/comments")
  110. fi
  111. # 提取 HTTP 状态码和响应体
  112. http_code=$(echo "$response" | tail -n1)
  113. response_body=$(echo "$response" | sed '$d')
  114. if [ "$http_code" -eq 201 ] || [ "$http_code" -eq 200 ]; then
  115. echo "Format notification comment added/updated successfully"
  116. echo "Comment URL: $(echo "$response_body" | jq -r '.html_url')"
  117. else
  118. echo "Failed to add/update comment. HTTP status: $http_code"
  119. echo "Response: $response_body"
  120. exit 1
  121. fi
  122. else
  123. echo "Not the first commit, skipping comment"
  124. fi
  125. else
  126. echo "Failed to get commits from GitHub API"
  127. echo "Response: $commits"
  128. exit 1
  129. fi