Skip to main content

编写 GitLab CI 脚本(.gitlab-ci.yml)

一定要多看官方的 templates

能找到很多灵感。例如要用 Docker 打包的 Laravel 项目,就综合看 Docker.gitlab-ci.yml 和 Laravel.gitlab-ci.yml。 所有模板:https://gitlab.com/gitlab-org/gitlab-foss/tree/master/lib/gitlab/ci/templates

如果未在作业中定义 when,则默认值为 when: on_success

https://gitlab.yitasoft.com/help/ci/yaml/index#when

if 可用的表达式

https://gitlab.yitasoft.com/help/ci/jobs/job_control.md#cicd-variable-expressions

当脚本命令返回非零的 exit code 时,作业将失败并且不会执行其他命令

解决方法是将退出代码存储在变量中,例如:

job:
script:
- false || exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;

when: never 只能在 rules 里面使用

rules:
- when: never

设置任务失败后的重试次数

默认是0,但是有些时候,任务遇到意外情况执行失败,只要原样重试一次就通了,很玄学。

job:
retry: 1

在 gitlab-ci 中,单引号/双引号里面都可以用变量

  • 仅限括起来的完整语句,

变量赋值除外,例如:

Good:

script:
- 'URL=http://gitlab.example.com/jobs/$CI_JOB_ID'
- 'curl $URL'

Bad:

script:
- URL='http://gitlab.example.com/jobs/$CI_JOB_ID'
- curl '$URL'

最终得到的是原样的字符串。

如何传 JOB ID 给后续的任务?

在同一个管道中,只能通过 JOB ID 获取对应的 Artifact,其它任何的方式获取 Artifact 都是返回 404,因为 GitLab 做了限制:只有流水线完全执行成功以后,才可以用诸如 https://gitlab.yitasoft.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/$CI_COMMIT_TAG/raw/dist.zip?job=release-zip 之类的 API 通过 job name 获取最新的 artifact。

官方文档:https://gitlab.yitasoft.com/help/ci/variables/index.md#pass-an-environment-variable-to-another-job

注意:

  • 生产 .env 文件的 Job 一定要手动加 artifacts:reports:dotenv:xxx 才能缓存该 .env 文件。
  • 其它 Job 使用自定义的 .env 时不需要再定义 artifacts 了,可以直接使用 .env 里面的变量。

示例:

release:
artifacts:
reports:
dotenv: release.env
script:
# 传变量给后面的 job
- echo "RELEASE_JOB_ID=$CI_JOB_ID" >> release.env

deploy:
script:
# 利用此 API 根据 Job ID 获取上个任务 (release) 生产的 artifact
- api_url='https://gitlab.yitasoft.com/api/v4/projects/$CI_PROJECT_ID/jobs/$RELEASE_JOB_ID/artifacts/dist.zip'

简单的纯前端项目,直接在生产环境 build 最新代码

在生产环境服务器上做如下操作:

variables:
DEPLOY_DIR: '/var/www/$CI_PROJECT_NAME'
script:
# node 环境
- export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
- nvm -v
- nvm use --lts
# 打包
- npm install
- npm run build
# 将打包后的产物移动到要部署的目录
- cd $DEPLOY_DIR

注意:

  • 这里不需要手动去 pull 最新代码,GitLab SSH Runner 已经帮我们做好。
  • script 默认的执行目录是 gitlab-runner 创建的临时目录,里面有我们本次 CI 对应版本的代码。

同时执行多行脚本

注意点:

  • 使用 - | 开头并另起一行。
  • 严格缩进。
  • CI 中会把多行命令都集中一起执行,只会在 console 中得到一个合并后的统一的输出以及 exit 返回值。
  • 直接导致的问题是,增加了调试里面具体某行命令的难度。

技巧:

  • 在开发调试 CI 时,复杂的多行命令最好用放单独脚本中,调好了该脚本,再放进 CI 里执行。这才是正道。
job:
script:
# 安装依赖(含有私库,需要根据 .npmrc 的内容传相应变量)
- |
GITLAB_PROJECT_ID=$CI_PROJECT_ID \
GITLAB_NPM_REGISTRY_AUTH_TOKEN=$CI_JOB_TOKEN \
npm install
- npm run build