1. 问题介绍
在使用Github Action做CICD的过程中会编写很多Workflow脚本, 很多脚本又有很多相似性, 例如针对开发(dev)/预生成(staging)和生成(prod)三个场景中只有触发工作流时事件(Event)和环境(Environment)不同, 而核心工作流步骤(Step)是差不多的, 如下:
dev
.github/workflows/dev-release.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39name: Dev(master) release
on:
push:
branches:
- master
jobs:
version-bump:
# ...
deploy-aws:
name: Deploy AWS - Dev environment
runs-on: ubuntu-latest
needs: version-bump
environment: dev
steps:
- name: Check out git repository
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ needs.version-bump.outputs.release-sha }}
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
cache: yarn
- name: Install CI dependencies
run: yarn install --frozen-lockfile
- name: Build and deploy applications to AWS
run: npx nx affected --target=deploy --configuration=${{ vars.ENV_NAME }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ENV_NAME: ${{ vars.ENV_NAME }}
AWS_DEFAULT_REGION: cn-northwest-1staging
.github/workflows/staging-release.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21name: Staging release
on:
push:
branches:
- release/*
jobs:
deploy-aws:
name: Deploy AWS - Staging environment
runs-on: ubuntu-latest
environment: staging
steps:
- name: Check out git repository
uses: actions/checkout@v3
with:
fetch-depth: 0
# ...
# be same with the dev workflow yaml L24~L39prod
.github/workflows/prod-release.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19name: Production release
on:
workflow_dispatch:
jobs:
deploy-aws:
name: Deploy AWS - Production environment
runs-on: ubuntu-latest
environment: production
steps:
- name: Check out git repository
uses: actions/checkout@v3
with:
fetch-depth: 0
# ...
# be same with the dev workflow yaml L24~L39
结合上面的例子分析可知:
不同点:
dev是代码push到master触发; staging是push release分支触发; prod是手动触发
dev/staging/prod三个工作流中的
environment
是不一样的`
相同点
- L24~L39是完全相同的
略有不同
- dev和checkout逻辑和staging/prod不同, 多了一个
ref
- dev和checkout逻辑和staging/prod不同, 多了一个
综上, 相同点
+略有不同
这两部分其实可以想办法复用, 而这个技术就是: 复用工作流
2. 复用工作流
复用工作流简而言之: 将类似的工作流, 这里主要就是相似的Step抽出到一个新的工作流, 而这个新的工作流可以被重复调用. 在实践之前需要简单介绍些理论:
- 被调用方
- 复用工作流的触发事件是: workflow_call, 即被调用方
- 在复用工作流可以继续调用其他服用工作流, 但是最多四层, 如: root->reuse1->reuse2记作2层
- 复用工作流定义在事件处定义:
inputs
和secrets
两种变量用于传递参数 - 复用工作流永远仅使用调用方的环境和上下文信息, 与自己所在位置无关
- 调用方
- 使用复用工作流的一方称为调用方, 调用方使用
uses
关键词来调用复用工作流 - 调用方使用
with
关键词设置inputs
参数设置 - 调用方使用
secrets
进行机密参数设置- secrets变量支持继承:
inherit
- secrets变量支持继承:
- 使用复用工作流的一方称为调用方, 调用方使用
结合上面的例子实现步骤如下:
被调用方: 定义复用工作流
github/workflows/deploy-aws.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49name: AWS deployment
on:
workflow_call:
inputs:
envName: # 支持环境切换
type: string
description: the deployment environment
required: true
releaseSha: # 支持两种checkout
type: string
description: the git head
jobs:
deploy:
name: Deploy AWS
runs-on: ubuntu-latest
environment: ${{ inputs.envName }} # 切换环境
steps:
- name: Check out git repository
if: inputs.releaseSha != '' # 支持ref的checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ inputs.releaseSha }}
- name: Check out git repository
if: inputs.releaseSha == '' # 支持默认的checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install CI dependencies
run: yarn install --frozen-lockfile
- name: Build and deploy applications to AWS
run: npx nx affected --target=deploy --configuration=${{ inputs.envName }} # 引用变量
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ENV_NAME: ${{ inputs.envName}} # 引用变量
AWS_DEFAULT_REGION: cn-northwest-1以上yaml中
#
注释部分是需要着重观察的地方dev调用方改造
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18name: Dev(master) release
on:
push:
branches:
- master
jobs:
version-bump:
# ...
deploy-aws:
uses: ./.github/workflows/deploy-aws.yml # 调用复用工作流
with: # 复用工作流参数设置
envName: dev
releaseSha: ${{ needs.version-bump.outputs.release-sha }}
secrets: inherit # 复用工作流机密参数设置
name: Deploy AWS - Dev environment
needs: version-bumpstaging调用方改造
1
2
3
4
5
6
7
8
9
10
11
12
13
14name: Staging release
on:
push:
branches:
- release/*
jobs:
deploy-aws:
uses: ./.github/workflows/deploy-aws.yml # 调用复用工作流
with: # 复用工作流参数设置
envName: staging
secrets: inherit # 复用工作流机密参数设置
name: Deploy AWS - Staging environmentprod调用方改造
1
2
3
4
5
6
7
8
9
10
11
12name: Production release
on:
workflow_dispatch:
jobs:
deploy-aws:
uses: ./.github/workflows/deploy-aws.yml # 调用复用工作流
with: # 复用工作流参数设置
envName: prod
secrets: inherit # 复用工作流机密参数设置
name: Deploy AWS - Production environment
3. 总结
复用工作流不仅支持在同一个代码仓库中创建和调用复用工作流, 也支持跨仓库调用复用工作流;
复用工作流的secrets
继承机制可以让我们在定义复用工作流时少些很多机密参数, 又因为复用工作永远使用调用方的上下文所以结合Github Envivronment使用切换环境和参数很方便;
复用工作流在代码工程/并行协作上也增加了质量和效率;
总之, 复用工作流是Github Action的一个最佳实践, 推荐使用!