堆栈中的每个拉取请求都会被评估,就好像它以堆栈的基数为目标,例如 main。 这可以跨每一层保持质量一致,但这也意味着工作流可以针对单个堆栈运行多次。 本文介绍了工作流如何在堆栈中运行,以及如何减少冗余 CI 使用情况。
堆栈中的工作流如何运行
GitHub Actions 工作流会触发,就像堆栈中的每个拉取请求都以该堆栈的基底为目标一样。 配置为在针对main的pull_request事件上运行的工作流会对堆栈中的每个拉取请求运行,而不只是底部的那个,因此无需更改工作流,你的检查即可在整个堆栈中运行。
由于每个拉取请求都会运行一次工作流,因此较大的 PR 堆栈会成倍增加 CI 用量。 但是,可以使用堆栈元数据仅在需要时运行昂贵的作业。
访问堆栈元数据
堆栈元数据可在工作流表达式中通过 github.event.pull_request.stack 获取。 仅当拉取请求属于堆栈时,此属性才存在,因此请确保工作流在读取其任何字段之前先筛选出包含该属性的项。
| 表达式 | Description |
|---|---|
github.event.pull_request.stack.number | 堆栈的编号,以存储库为作用域。 |
github.event.pull_request.stack.size | 堆栈中的拉取请求总数。 |
github.event.pull_request.stack.position | 此拉取请求在堆栈中基于 1 的位置(1 为底部)。 |
github.event.pull_request.stack.base.ref | 整个堆栈最终面向的分支,例如 main。 |
github.event.pull_request.stack.base.sha | 堆栈基分支的 HEAD SHA。 |
例如,以下工作流读取堆栈元数据,仅当堆栈以名称开头为 release/ 的分支为目标时,才会运行第二步。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Show stack info
if: github.event.pull_request.stack != null
run: |
echo "Stack base ref: ${{ github.event.pull_request.stack.base.ref }}"
echo "PR ${{ github.event.pull_request.stack.position }} of ${{ github.event.pull_request.stack.size }} in the stack"
- name: Run only when the stack targets a release branch
if: github.event.pull_request.stack != null && startsWith(github.event.pull_request.stack.base.ref, 'release/')
run: echo "This stack targets a release branch"
减少 CI 使用量
由于工作流会针对堆栈中的每个拉取请求运行,因此可以使用 stack 参数仅在重要位置运行昂贵的作业。 两个条件特别有用:
- 最低未合并拉取请求 — 当前位于剩余堆栈底部的拉取请求,直接以该堆栈的基底为目标。 这是
github.event.pull_request.stack.base.ref等于github.event.pull_request.base.ref的拉取请求。 - 顶部拉取请求(PR) — 堆栈中最后一个拉取请求(PR),其中包含完整的更改集。 这是
github.event.pull_request.stack.position等于github.event.pull_request.stack.size的拉取请求。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run for the lowest unmerged pull request in the stack
if: github.event.pull_request.stack != null && github.event.pull_request.stack.base.ref == github.event.pull_request.base.ref
run: echo "Lowest unmerged pull request in the stack"
- name: Run for the top pull request in the stack
if: github.event.pull_request.stack != null && github.event.pull_request.stack.position == github.event.pull_request.stack.size
run: echo "Top pull request in the stack"
当拉取请求自下而上合并时,最下面的未合并拉取请求会发生变化。 最底部的拉取请求合并后,下一个拉取请求将重新变基,直接以堆栈基部为目标,因此它会在下一次工作流运行中成为新的最低未合并拉取请求。
还可以使用 github.event.pull_request.stack.position == 1 对原始拉取请求进行门控,或使用 position 对任何特定层进行门控。