使用 GitHub Actions 构建 CI/CD 流水线
初入公司的时候,所经历项目用的 CI/CD 的工具都是 Jenkins。后来慢慢的,发现用 GitHub Actions 实现 CI/CD 的项目越来越多了。
一直对这个东西有点好奇,但也没系统的研究它的应用。巧在,现有项目上有机会让自己从头配置 CI/CD,也就掀开了我对 GitHub Actions 的“神秘面纱”。
仅以此博客分享如何使用 GitHub Actions 构建 CI/CD 流水线以及遇到过的坑和解决办法 。
GitHub Actions 的简单介绍
GitHub Actions 是 GitHub 的自动化平台,它支持各种语言和框架。通过编写 YAML 文件, 用户可以定义在代码库中发生特定事件(比如:Push、Tag等) 时所触发的工作流程,从而帮助用户实现自动化的 CI/CD。
添加 Runner 主机
Runner 主机是执行 GitHub Actions 的核心。为了运行工作流程,我们需要在 Runner 主机。
GitHub Actions 提供了两种类型的 Runner:
托管 Runner:GitHub 提供的 Runner,无需自己维护。
自托管 Runner:在自己的服务器上运行的 Runner,可以根据需要进行定制。
因为自托管 Runner 允许用户在自己的服务器上运行工作流程,提供更多的灵活性和控制。因此我们选择自托管 Runner。
配置 Runner
进入GitHub 仓库的 Settings --> Actions --> Runners --> 点击【New self-hosted-runner】
在该页面,即可看到 Runner 配置流程以及Token, 以 Linux 为例:
$ mkdir actions-runner &&cd actions-runner
$ curl-o actions-runner-linux-x64-2.317.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gzCopied!
$ tar xzf ./actions-runner-linux-x64-2.317.0.tar.gz
$ ./config.sh --url https://github.com/your-repo --token YOUR_TOKEN
注意:
这里需要根据系统类型,下载不同的安装包(始终记得在 Linux 系统里下载了 Macos runner,死活跑不起来,排查了半天原因)
在 Config Token 这一步配置最好为当前 Runner 添加额外的 Lables(而不是默认生成),以便于后续存在多个 Runner 时更好区分
运行单个 Runner
如果只有一个 Runner 需要执行,运行如下命令即可:
$ ./run.sh
批量运行多个 Runner
由于项目上一般会存在多个仓库,每个仓库都需要 CI/CD 流水线,因此我们需要在服务器上运行多个 Runner。
为了更好管理,采用 docker-compose 的方式来批量化运行多个 Runner
添加文件夹
mkdir actions-runner &&cd actions-runner
在actions-runner/runners 下按照上述步骤为每个仓库添加的 Runner 主机, eg: actions-runner/runners/service-name1、actions-runner/runners/service-name2
$ mkdir runners &&cd runners
基于 Action Runner 的基础镜像配置 dockerfile
FROM mattermost/actions-runner:2.313.0-0
# 设置工作目录
WORKDIR /home
USER runner
# 复制应用程序代码到容器中
COPY --chown=runner:runner ./runners /home
RUN sudochown-R runner:runner /home
ENV PATH="/home/runner/.local/bin:$PATH"# 定义容器启动时要执行的命令
CMD ["./start-runners.sh"]
基于 dockerfile 构建一个 action-runner 的镜像
docker build -t action-runners .
检查镜像构建成功
docker images |grep action-runners
配置 docker-compose 文件
version: "3"
services:
test_runner1:
image: action-runners
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: ./service-name1/run.sh
test_runner2:
image: action-runners
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: ./service-name2/run.sh
运行 docker-compose 实现批量化运行多个 Runner
docker-compose up -d
查看容器状态
dockerps
当能看到两个 Runner 容器 STATUS 为 Up 时,即代表容器启动成功
配置 Runner 权限
值得注意的是,考虑到安全性和隔离性,我们在 Runner 容器内设置了专门的用户:Runner 用于运行 GitHub Actions Runner。
为了确保 Runner 用户的权限,我们需要确保 Runner 用户属于与 Docker 套接字所关联的组。
进入 rnnner 所在容器
sudodockerexec-it[RUNNER 容器id]bash
创建docker组(如果还没有)
groupadddocker
将runner用户添加到docker组
usermod-aGdocker runner
确保 /var/run/docker.sock 文件的组是 docker
chown root:docker /var/run/docker.sock
验证 Runner
要验证 Runner 正常运行,可以在 GitHub 仓库的Settings --> Actions --> Runners 中查看 Runner 状态。
如果 Runner 显示为 Idle 状态,说明配置成功。
编写工作流程( Workflow)文件
Workflow 是一系列可以自动执行的步骤,它们定义了项目的构建、测试和部署过程。Workflow 由 YAML 文件定义,这些文件存储在代码仓库的 .github/workflows 目录下。
在此目录下创建一个 development.yml(下文用到的所有Demo 大家感兴趣都可以移步至仓库进行查看:https://github.com/yzq327/react-redux-demo)。
定义 Workflow 触发器
首先,需要定义 Workflow 何时触发。在这个 Demo 中,我们将 Workflow 设置为在代码推送到 main 分支时触发。
name: Build and deploy
on:
push:
branches: ['main']
补充说明: Workflow 的触发方式有很多,用户可以基于自己的需求进行定义自动触发/手动触发、触发的分支、触发的条件等, 具体可以参考文档: https://docs.github.com/en/actions/using-workflows/triggering-a-workflow
定义 Jobs
Workflow 由一个或多个 Jobs 组成。 这里,我们先定义一个名为 build 的 Job。
jobs:
build:
runs-on: [self-hosted, test-runner]
注意:runs-on 指定 Job 在自托管的 test-runner (上文创建的 Runner)上运行。如果你使用的是 GitHub 托管 Runner,可以使用 ubuntu-latest 等标签。
添加 Steps
每个 Job 包含一个或多个 Steps,这些 Steps 是实际执行的命令或动作。
比如我想在 job: build 中实现每次推送代码到 main 分支时都自动构建和测试项目, 则可以将其拆分为如下步骤:
steps:
- name: Checkout the repository
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '14'
- name: Install dependencies
run: npminstall
- name: Run tests
run: npmtest
- Checkout the repository:检出代码
所有 CI/CD 工作流程的基础步骤,因为后续的构建、测试和部署操作都依赖于代码库中的文件。
actions/checkout Action 会将指定的分支或提交检出,并将代码复制到 Runner 主机的工作目录中。
- Set up Node.js: 设置 Node.js 环境
使用 actions/setup-node Action 可以自动下载并安装指定版本的 Node.js,并将其添加到系统路径中,使得后续步骤能够使用这个 Node.js 环境。
通过指定 node-version,你可以确保每次工作流程运行时使用相同的 Node.js 版本,从而避免版本不一致带来的问题。
具体使用什么环境取决于仓库本身
- Install dependencies:安装依赖项
项目的构建和测试都需要安装好所需的所有依赖项
由于当前 Demo 是个前端项目,所以可根据 package.json 文件中的依赖项列表,下载并安装所有必要的包。
- Run tests:运行测试
为了验证代码的正确性和稳定性,我们需要保证每次提交都能跑过所有的测试用例,如果任何一个测试失败,Workflow 将标记为失败,从而提醒开发者检查和修复代码问题。
运行 npm test 命令,以执行项目中的测试用例。“npm test” 是项目定义在 package.json 中执行所有测试用例的命令。
测试 Workflow
推送代码到 main 分支,GitHub Actions 将自动触发 development workflow。用户可以在 GitHub 上的 Actions 标签页中查看 workflow 的运行状态和日志。
图中的 Set up job、Post Setup Node.js、Complete jos 等 steps 是 Github actions 自己添加的前置或后置步骤,用于准备运行环境或清理临时文件等。
Jobs 的运行步骤
前面我们有提到过,一个Workflow 由一个或多个 Jobs 组成。每个 Job 是一组可以并行或串行运行的步骤。通常默认情况下,Jobs 间为并行关系。
如果你希望 Jobs 间存在穿行/依赖关系,比如 Job B 需要在 Job A 完成后才执行,则可以通过关键字:“needs” 设置 Jobs 之间的依赖关系
添加 Job deploy-to-dev 依赖于 Job build:
needs: build 指定 deploy-to-dev Job 依赖于 build Job,即只有在 build 成功后,deploy-to-dev 才会运行。
deploy-to-dev:
runs-on: [self-hosted, test-runner]
needs: build
steps:
- name: Deploy to Development
run: |echo"Deploying to development environment..."
./deploy-dev.sh
添加 Job deploy-to-prod 依赖于 Job deploy-to-dev:
needs: deploy-to-dev 指定 deploy-to-prod Job 依赖于 deploy-to-dev Job,即只有在 deploy-to-dev 成功后,deploy-to-prod 才会运行
deploy-to-prod:
needs: deploy-to-dev
runs-on: [self-hosted, test-runner]
steps:
- name: Deploy to Production Environment
run: |echo"Deploying to production environment..."
./deploy-prod.sh
测试 workflow
基于上述配置,可看到当前 workflow 中 Jobs 为串形执行,顺序如下:
添加部署保护规则
细心的朋友会发现上述流水线会存在一个很严重的问题,即开发伙伴提交代码后,如果顺利跑过build 即直接推动到的 dev环境,而后进一步执行 deploy-to-prod,也就是说每一次提交都会上生产环境。
很明显,在真实项目中这样的流水线是不允许存在的。真实项目上,我们会对部署到不同环境设置一定的触发条件或者手动点击触发。
针对当前 Demo,我们希望只有团队觉得可以上生产的 code,才会执行 deploy-to-prod。这时,可以使用关键字:“environment”。
“environment” 是一个用于描述和管理部署环境的概念。通过配置环境,用户可以在不同环境之间更好地管理部署过程,并应用部署保护规则以确保代码在不同环境中的安全部署。
配置部署保护规则
- 生成Environments
进入GitHub 仓库的 Settings --> Environments --> 点击【New environment】
输入 Environment 的名字: production
生成 production Enviroment, 并进入 Configure 页面
- Configure Environment
在【 Configure production 页面中,你可以添加部署保护规则,例如:
Reviewers:指定哪些用户或团队审批后才能进行部署。
Wait timer:设置一个等待时间,在该时间过后才能进行部署。
选择设置一个 Reviewers, 即只有通过 Reviewer 审批后,代码才能部署到 production 环境
设置完成, 点击【Save protection rules】
重构 deploy-to-prod
如果需要应用上一步设置的部署保护规则, 则需在Job中指定 environment 为上面配置的 production。
deploy-to-prod:
needs: deploy-to-dev
runs-on: [self-hosted, test-runner]
environment:
name: production
steps:
- name: Deploy to Production Environment
run: |echo"Deploying to production environment..."
./deploy-prod.sh
测试 workflow
基于上述配置,可看到当前的 workflow 执行完 deploy-to-dev 后会停下,等待 Reviewers 的 Approve。只有 Reviewers approve 之后,才会执行 deploy-to-prod。
环境变量
上一节介绍了关键字 environment 是用于描述和管理不同的部署环境。在 GitHub Actions Workflow 中,还有一个关键字:env 用于设置环境变量。
环境变量在 Workflow 的应用非常多, 比如:
- 配置敏感信息,如 API 密钥或令牌。
- 定义常量值,避免在多个地方重复。
- 控制 Workflow 行为,如设置标志或模式。
环境变量有三种:
- Workflow 级别环境变量
- Job 级别环境变量
- Step 级别环境变量。
下面我们可以根据 Demo 一起探讨不同级别环境变量的作用区域和优先级。
Demo 如下:
name: Env Priority Example
on: [push]
env:
GLOBAL_VAR: global_value
SHARED_VAR: global_shared_value
jobs:
build:
runs-on: ubuntu-latest
env:
JOB_VAR: job_value
SHARED_VAR: job_shared_value
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Print Env Variable at Job Level
run: |echo"GLOBAL_VAR: ${{ env.GLOBAL_VAR }}"echo"JOB_VAR: ${{ env.JOB_VAR }}"echo"SHARED_VAR at Job Level: ${{ env.SHARED_VAR }}"
- name: Print Env Variable at step Level
env:
STEP_VAR: step_value
SHARED_VAR: step_shared_value
run: |echo"GLOBAL_VAR: ${{ env.GLOBAL_VAR }}"echo"JOB_VAR: ${{ env.JOB_VAR }}"echo"STEP_VAR: ${{ env.SHARED_VAR }}"echo"SHARED_VAR at Step Level: ${{ env.SHARED_VAR }}"
触发 workflow 后,输出日志如下:
我们可以得出如下结论:
- Workflow级别环境变量:
在 Workflow 文件的顶层定义。
适用于所有 Jobs 和 Steps,但可以被 Job 级别和 Step 级别环境变量覆盖。
示例:GLOBAL_VAR 和 SHARED_VAR 在全局级别定义。
- Job 级别环境变量:
在特定的 Job 中定义。
适用于该 Job 内的所有 Steps,但可以被 Step 级别环境变量覆盖。
示例:JOB_VAR 和 SHARED_VAR 在 Job: build 中定义,同时 Job 级别的 SHARED_VAR 覆盖了全局级别的 SHARED_VAR。
- Step 级别环境变量:
在特定的 Step 中定义。
仅适用于该 Step。
STEP_VAR 和 SHARED_VAR 在 Step: Print Env Variable at step Level中定义,同时 Step 级别的 SHARED_VAR 覆盖了全局级别 和 Job 级别的 SHARED_VAR
密钥和常量
前面我们有提到环境变量的重要作用有配置敏感信息和常量值。对应的,GitHub Actions 中,提供了 密钥(Secrets) 和 常量(Variables)用于存储和保护敏感信息与变量值
Secrets
Secrets 用于存储敏感信息(如 API 密钥、访问令牌、密码等)。Secrets 只能在 GitHub Actions 工作流程中使用,不能被直接输出, 也不会在日志中显示。(这也意味着你需要额外记录你存储的Secrets的值,因为一旦保存了 Secrets,是没有办法查看该值的)
添加 Secrets
进入GitHub 仓库的 Settings --> Secrets and variables --> Actions 进入【Actions secrets and variables】页面
在 【Actions secrets and variables】页面,你可以看到有两种 Secrets: Environment secrets 和 Repository secrets
- Environment secrets适用于不同 Environment(如开发、测试、生产)中需要使用的特定配置或敏感信息。这里的 Environment 即上文我们描述的关键字:Environment 当我想为 Production 环境添加 Secrets:PROD_SECRET 时,操作如下:点击【Manage enviroment secrets】 选择 【production】, 在 Secrets 部分点击 【Add Environment secret】,输入名称和值,并保存。
- Repository secrets适用于需要在仓库中所有 Workflow 中使用的全局配置或敏感信息。 当我想为当前仓库添加 Secrets: ENV_SECRET 时,操作如下:在 Secrets 部分点击 【New repository variable】,输入名称和值,并保存。
Secrets 的使用
- 在 workflow 中使用 Environment Secrets
使用 Environment Secrets 时,需要指定关键词 environment 的值。这时 workflow 将使用对应 environment 的 Secret PROD_SECRET 的值。
jobs:
build:
runs-on: ubuntu-latest
environment: production # 指定环境为 production
steps:
- name: Use Environment secret
run: echo${{ secrets.PROD_SECRET }}
- 在 workflow 中使用 Repository Secrets
由于没有指定任何环境,因此 workflow 将使用 Repository Secret ENV_SECRET 的值。
- jobs: build: runs-on: ubuntu-latest steps:
- name: Use Repository secret
run: echo${{ secrets.ENV_SECRET }}
Secrets 的优先级
在 GitHub Actions 中,当同一个名称的 Secret 在不同的层级(Environment 和 Repository)中定义时,GitHub 会优先使用 Environment Secrets。即:
如果在工作流中指定了一个环境,并且该环境包含一个与 Repository Secret 同名的 Environment Secret,工作流将使用 Environment Secret 的值。
如果没有指定环境,或者指定的环境没有定义该 Secret,则工作流将使用 Repository Secret 的值。
Variables
Variables 用于存储非敏感信息,如配置选项、文件路径、常量等。Variables 也分为 Environment variables 和 Repository variables,其添加方式以及优先级和 Secrets 一致,在此就不赘述了,唯一不同的是使用方式。
当用户已经添加了 Repository variables:MY_VAR,其使用方式如下:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Use Repository secret
run: echo${{ vars.MY_VAR }}
Secrets 和 Variables 的区别和实践
基于上面分析,我们可以得出Secrets 和 Variables 的区别和实践
- 安全性:Secrets 应该仅用于敏感信息,而 Variables 则用于配置和非敏感数据。
- 可见性:Secrets是不可见的,并且不会记录在工作流日志中,而 Variables 是可见的。
- 使用场景: Secrets:API 密钥、认证令牌、密码等; Variables:环境配置、文件路径、常量等
信息传递
我们目前知道一个 Github action 可以包含多个 Workflow, 一个 Workflow 可以包含多个 Job,一个 Job 可以包含多个 Step。
在实现 CI / CD 过程中, 我们可能需要在不同的 Workflows、Jobs 以及 Steps 之间传递信息或数值。
跨 Workflows 信息传递
跨 Workflows 的信息传递可以通过 GitHub Actions 的 Repository Dispatch 事件和 GitHub API 来实现。这种方法允许一个 Workflow 触发另一个 Workflow,并传递自定义的负载信息。
- Workflow 1使用 peter-evans/repository-dispatch@v3 action 触发一个 repository dispatch 事件。并传递一个自定义的 JSON 负载 {“message”: “Hello from Workflow 1”}
name: Workflow 1
on: [push]
jobs:
dispatch:
runs-on: ubuntu-latest
steps:
- name: Trigger Workflow 2
uses: peter-evans/repository-dispatch@v3
with:
event-type: trigger-workflow-2
client-payload: '{"message": "Hello from Workflow 1"}'
- Workflow 2 监听 repository_dispatch 事件,并指定 trigger-workflow-2 类型。通过 ${{ github.event.client_payload.message }} 访问和使用 Workflow 1 传递的自定义负载信息。
name: Workflow 2
on:
repository_dispatch:
types: [trigger-workflow-2]
jobs:
example-job:
runs-on: ubuntu-latest
steps:
- name: Receive payload
run: echo"Received message: ${{ github.event.client_payload.message }}"
输出日志如下:
通过这种方式,即可实现跨 Workflows 信息传递。
跨 jobs 信息传递
在同一个 Workflow 中,不同 Jobs 之间的信息传递可以通过文件存储(Artifacts) 或者输出变量(Output Variables) 来实现。
文件存储
文件存储方式主要是用过 GitHub Actions 提供的 actions/upload-artifact 实现的,它允许用户在 GitHub Actions Workflow 中上传文件或目录作为 Artifacts。这样,用户可以在不同 Job 之间共享数据,或者在 Workflow 完成后保留数据以供后续使用。
name: Cross Jobs Example
on: [push]
jobs:
upload-job:
name: Pass values by artifacts
runs-on: ubuntu-latest
steps:
- name: Create artifact
run: echo"artifact_content"> artifact.txt
# Upload artifact
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: my-artifact
path: artifact.txt
download-job:
name: Get values by artifacts
needs: upload-job
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: my-artifact
- name: Use artifact
run: cat artifact.txt
输出日志如下:
输出变量
输出变量方式使用关键词:needs 和 outputs 的实现 Jobs 之间的信息传递。
jobs:
output-job:
name: Pass values by needs
runs-on: ubuntu-latest
outputs:
job_output: ${{ steps.set-output.outputs.my_output }}
steps:
- name: Set output variable
id: set-output
run: |-
echo"my_output=Hello from output-job">>$GITHUB_OUTPUT
get-job:
name: Get values by needs
runs-on: ubuntu-latest
needs: output-job
steps:
- name: Use output-job output
run: echo"${{ needs.output-job.outputs.job_output }}"
输出日志如下:
文件存储和输出变量的异同
- 相同点:
都可以用于在同一 Workflow 的 Jobs 之间传递信息。
在同一 Workflow 中都需要关键字 “needs” 确保上传 Job 先执行或确保定义输出变量的 Job 先执行
- 区别:
文件存储方式需要上传和下载过程,可能会增加一些时间开销,特别是文件较大时,适用于传递大量数据或文件的场景更适用于传递大量数据或文件的场景
输出变量的方式直接在内存中传递,速度更快,适用于传递简单的变量和数据
跨 Steps 信息传递
对于跨 Steps 的数据传递,常见的方式有使用环境变量(environment variables)和 输出变量(output variables)
环境变量
由于 GitHub Actions 会在每个步骤开始时读取 $GITHUB_ENV 文件中定义的环境变量,所以可以通过 $GITHUB_ENV 的方式将数据存储为环境变量,给后续 Steps 使用。
需要注意的是, $GITHUB_ENV 写入的环境变量仅在当前 Job 的后续 Step 中有效,它们不会传递到其他 Job 或Workflow 中。
jobs:
environment-job:
runs-on: ubuntu-latest
steps:
- name: Set environment variable
run: echo"MY_VARIABLE=Hello From environment-step">>$GITHUB_ENV
- name: Use environment variable
run: echo$MY_VARIABLE
输出日志如下:
输出变量
$GITHUB_OUTPUT 是 GitHub Actions Workflow 中一个特殊的环境变量,它指向一个文件,用于存储 Step 的输出。
通过重定向操作符 >> 将其追加到环境变量 $GITHUB_OUTPUT 指向的文件中,后续的 Step 即可通过 id 和 output 名字 获取到对应的值。
jobs:
output-job:
runs-on: ubuntu-latest
steps:
- name: Set output variable
id: step1
run: |-
echo"my_output=Hello from output-step">>$GITHUB_OUTPUT
- name: Use output variable
run: echo"${{ steps.step1.outputs.my_output }}"
输出日志如下:
踩坑日记
以上总结了使用 Github Action 构建 CI/CD 流水线会用到的大部分相关知识。如果大家针对 Github Action 实现 CI/CD 还有其他疑惑,可以进一步去 Github action 官网查看相关文档:https://docs.github.com/en/actions
下面给大家分享一些文档记录外,我们所踩的坑。
Secret 引用错误
使用背景:存在 Step 如下:
- name: Deploy to Prod
run: ./deploy-prod.sh ${{ secrets.DB_USERNAME }}${{ env.DB_PASSWORD }}
前面我们提到, 在 Workflow中,如果存在 Secret: DB_PASSWORD, 可通过 ${{ secrets.DB_PASSWORD }} 的方式引用。
由于我们的 deploy-prod.sh 的脚本需要接收 DB_USERNAME 和 DB_PASSWORD 两个值,所以我们希望通过这种方式将值传输进去。
但是服务启动发现数据库连接有问题,层层排查后,发现是 DB_USERNAME 和 DB_PASSWORD 的值传输得不正确
这是因为在引用 secrets 或 Variable 或其他 env 时,需要根据情况来判断是否添加引号以及添加那种引号类型
引号类型和使用场景总结如下:
- ${{ secrets.DB_PASSWORD }}
没有引号,直接使用变量
适用于需要直接引用secrets的场景,例如直接传递给命令行参数。
- ‘${{ secrets.DASHSCOPE_API_KEY }}’
单引号包裹,适用于需要将变量作为字符串处理的场景。
单引号不会对内部的特殊字符进行转义处理,因此对于包含特殊字符的 Secret,需要特别注意。
- “${{ secrets.DASHSCOPE_API_KEY }}”
双引号包裹,适用于需要将变量作为字符串处理并且内部可能包含需要转义的特殊字符的场景。
双引号会对内部的特殊字符进行转义处理。
解决方案:由于我们的 Secret 中包含特殊字符,因此,我们需要通过双引号包裹进行引用。
输出变量丢失
使用背景:存在 Job-B 依赖于 Job-A 并想获取来自 Job-A 的 outputs
Job-A:
name: Pass values by needs
runs-on: ubuntu-latest
outputs:
job_output: ${{ steps.set-output.outputs.my_output }}
steps:
- name: Set output variable
id: set-output
run: echo"my_output=mock-test/${{ env.ACR_INSTANCE_ID }}/${{ env.IMAGE_NAME }}">>$GITHUB_OUTPUT
Job-B:
name: Get values by needs
runs-on: ubuntu-latest
needs: Job-A
- name: Use output-job output
run: echo"${{ needs.Job-A.outputs.job_output }}"
根据上面跨 Jobs 信息传递, 这个代码似乎没问题,但是Job-B 一直没有接收到 Job-A 的 Outputs,原因是 Job-A 拒绝传输 job_output, 拒绝原因:job_output 中包含 secrets。
进一步排查发现,因为 Github Action 的保护机制会拒绝传输 Secret, 而 my_output 中 ACR_INSTANCE_ID 的值刚好和 Secret: ACR_NAME_SPACE 值相同,因此 Job-A 拒绝传输 job_output。
解决方案:经过分析 ACR_NAME_SPACE 应归属于 Variables, 因此将其从 Secrets 中移除,问题即解决
解决思路:
创建 Secrets 时应谨慎,认真识别值属于 Secrets 还是 Variables
避免使用输出变量(Outputs)方式传输 Secrets,如果真的需要跨 Jobs 传递 Secrets,建议使用文件存储(Artifacts)方式进行传输
总结:
以上就是关于使用 GitHub Actions 构建 CI/CD 流水线的一些知识分析和心得体会啦,上文提到的所有Demo 大家感兴趣也可以移步至仓库进行查看:https://github.com/yzq327/react-redux-demo。
就个人而言,通过 Github Action 打造 CI/CD 流水线的过程是收获与“惊喜”并存的,这种方式的优缺点也是比较明显的
- 优点:
GitHub Actions 是 GitHub 原生的 CI/CD 工具,能够与 GitHub 仓库紧密集成,无需额外配置 Webhook 或集成第三方工具
GitHub Actions 提供了大量的预定义操作(Actions),可以帮助用户快速搭建 Workflow
通过 YAML 文件定义 Workflow,相对简单明了,易于阅读和维护
GitHub Actions 拥有庞大的社区支持,且GitHub 官方和社区会不断推出新的功能和优化,文档阅读起来也比较友好
- 缺点
只能在 GitHub 平台上使用,如果你的代码仓库不在 GitHub,那么无法使用 GitHub Actions,需要考虑其他 CI/CD 工具
在高峰期,可能会遇到队列延迟,影响构建和部署的及时性
如果没有 YAML 使用经验的话,学习如何编写和调试 YAML 文件可能需要一定学习成本,且尽管GitHub 提供了丰富的预定义操作,但在需要编写自定义操作时,仍需具备一定的开发和调试能力(不过,学习都需要成本,所以这个可能也不算缺点)
总的来说,如果用户已经选择 GitHub 作为代码托管平台, 那么选择 GitHub Actions 去构建 CI/CD 是很合适的
如果大家有空,也不妨自己玩儿一下~
最后,欢迎大家分享更多自己的感想和心得
版权归原作者 不负如来不负清 所有, 如有侵权,请联系我们删除。