使用 Gitlab CI/CD 自动打包和部署微前端
前段时间微前端实践:single-spa+vite的方式对项目进行了整合,也用 使用 Gitlab CI/CD 自动打包和部署微前端
基础概念
- jobs
- 定义在
pipeline
中的单个任务
- 定义在
stage
- 用于组合
job
, 官方提供了一些默认值.pre
build
test
deploy
.post
, 除了这些默认值以外, 可以通过全局关键字stages
自定义 stage
是从上到下按序执行,stage
中的job
是并行运行的, 可以通过needs
/dependencies
更改
- 用于组合
pipeline
- 是一组
job
的集合, 也代表 CI/CD 处理流程, 这些job
可以并行/按顺序运行 - 可以通过多种方式触发, 触发来源可通过
CI_PIPELINE_SOURCE
获取 (ci_pipeline_source)
- 是一组
runner
- 一个应用程序, 在服务器安装以及通过
token
注册之后, 可以监听以及运行分配给它的job
- 可以通过安装 gitlab 实例/群组/项目级别的 runner, 以及在
job
中定义tag
等来管理 runner 以及分配任务
- 一个应用程序, 在服务器安装以及通过
executor
- 设置
job
运行的环境, 可以根据不同的环境来选择
- 设置
artifacts
- 用于存储
job
生成的文件或数据, 可以通过expire
字段定义其过期时间
- 用于存储
cache
- 用于缓存会复用文件或者文件夹, 比如包依赖, 打包工具之类的, 用以加速构建速度
实现思路
思路可以有很多种,这里就说下我试过的
最后的结果主应用和微应用会整合为一个文件,也就是只有一个 nginx,一个端口,一个镜像文件
git sub-modules
使用 git sub-modules 打包微前端是一种可行方案, 通过
git sub-modules
由主应用绑定微应用但是由于是单向的,所以只适合从主应用作为入口点来完成整个流程,这在测试和开发阶段是不太方便的,所以最后没有采用
仓库之间相互触发
- 微应用和主应用程序都可以作为入口点, 相互调用 pipeline 以完成整个构建任务
- 不管从哪个入口进入,进入的时候都应该记录当下环境信息或者其他业务逻辑相关的信息,比如版本信息可能从 commit 或者 tag 中提取, 这些信息后续部署的
job
以及其他应用都可能会用到 - 任何上传了
artifacts
的job
都应该记录其CI_JOB_ID
, 用于后续其他应用下载其artifacts
微应用发生了变更,以微应用作为入口触发
- => 构建微应用并上传
artifacts
(打包后的结果) - => 触发主应用
pipeline
, 可以指定主应用的稳定版本 artifacts id,避免主应用以及其他子应用重新打包
1 | image: node:20.16.0 |
主应用发生了变更,从主应用作为入口触发
- 在生产环境中,以安全为考量因素,或者在开发测试阶段为了快速部署,大部分时候我们其实不需要现打包子应用,可以考虑以 tag 或者分支为凭据收集稳定版本的子应用的
artifacts
- 需要现打包子应用
- => 提取环境变量, 然后携带相关参数调用子应用
pipeline
- => 打包单个子应用:等待子应用构建完成后, 再由子应用重新触发主应用
pipeline
- => 同时打包多个子应用时:其实不太会碰到需要同时打包多个子应用的情况,因为每一个应用变更都会触发一次构建流程,那么最新的主应用 artifacts 就会更新
- 但是如果有,可以在调用多个子应用
pipeline
后通过 scheduled pipeline 来定时检查子应用pipeline
的构建情况
- 但是如果有,可以在调用多个子应用
- => 打包单个子应用:等待子应用构建完成后, 再由子应用重新触发主应用
- => 提取环境变量, 然后携带相关参数调用子应用
不管从哪个入口进入,最后都会到主应用来完成整个镜像打包以及部署流程
- => 构建部署文件,在这个
job
里会生成所有需要的文件和信息,并作为artifacts
上传- => 主应用构建,(如果主应用没有变化,那可以以 tag 或者分支为凭据下载之前构建的
artifacts
, 然后再根据子应用情况来决定是否重新打包替换文件)- => 根据子应用构建
job
的id
来收集子应用artifacts
- => 根据环境和版本信息生成并存储
docker
镜像的tag
, 存储tag
是因为在k8s
部署的时候需要设置image
的地址
- => 根据子应用构建
- => 主应用构建,(如果主应用没有变化,那可以以 tag 或者分支为凭据下载之前构建的
- => 从
build job
的artifacts
获取docker
镜像的信息, 然后构建并推送docker
镜像 - => 从
build job
的artifacts
里获取docker
镜像的信息 , 更新k8s
资源
1 | frontend_build: |
1 | !/bin/bash |
构建 docker 镜像
官方提供多种方式, 这里就只列举了两个尝试过的
- 如果运行器的执行器也是 docker, 在 docker 中构建 docker, (using_docker_build)
- 使用
kaniko
更简单些 (using_kaniko),kaniko
不要求Docker daemon
以及privileged mode
, 适合一些无法运行 Docker 的场景, 比如Kubernetes
或者CI/CD pipelines
1 | frontend_image_build: |
使用 k8s 部署
1 | frontend_image_deploy: |
在多个仓库之间的交互方式
- 通过 GitLab API 在脚本中互相调用
pipeline
(Trigger pipelines by using the API) web hook
, 可以通过web hook
监听push
merge
之类的事件来调用pipeline
如何在 job
或者 pipeline
之间分享变量
- 这里的变量指的是一些动态变量, 比如环境信息可能从
commit
信息中提取, 或者从外部获取来的, 这些信息可能后面的job
也会用到, 那就需要将这些变量传递下去
artifacts
可以将变量存储在
artifacts
中, gitlab 不会默认提供artifacts
访问能力, 需要通过need
或者dependencies
配置允许保留上一个job
的artifacts
needs
/dependencies
这两个配置都可以用来定义 job 的执行顺序以及提供artifacts
的访问能力,dependencies
主要用于定义artifacts
的依赖关系, 表明当前任务的运行依赖于某些任务的artifacts
needs
用于定义job
的依赖关系, 这就会包含artifacts
的访问权限- 由于同一个
stage
中的job
是并行运行的, 所以在同一个stage
中的artifacts
的分享就需要使用needs
而不是dependencies
(https://docs.gitlab.com/ee/ci/yaml/index.html#dependencies)
1
2
3
4
5
6
7
8保存
echo "ENV=$ENV" > shared_vars.env
echo "REF=$REF" >> shared_vars.env
保存多个
declare -p VAR3 VAR4 >> shared_vars.env
使用
source shared_vars.env
echo $ENVartifacts
会被上传, 那么通过下载artifacts
自然也能在pipeline
之间共享变量
1 | curl --location --output artifact.zip "https://gitlab.example.cn/api/v4/projects/${CI_PROJECT_ID}/jobs/${CI_JOB_ID}/artifacts?job_token=$CI_JOB_TOKEN" |
通过 pipeline api 携带
pipeline
可以通过 api 调用, api 的 variables
可以用来传递一些额外的变量, 这些变量拥有最高的优先权, 可以覆盖其他任何同名的变量, 这些变量在 job
详情页面也可以看到
pass-cicd-variables-in-the-api-call
1 | curl --request POST \ |
变量相关 api
通过使用 GitLab CI/CD 项目/组级别的变量增删改相关的 api, 也可以达到在 job
或者 pipeline
动态传递变量的目的, 但是毕竟是全局变量,也可能有权限问题, 酌情使用 (project_level_variables),
QA
- error: This job is stuck because the project doesn’t have any runners online assigned to it.
- job are assigned by
tag
, or enable the runner to run without tags
- job are assigned by
- error: could not read Username for ‘https://gitlab.com‘: No such device or address on Gitlab CI
- make sure Allow access to this project with a
CI_JOB_TOKEN
switch is enabled
- make sure Allow access to this project with a
更新时间:2025-01-23
转载请注明来源,欢迎指出任何有错误或不够清晰的表达