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

GitHub Actions:如何关联PR工作流产物至合并后部署工作流?

问题描述

我希望配置GitHub Actions实现以下流程:

  • 向master分支创建Pull Request(PR)时,触发执行应用构建与单元测试的工作流;
  • PR被接受并合并后,触发另一个工作流,使用PR工作流的构建产物完成部署。

已知可通过actions/download-artifact@v4实现跨工作流获取产物,示例代码:

- name: Download artifacts
  uses: actions/download-artifact@v4
  with:
    name: my_artifact
    run-id: ${{ github.event.workflow_run.id }}
    github-token: ${{ secrets.GITHUB_TOKEN }}

但遇到以下矛盾:

  • 若采用workflow_run触发合并后工作流(配置如下),虽能关联前置工作流,但GitHub会为PR创建独立提交,无法正确标记合并后的对应提交:
on:
  workflow_run:
    workflows: ["Build and Test"]
    types:
      - completed
  workflow_dispatch:
  • 若改用push触发合并后工作流(配置如下),则无内置方式获取对应PR工作流的workflow_run.id以下载产物:
on:
  push:
    branches:
      - master

请问如何解决该问题,实现合并后工作流正确关联并获取PR工作流的构建产物?


解决方案

可以通过在PR工作流中留存关联信息,或直接通过GitHub API查询对应PR的工作流ID两种方式解决,具体实现如下:

方案一:通过文件留存PR与工作流ID的关联

1. 修改PR构建测试工作流

在构建上传产物后,新增步骤将当前工作流ID与PR编号写入文件,推送到PR分支:

name: Build and Test
on:
  pull_request:
    branches: [master]

jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      # 执行构建、单元测试步骤
      - name: Build application
        run: npm run build # 替换为你的构建命令
      - name: Run unit tests
        run: npm run test # 替换为你的测试命令

      # 上传构建产物
      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: my_artifact
          path: dist/ # 替换为你的产物路径

      # 记录PR编号与工作流ID的映射
      - name: Save workflow-PR mapping
        run: echo "${{ github.event.pull_request.number }}:${{ github.run_id }}" >> PR_WORKFLOW_MAP
      # 将映射文件推送到PR分支
      - name: Push mapping file
        uses: ad-m/github-push-action@master
        with:
          branch: ${{ github.head_ref }}
          files: PR_WORKFLOW_MAP
          github_token: ${{ secrets.GITHUB_TOKEN }}

2. 修改master分支的部署工作流

当PR合并到master后,触发部署工作流,通过合并提交提取PR编号,再读取映射文件获取工作流ID,最后下载产物部署:

name: Deploy to Production
on:
  push:
    branches: [master]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # 需获取完整提交历史

      # 从合并提交中提取PR编号
      - name: Extract PR number from merge commit
        id: get-pr
        run: |
          PR_NUM=$(git log --merges --grep="Merge pull request #" -1 --format="%s" | sed -n 's/Merge pull request #\([0-9]*\).*/\1/p')
          echo "pr_number=$PR_NUM" >> $GITHUB_OUTPUT

      # 拉取PR分支的映射文件
      - name: Fetch PR branch mapping file
        run: |
          git fetch origin refs/pull/${{ steps.get-pr.outputs.pr_number }}/head:temp-pr-branch
          git checkout temp-pr-branch -- PR_WORKFLOW_MAP

      # 读取对应的工作流ID
      - name: Get workflow run ID
        id: get-run-id
        run: |
          RUN_ID=$(grep "^${{ steps.get-pr.outputs.pr_number }}:" PR_WORKFLOW_MAP | cut -d':' -f2)
          echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT

      # 下载PR工作流的构建产物
      - name: Download build artifact
        uses: actions/download-artifact@v4
        with:
          name: my_artifact
          run-id: ${{ steps.get-run-id.outputs.run_id }}
          github-token: ${{ secrets.GITHUB_TOKEN }}

      # 执行部署操作
      - name: Deploy to production
        run: |
          # 替换为你的实际部署命令,如kubectl apply、scp等
          echo "Deploying artifact to production environment..."

方案二:通过GitHub API直接查询PR的工作流ID

无需维护映射文件,直接调用GitHub API获取对应PR的已完成构建工作流ID:

name: Deploy to Production
on:
  push:
    branches: [master]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      # 提取合并提交对应的PR编号
      - name: Extract PR number
        id: get-pr
        run: |
          PR_NUM=$(git log --merges --grep="Merge pull request #" -1 --format="%s" | sed -n 's/Merge pull request #\([0-9]*\).*/\1/p')
          echo "pr_number=$PR_NUM" >> $GITHUB_OUTPUT

      # 通过API查询PR对应的构建工作流ID
      - name: Get workflow run ID via API
        id: get-run-id
        run: |
          RUN_ID=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
            "https://api.github.com/repos/${{ github.repository }}/actions/runs?event=pull_request&pull_request=${{ steps.get-pr.outputs.pr_number }}&status=completed" \
            | jq -r '.workflow_runs[] | select(.name == "Build and Test") | .id' | head -n1)
          echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT

      # 下载构建产物
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: my_artifact
          run-id: ${{ steps.get-run-id.outputs.run_id }}
          github-token: ${{ secrets.GITHUB_TOKEN }}

      # 部署步骤
      - name: Deploy
        run: |
          # 替换为你的部署命令
          echo "Starting production deployment..."

注意:需确保工作流名称Build and Test与PR工作流的名称完全一致,Ubuntu runner默认已预装jq工具。


内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:19:58