如何让GitHub Workflow在两个工作流成功后触发?解决重复触发问题
问题描述
想要实现一个GitHub部署测试环境的Workflow,要求仅在后端、前端构建Docker镜像的两个Workflow都成功完成后才触发。当前使用workflow_run监听这两个Workflow,但每次其中一个完成时就会触发部署Workflow,导致重复触发两次;即使添加了if: ${{ github.event.workflow_run.conclusion == 'success' }}的过滤条件,问题仍然存在。
当前部署Workflow配置如下:
name: Deploy to Test Environment env: GITHUB_REGISTRY: "ghcr.io" GITHUB_OWNER: "mjovanc" GITHUB_DOCKER_IMAGE: "test" on: workflow_run: workflows: ["Backend Main Pipeline", "Frontend Main Pipeline"] branches: [main] types: - completed
原因分析
workflow_run的触发逻辑是每个被监听的Workflow完成时,都会单独触发一次当前Workflow。你添加的conclusion == 'success'只是过滤掉了依赖Workflow失败时的触发,但只要其中一个依赖Workflow成功完成,就会触发一次部署Workflow。因此当两个依赖Workflow都成功时,部署Workflow会被触发两次。
解决方案
方案1:结合GitHub API检查两个依赖Workflow的状态
在部署Workflow中添加前置检查步骤,通过GitHub API查询另一个依赖Workflow在当前提交上的运行状态,只有当两个都成功时才执行部署操作。
修改后的完整配置:
name: Deploy to Test Environment env: GITHUB_REGISTRY: "ghcr.io" GITHUB_OWNER: "mjovanc" GITHUB_DOCKER_IMAGE: "test" on: workflow_run: workflows: ["Backend Main Pipeline", "Frontend Main Pipeline"] branches: [main] types: - completed jobs: # 第一步:检查两个依赖Workflow是否都成功 check-all-workflows: runs-on: ubuntu-latest outputs: can-deploy: ${{ steps.check.outputs.can-deploy }} steps: - name: Verify both workflows succeeded id: check run: | # 确定当前触发的是哪个依赖Workflow triggered_workflow="${{ github.event.workflow_run.name }}" # 定义需要检查的另一个Workflow名称 if [ "$triggered_workflow" = "Backend Main Pipeline" ]; then target_workflow="Frontend Main Pipeline" else target_workflow="Backend Main Pipeline" fi # 查询目标Workflow在当前提交上的最新运行状态 response=$(gh api repos/${{ github.repository }}/actions/workflows/"$(echo "$target_workflow" | tr ' ' '-')".yml/runs \ --method GET \ -f head_sha="${{ github.event.workflow_run.head_sha }}" \ -f status=completed \ -f per_page=1) # 解析响应,判断目标Workflow是否成功 target_conclusion=$(echo "$response" | jq -r '.workflow_runs[0].conclusion') if [ "$target_conclusion" = "success" ] && [ "${{ github.event.workflow_run.conclusion }}" = "success" ]; then echo "can-deploy=true" >> "$GITHUB_OUTPUT" else echo "can-deploy=false" >> "$GITHUB_OUTPUT" fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 第二步:仅当两个依赖都成功时执行部署 deploy-test-env: needs: check-all-workflows if: ${{ needs.check-all-workflows.outputs.can-deploy == 'true' }} runs-on: ubuntu-latest steps: - name: Start deployment run: | echo "Deploying to test environment..." # 这里添加你的具体部署命令
方案2:使用环境保护规则(需GitHub高级计划)
如果你的仓库使用GitHub Enterprise或Team计划,可以给测试环境设置Required workflows规则:
- 在仓库的
Settings→Environments中创建测试环境; - 在环境的
Protection rules里添加Required workflows,选择后端和前端的两个构建Workflow; - 部署Workflow直接监听代码推送或其他事件,当执行到部署步骤时,GitHub会自动检查两个依赖Workflow是否都已成功,只有满足条件才会继续执行部署。
方案3:基于repository_dispatch的协调触发
让后端和前端Workflow在成功完成后,分别发送一个repository_dispatch事件,部署Workflow监听该事件,并通过缓存或GitHub存储记录已完成的Workflow,当两个都完成时再执行部署。这种方式适合更复杂的依赖场景,但配置相对繁琐。
内容的提问来源于stack exchange,提问作者user21225362

