如何在GitHub Actions中排除含WIP的PR触发UAT部署工作流?
背景与上下文
我们有两个GitHub Action工作流:1.「构建、测试与打包」,2.「部署到UAT」。
工作流(1)的触发规则如下:
# 触发条件:拉取请求(变更或推送)或标签(发布用) on: pull_request: release:
该工作流负责构建软件、运行单元测试并打包可在环境中运行的Docker容器。
工作流(2)在工作流(1)完成后触发,其触发规则如下:
on: # 当构建工作流完成时触发(不一定成功,成功判断需下方的IF条件) # 注意:此触发方式始终基于master分支运行 workflow_run: workflows: ["Build, Test & Package"] types: - completed # 或手动触发 # 注意:此触发方式始终基于master分支运行 workflow_dispatch: inputs: PACKAGE_VERSION: description: "PACKAGE_VERSION" required: false
同时,该工作流的第一步需添加if条件,排除工作流(1)执行失败的情况:
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
问题
我们希望实现:当启动整个流水线的初始拉取请求(PR)标题中包含「WIP」时,不运行部署工作流(2)。核心需求是避免UAT环境被非指定PR的构建污染,同时仍允许所有PR(含WIP状态)运行CI流水线以验证测试等内容。请问该需求是否可实现?
可以实现,以下是两种可行方案:
方案一:在工作流(1)中传递PR标题信息
- 先在工作流(1)中新增步骤,捕获PR标题并作为输出变量留存:
jobs: build-test-package: runs-on: ubuntu-latest outputs: pr_title: ${{ steps.get_pr_title.outputs.title }} steps: - name: 捕获PR标题 id: get_pr_title if: github.event_name == 'pull_request' run: echo "title=${{ github.event.pull_request.title }}" >> $GITHUB_OUTPUT - name: 设置非PR场景的默认标题值 if: github.event_name != 'pull_request' run: echo "title=NON_PR" >> $GITHUB_OUTPUT # 原有的构建、测试、打包步骤保持不变...
- 在工作流(2)中,通过GitHub API拉取工作流(1)的输出变量,扩展
if条件判断标题是否含「WIP」:
jobs: deploy-to-uat: runs-on: ubuntu-latest if: >- ${{ (github.event.workflow_run.conclusion == 'success' && !contains(steps.fetch_pr_title.outputs.title, 'WIP')) || github.event_name == 'workflow_dispatch' }} steps: - name: 获取工作流(1)的PR标题输出 id: fetch_pr_title if: github.event_name == 'workflow_run' run: | RESPONSE=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ "https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}/jobs") PR_TITLE=$(echo "$RESPONSE" | jq -r '.jobs[] | select(.name == "build-test-package") | .steps[] | select(.name == "捕获PR标题") | .outputs.title') echo "title=$PR_TITLE" >> $GITHUB_OUTPUT # 原有的部署步骤保持不变...
方案二:直接在工作流(2)中解析触发PR信息
无需修改工作流(1),直接在工作流(2)中通过分支名解析PR编号,再调用API获取标题:
jobs: deploy-to-uat: runs-on: ubuntu-latest if: >- ${{ (github.event.workflow_run.conclusion == 'success' && !contains(steps.fetch_pr_title.outputs.title, 'WIP')) || github.event_name == 'workflow_dispatch' }} steps: - name: 获取触发PR的标题 id: fetch_pr_title if: github.event_name == 'workflow_run' && startsWith(github.event.workflow_run.head_branch, 'refs/pull/') run: | PR_NUMBER=$(echo "${{ github.event.workflow_run.head_branch }}" | cut -d'/' -f3) RESPONSE=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ "https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER") PR_TITLE=$(echo "$RESPONSE" | jq -r '.title') echo "title=$PR_TITLE" >> $GITHUB_OUTPUT - name: 设置非PR场景的默认标题值 if: github.event_name == 'workflow_run' && !startsWith(github.event.workflow_run.head_branch, 'refs/pull/') run: echo "title=NON_PR" >> $GITHUB_OUTPUT # 原有的部署步骤保持不变...
关键说明
- 两种方案均满足需求:含「WIP」标题的PR会正常执行工作流(1)完成CI验证,但不会触发工作流(2)部署UAT;非WIP标题的PR在工作流(1)成功后自动触发部署。
- 手动触发工作流(2)不受PR标题限制,符合现有规则。
内容的提问来源于stack exchange,提问作者Kieran Benton
相关产品推荐
相关产品推荐

