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
相关产品推荐
相关产品推荐

