如何避免GitHub Actions针对同一PR+Hash重复触发运行?
解决PR评论触发的GitHub Actions重复运行问题(保留当前运行,阻止新启动)
核心需求回顾
针对特定PR+提交Hash组合,在已有运行中的工作流时,阻止新的工作流启动(而非取消正在运行的实例),避免多人重复触发耗时30+分钟的任务。
方案一:使用GitHub Actions原生concurrency配置(推荐)
GitHub Actions的concurrency配置支持cancel-in-progress: false选项,正好匹配需求:当同一并发组内已有运行中的工作流时,新的运行会被直接标记为“跳过”,不会启动,同时保留当前运行的实例。
配置示例
name: 耗时PR工作流 on: issue_comment: types: [created] # 定义并发组:PR编号 + 提交Hash,确保仅同一PR同一提交的工作流会被分组 concurrency: group: pr-${{ github.event.issue.number }}-${{ github.event.pull_request.head.sha }} # 关键:设置为false,禁止取消正在运行的实例,新运行会被跳过 cancel-in-progress: false permissions: contents: read pull-requests: read jobs: long-running-task: runs-on: ubuntu-latest # 仅处理PR评论,排除普通issue评论 if: github.event.issue.pull_request steps: # 以下是你的原有工作流步骤 - name: 初始化环境 run: echo "准备运行耗时任务..." - name: 执行耗时操作 run: | echo "开始30分钟任务..." sleep 1800 # 模拟30分钟执行时间 echo "任务完成,更新状态..."
注意事项
- 并发组命名必须唯一标识“PR+提交Hash”:
pr-${{ github.event.issue.number }}-${{ github.event.pull_request.head.sha }}确保只有同一PR的同一提交触发的工作流才会被纳入同一组,不同提交或不同PR的工作流不受影响。 - 权限设置:需要
pull-requests: read权限来获取PR的提交Hash信息。
方案二:通过GitHub API主动查询运行状态(灵活扩展)
如果需要更复杂的过滤逻辑(比如仅检查特定步骤的运行状态),可以在工作流启动前调用GitHub API,查询是否存在同一PR+Hash的运行中工作流,存在则终止新运行。
配置示例
name: 耗时PR工作流 on: issue_comment: types: [created] permissions: contents: read actions: read pull-requests: read jobs: check-and-execute: runs-on: ubuntu-latest steps: - name: 确认是PR评论 if: github.event.issue.pull_request id: get_pr_info run: | echo "pr_number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT echo "pr_sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT - name: 检查是否有运行中的同组工作流 if: steps.get_pr_info.outputs.pr_number run: | # 使用GitHub CLI查询当前仓库中,关联指定PR、提交Hash且状态为in_progress的同工作流 RUNNING_COUNT=$(gh run list \ --repo ${{ github.repository }} \ --workflow ${{ github.workflow }} \ --status in_progress \ --json headSha,pullRequests \ --jq '.[] | select(.headSha == "${{ steps.get_pr_info.outputs.pr_sha }}" and .pullRequests[0].number == ${{ steps.get_pr_info.outputs.pr_number }}) | length') if [ "$RUNNING_COUNT" -gt 0 ]; then echo "发现PR #${{ steps.get_pr_info.outputs.pr_number }} 已有运行中的工作流,终止当前新运行。" exit 1 fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 原有工作流步骤 - name: 执行耗时任务 run: | echo "启动耗时任务..." sleep 1800 echo "任务完成。"
优势
- 可自定义过滤条件:比如仅检查特定job的运行状态,或排除手动触发的运行等。
- 完全控制终止逻辑:可以在终止前添加日志、通知等操作。
为什么不依赖状态检查(status check)
你提到的“检测已发布状态不可靠”是合理的,因为状态检查只能证明某个状态曾被提交过,无法区分是“正在运行中”还是“已完成”。而上述两种方案都是直接查询GitHub Actions的运行实例状态,能准确判断是否有活跃的工作流在执行,可靠性更高。
内容的提问来源于stack exchange,提问作者Vladimír Slávik
相关产品推荐
相关产品推荐

