Skip to main content

优化堆积拉取请求的 CI

了解工作流如何 GitHub Actions 为堆栈运行、访问工作流中的堆栈元数据以及减少冗余 CI 使用情况。

注意

此功能以公共预览版提供,可能会发生更改。

将计算堆栈中的每个拉取请求,就好像它以堆栈的基数为目标,例如 main。 这可以在整个层中保持质量一致,但这也意味着工作流可以针对单个堆栈运行多次。 本文介绍了工作流如何为堆栈运行,以及如何减少冗余 CI 使用情况。

工作流如何为堆栈运行

GitHub 操作工作流会触发,就像堆栈中的每个拉取请求都面向堆栈的基础一样。 配置为针对pull_request堆栈中的每个拉取请求(而不仅仅是底部请求)运行的事件main上运行的工作流,因此检查无需进行工作流更改即可跨整个堆栈运行。

由于每个拉取请求一次工作流运行一次,因此大型堆栈会乘以 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
  • 顶部拉取请求 - 堆栈中最后一个拉取请求,其中包含完整的更改集。 它是等于github.event.pull_request.stack.size的拉取请求github.event.pull_request.stack.position
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"

当拉取请求从下而上合并时,未合并请求的最低更改。 下一个拉取请求到达后,下一个拉取请求将重新定基以直接定位堆栈基础,因此它会成为以下工作流运行中新的最低未合并拉取请求。

还可以通过任何特定层position(使用)对原始底部拉取请求github.event.pull_request.stack.position == 1进行门控。