Reuse Workflow#

GitHub Actions 中的 Reuse Workflow 和 CircleCI Orb, 都是为了解决 YAML 代码复用, 参数化而设计的机制.

它的本质就是用一个 Workflow 去 Call 另一个 Workflow (用 ${Organization}/${Repository}/${PathToYamlFile}@${reference} 这样的格式去调用).

1. Basic Usage#

这里的关键就是 Worker (被调用方) 需要在 on 里加一个 workflow_call: trigger. 然后再 Caller (调度方) 用 jobs.<job_id>.uses 指定使用 Worker 的 yaml file. 具体格式是 ${Organization}/${Repository}/${PathToYamlFile}@${reference}.

Caller

 1# ------------------------------------------------------------------------------
 2# Reuse workflow caller
 3#
 4# - Reusing workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows
 5# - Using inputs and secrets in a reusable workflow: https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-inputs-and-secrets-in-a-reusable-workflow
 6# ------------------------------------------------------------------------------
 7name: 01_09_01_reusable_workflow_caller
 8on:
 9  workflow_dispatch:
10jobs:
11  call_worker:
12    uses: MacHu-GWU/learn_github_action-project/.github/workflows/01_09_01_reusable_workflow_worker.yml@main

Worker

 1name: 01_09_01_reusable_workflow_worker
 2on:
 3  workflow_call:
 4jobs:
 5  build:
 6    runs-on: ubuntu-latest
 7    steps:
 8      - uses: actions/checkout@v3
 9      - name: Run a one-line script
10        run: echo Hello, world!
11      - name: Run a multi-line script
12        run: |
13          echo build your project
14          echo test your project
15          echo deploy your project

2. Reuse a Workflow in the Same Branch#

前面的例子介绍了, 引用一个 Workflow 需要指定 @${reference}, 也就是 branch / tag / commit_id. 如果你不指定的话就会使用默认 branch. 但有的时候你在一个 feature branch 上的开发任务就是 workflow yaml file 本身, 你可不想把你的 feature branch hardcode 在 @${reference} 里.

凭直觉, 你可能会想要用 ${{ github.base_ref }} 这个 context 来取代 main, 但是很不幸, 这个 context 在 jobs.<job_id>.uses 里是不支持的.

GitHub 在 2022-01-25 发布了一个新功能, 现在你能用相对路径的语法来指定一个同 branch 上的 yaml 文件了

Caller

 1# ------------------------------------------------------------------------------
 2# Reuse workflow caller
 3#
 4# - Reusing workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows
 5# - Using inputs and secrets in a reusable workflow: https://docs.github.com/en/actions/using-workflows/reusing-workflows#using-inputs-and-secrets-in-a-reusable-workflow
 6# ------------------------------------------------------------------------------
 7name: 01_09_02_reusable_workflow_caller
 8on:
 9  workflow_dispatch:
10jobs:
11  call_worker:
12    # --------------------------------------------------------------------------
13    # in the previous example, we have to have a @main at the end to specify
14    # which branch to use for searching the workflow yaml file. without @main
15    # it always uses the default branch.
16    #
17    # however, if you are working on a feature branch, and you are editing the
18    # worker yaml file, how do you let caller to find the worker yaml file from
19    # the same branch?
20    #
21    # Intuitively, you may want to use ${{ github.base_ref }} context,
22    # however, the github context is not available in the jobs.<job_id>.uses key
23    #
24    # GitHub released a new feature 2022-01-25, now you can reference a workflow
25    # in the same branch locally
26    # GitHub Actions: Reusable workflows can be referenced locally: https://github.blog/changelog/2022-01-25-github-actions-reusable-workflows-can-be-referenced-locally/
27    # # --------------------------------------------------------------------------
28    uses: ./.github/workflows/01_09_02_reusable_workflow_worker.yml

Worker

 1name: 01_09_02_reusable_workflow_worker
 2on:
 3  workflow_call:
 4jobs:
 5  build:
 6    runs-on: ubuntu-latest
 7    steps:
 8      - uses: actions/checkout@v3
 9      - name: Run a one-line script
10        run: echo Hello, world!
11      - name: Run a multi-line script
12        run: |
13          echo build your project
14          echo test your project
15          echo deploy your project
16          echo this is dev branch

4. Multiple Project Release in Mono Repo#

在 Monorepo 项目中, 你可能会用多个项目文件夹隔离不同的项目. 每一个项目都是一个 deployment unit, 都会有一个自己的 workflow 让自己分别部署. 但有的时候你会希望将这些 workflow 一次性部署. 这应该如何实现比较好呢?

可以这样做, 由于是 mono repo, 你的每个 project 的 release 都是放在 ${project_name}/release branch 上做的.

而如果你要一次性的 release 多个项目, 你则是在 all/release branch 上做, 并且直接在这个 branch 上修改 caller 的 workflow yaml file 即可. 你要 release 几个项目就启用几个项目即可, 不需要的项目就 comment 掉.

Caller

Project 1 Worker

 1name: 01_09_04_reusable_workflow_project1.yml
 2on:
 3  workflow_call:
 4  push:
 5    branches:
 6      - 'project1/release*'
 7jobs:
 8  build:
 9    runs-on: ubuntu-latest
10    steps:
11      - name: Run a one-line script
12        run: echo deploy project 1

Project 2 Worker

 1name: 01_09_04_reusable_workflow_project1.yml
 2on:
 3  workflow_call:
 4  push:
 5    branches:
 6      - 'project1/release*'
 7jobs:
 8  build:
 9    runs-on: ubuntu-latest
10    steps:
11      - name: Run a one-line script
12        run: echo deploy project 1

Reference#