You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:33:52