Gitlab|Gitlab CI/CD教程及npm包构建发布实战

!!!实践过程中请留意文档版本号跟你实际使用Gitlab的版本号
中文文档-14.8-pre
【Gitlab|Gitlab CI/CD教程及npm包构建发布实战】Gitlab版本—12.9
前置知识
  1. yaml语法,教程YAML 入门教程
  2. Docker相关知识,教程Docker教程
  3. linux命令,教程Linux 命令大全
自定义配置目录
默认配置文件目录是在mono repo的根目录,文件名为.gitlab-ci.yml
若需要自定义设置CI脚本文件的路径,如下:
Gitlab|Gitlab CI/CD教程及npm包构建发布实战
文章图片

流水线配置
.gitlab-ci.yml文件中对流水线配置大致可以分为2个环节:
  1. 全局配置,运行在单个stage之前或者之后。
  2. 单个stage配置
结构大致可以如下:
# 指定脚本执行的镜像环境,如下为node环境为14.17.1 image: node:14.17.1# 单个job执行之前执行 before_script: - echo '====== 准备构建中 ========='# 配置单个stage的执行顺序,串行 stages: - install - build# 单个stage配置 # 安装依赖 npm_install: only: - master stage: install script: - yarn - ls -al# 单个stage配置 # 构建 webpack_build: only: - master stage: build script: - yarn build# 单个job全部执行完之后执行 after_script: - echo "====== 构建结束 ========="

重要概念
Pipeline 流水线,一次流水线相当于一次构建任务,里面可以包含多个阶段,比如install -> eslint -> build -> deploy等流程 ;
stages 表示构建阶段,每个stage串行同步执行。一旦有一个stage中的一个job失败了,那么下一个stage的任务便不会执行。如果当前stage定义了多个任务,那么其中一个任务失败,另外一个任务还是会被继续执行。但是只有当所有 stages 成功完成后,该构建任务 (Pipeline) 才算成功。
jobs job表示某个stage里面执行的工作 ,一个stage里面可以定义多个job 。
jobs有如下特点 :
  • 相同 stage 中的jobs 会并行执行
  • 相同 stage 中的 jobs 都执行成功时,该 stage 才会成功
  • 如果任何一个job 失败,那么该 stage 失败,即该构建任务 (Pipeline) 失败
gitlab runner 执行构建任务的一个服务,里面包含了持续集成的的环境,一般由docker创建。它可以在不同的主机上部署,也可以在同一个主机上设置多个gitlab-runner ,还可以根据不同的环境设置不同的环境,比如我们需要区分研发环境,测试环境以及正式环境等。
关键字
image CI/CD脚本运行环境的docker镜像,镜像就是一种文件存储形式,可以理解为是一个环境的集合,内含多种文件。如指定node环境镜像:
# 最新版本node环境 image: node:@latest

tags 指定gitlab 在执行脚本时使用哪个runner。
before_script 在单个stage执行之前执行的脚本内容,内容以数组形式配置,如上例子中:
before_script: - echo '====== 准备构建中 ========='

stages CI允许我们进行自定义的流水线阶段配置,可以将一个流水线拆分为多个阶段(stage),stages会串行执行。
stages: - install - build

script 执行脚本,脚本内容以数组形式配置。如上例子中stage为npm_install阶段执行的脚本为:
script: - yarn - ls -al

先执行yarn命令安装依赖,结束后查看了当前目录下文件及目录的具体信息,是个串行执行的过程。
cache 缓存多个流水线任务之间共用的文件和目录,缓存相关概念下文详情讲述。
only & except 设置流水线任务执行时机:使用 only 来定义job何时运行,使用 except 定义job不 运行的时间。
  • 指定分支触发执行时机
    job:only: - branches@gitlab-org/gitlab except: - main@gitlab-org/gitlab - /^release/.*$/@gitlab-org/gitlab

    此示例为 gitlab-org/gitlab 上的所有分支运行 job,除了 main 和以 release/ 开头的分支。
  • 在合并请求时触发
    job1: script: - echo "This job runs in merge request pipelines" only: - merge_requests

  • 在push的时候触发
    job1: script: - echo "branch push" only: - pushes

  • 手动触发
    在Gitlab Runner/pipeline里面点击run pipeline时触发
    job1: only: - web

  • 根据git提交消息或者判断分支触发执行时机
    build: script: - yarn build except: variables: - $CI_COMMIT_MESSAGE =~ /test/ || $CI_COMMIT_BRANCH == "main"

    git commit 消息为”test“的push跟提交分支为”main“的push不触发此job。
  • 根据文件修改判断执行时机
    build: script: yarn build except: changes: - "*.md"

    只要有md文件修改就不执行此job。
retry job重试次数,默认为0,最大重试次数为2,其中when可设置在特定失败原因的情况下执行。
rules:if 此字段可以在单个流水线job或者workflow字段下进行配置。
rules关键词下可以进行if语句配置,如果if满足的话可执行某些自定义配置。
rules: - if: $CI_COMMIT_REF_NAME =~ /feature/

注意: only & exceptrules:if都是用来决定单个job执行时机的,在配置时只能存在一个,否则会报错。
workflow 和rules配合用来控制流水香的执行动作,在最外层进行配置,workflow: rules 接受这些关键字:
  • if:检查此规则以确定何时运行流水线。
  • when:指定当if为 true 时要做什么。
    • 要运行流水线,请设置为 always
    • 要阻止流水线运行,请设置为 never
  • variables:如果未定义,则使用在别处定义的变量。适用版本13.11 ~14.0
当没有规则为 true 时,流水线不会运行。
以下示例中,前两天规则都匹配到不执行时机,当else时,流水线执行。
workflow: rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' when: never - if: '$CI_PIPELINE_SOURCE == "push"' when: never - when: always

when 控制上一个stage成功或者失败时,当前stage的行为。
  • on_success(默认值): 上一个stage成功了才会执行当阶段任务,或者之前失败的任务配置了allow_failure: true
  • on_failure :只有上一个阶段任务失败了才会执行当前任务。
  • always:无论上一个阶段的jobs状态如何,都会触发当前阶段的任务。
  • never:不运行当前任务。
  • manual:在gitlab网页中手动点击触发。
模块化
使用关键字include引入其他yml文件中的配置。
include: - '/yml/job1_install.yml' - '/yml/job2_lint.yml' - '/yml/job3_build.yml' - '/yml/job4_deploy.yml'

缓存
重要概念 在 GitLab CI/CD 中,我们所使用的 runner 是以 docker 的形式运行不同的任务。普通的 cache 机制(即不指定URL,No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted. ),其 cache 是存储在本地,所以如果两个 job 实际运行的位置是不用宿主机上的,其相互之间的缓存是无法共享的。
分布式缓存 分布式缓存需要runner配置支持,开启后需要在cache中配置s3ServerAddress、s3BucketName等信息进行缓存跨runner共享。
缓存路径 在配置cache时,pathsfiles的文件/目录都是以项目的根目录为相对位置的,在store cache的时候也是以项目名区分缓存路径的,应用缓存的时候会在项目下配合key值去应用缓存,即使是分布式缓存也是按照这个策略。
Gitlab|Gitlab CI/CD教程及npm包构建发布实战
文章图片

缓存文件信息上会有最后更新时间(重要信息)、文件权限、cache中设置的key等,其中更新时间跟缓存策略有联系,如果恶意篡改服务器时间,可能会出现依赖前后不一致导致打出来的包不符合预期的情况。
缓存绑定文件 缓存绑定到当前版本的文件。当这些文件之一发生变化时,将计算一个新的缓存键并创建一个新的缓存,如下:
cache-job: script: - echo "This job uses a cache." cache: key: files: - Gemfile.lock - package.json paths: - vendor/ruby - node_modules

此时的 key 是根据最近更改了每个列出的文件的提交计算得出的 SHA。如果在任何提交中都没有更改任何文件,则键就是默认值 default
多文件缓存 cache可以配置多个key,适用于13.10 ~ 13.12版本,其他版本可以在key下的filespaths配置多个路径/文件来实现。
禁用缓存 使用cache: {}来禁用缓存。
继承缓存 缓存配置可复用的情况下使用继承写法,可以在当前job下覆盖(重写)某个策略或者设置优先级
cache: &global_cache key: $CI_COMMIT_REF_SLUG paths: - node_modules/ - public/ - vendor/ policy: pull-pushjob: cache: # 继承全局缓存 <<: *global_cache # 重写缓存策略 policy: pull

回退缓存键 13.4版本以上可应用回退缓存键,功能类似缓存备份。你可以使用 CACHE_FALLBACK_KEY 变量来指定一个备份缓存key,他会在你指定key的缓存不存在时去查找应用备份缓存。
variables: CACHE_FALLBACK_KEY: fallback-keyjob1: script: - echo cache: key: "$CI_COMMIT_REF_SLUG" paths: - binaries/

手动清除缓存 您可以在 GitLab UI 中清除缓存:
  1. 在顶部栏上,选择 菜单 > 项目 并找到您的项目。
  2. 在左侧边栏上,选择 CI/CD > 流水线 页面。
  3. 在右上角,选择 清除 Runner 缓存。
在下一次提交时,您的 CI/CD 作业使用新的缓存。
实战:构建发布组件库到npm仓库
编写.gitlab-ci.yml基本流程,如下:
image: node:14.17.1before_script: - echo '====== 准备构建中 ========='stages: - install - lint - build - deploy### 配置缓存 cache: key: files: - package.json - packages/ghost-weapp-ui/package.json paths: - node_modules/ - packages/ghost-weapp-ui/node_modules/ ### 直接缓存.npm,.npm中缓存了所有依赖,因为gitlab缓存是分项目的,所以两种方法个人觉得没有什么区别 # - .npm/# eslint检测 job_lint: only: - master stage: lint before_script: - echo 'eslint检测' - ls -a script: - cd packages/ghost-weapp-ui - ls -a - yarn lint - echo 'eslint检测完成' retry: 0 when: 'on_success'# 安装依赖 job_install: only: - master stage: install before_script: - echo '安装依赖' script: - yarn config set registry https://registry.npm.taobao.org/ - yarn install - cd packages/ghost-weapp-ui - ls -a - yarn install - ls -a - echo '依赖安装完成' retry: 0# 打包编译 job_build: only: - master stage: build before_script: - echo '开始打包' script: - cd packages/ghost-weapp-ui - ls -a - yarn - ls -a - yarn build - echo '构建完成' when: 'on_success' retry: 0# 发布 job_deploy: only: - master stage: deploy before_script: - echo '更新补丁版本,准备发布' script: - cd packages/ghost-weapp-ui - node deploy.js ${CI_COMMIT_REF_NAME} when: 'on_success' retry: 0after_script: - echo "====== 发布完成 ========="

编写部署脚本,其中主要是模拟npm login流程替换为使用token进行登录并且执行npm publish,发布到npm的流程。
const fs = require('fs') const path = require('path') const os = require('os') const { exec } = require('child_process')// 替换为自己npm账号的authToken // token获取方法:vim ~/.npmrc const npmrcText = `registry=https://registry.npmjs.org/ home=https://www.npmjs.org //registry.npmjs.org/:_authToken=${authToken} `// 获取命令中第三个参数,此例子中为'master' // node deploy.js ${CI_COMMIT_REF_NAME}, 分支名为master const env = process.argv[2]// 拼接命令,执行npm publish,打tag function deploy() { fs.writeFileSync(path.resolve(os.homedir(), '.npmrc'), npmrcText) const argsArray = ['publish'].concat(['--tag', env === 'master' ? 'latest' : 'beta']) execa('npm', argsArray); }async function execa(a, arry = []) { return new Promise((resolve, reject) => { exec(`${a} ${arry.join(' ')}`, (err, stdout, stderr) => { if (err) { console.error(err); reject(err); } resolve(stdout) }) }) }deploy();

执行结果:
Gitlab|Gitlab CI/CD教程及npm包构建发布实战
文章图片

收到npm发布成功反馈邮件:
Gitlab|Gitlab CI/CD教程及npm包构建发布实战
文章图片

以上就是gitlab CI/CD的相关知识点以及实战发布npm包的示例,感谢阅读!

    推荐阅读