Skip to content

GitLab

.gitlab-ci.yml

yaml
before_script:
  - bundle install

after_script:
  - rm secrets

stages:
  - build
  - test
  - deploy

job1:
  stage: build
  script:
    - execute-script-for-job1
  only:
    - master
  tags:
    - docker

下面列出保留字段,这些保留字段不能被定义为 job 名称

关键字是否必须描述
image用于 docker 镜像,查看 docker 文档
services用于 docker 服务,查看 docker 文档
stages定义构建阶段
typesstages 的别名(已废除)
before_script定义在每个 job 之前运行的命令
after_script定义在每个 job 之后运行的命令
variable定义构建变量
cache定义一组文件列表,可在后续运行中使用

Job

.gitlab-ci.yml 允许指定无限量 jobs。每个 jobs 必须有一个唯一的名字,而且不能是关键字。job 由一列参数来定义 jobs 的行为。

yaml
job_name:
  script:
    - rake spec
    - coverage
  stage: test
  only:
    - master
  except:
    - develop
  tags:
    - ruby
    - postgres
  allow_failure: true
关键字是否必须描述
scriptyesRunner 执行的命令或脚本
imageno所使用的 docker 镜像,查阅使用 docker 镜像
servicesno所使用的 docker 服务,查阅使用 docker 镜像
stageno定义 job stage(默认:test)
typenostage 的别名(已弃用)
variablesno定义 job 级别的变量
onlyno定义一列 git 分支,并为其创建 job
exceptno定义一列 git 分支,不创建 job
tagsno定义一列 tags,用来指定选择哪个 Runner(同时 Runner 也要设置 tags)
allow_failureno允许 job 失败。失败的 job 不影响 commit 状态
whenno定义何时开始 job。可以是 on_success,on_failure,always 或者 manual
dependenciesno定义 job 依赖关系,这样他们就可以互相传递 artifacts
cacheno定义应在后续运行之间缓存的文件列表
before_scriptno重写一组在作业前执行的命令
after_scriptno重写一组在作业后执行的命令
environmentno定义此作业完成部署的环境名称
coverageno定义给定作业的代码覆盖率设置

Job 可以理解为 CI 流程中的单个任务是一个顶级元素(相当于 yml 配置的一个根元素),它可以起任意的名称、并且不限数量,但必须至少包含 script 子句,用于指定当前任务要执行的脚本

yaml
job1:
  script: execute-script-for-job1
job2:
  stage: build
  script:
    - scripts/build.sh
  only:
    - master
# job n...

stage

stage 允许一组 jobs 进入不同的 stages。jobs 在相同的 stage 时会 parallel 同时进行。

script

用于指定运行器要执行的脚本命令,可以指定多条

yaml
job:
  script:
    - echo  start job!
    - scripts/deploy.sh

before_scriptafter_script 用于定义应在 job 在执行脚本之前/后时要执行的内容

yaml
job:
  before_script:
    - echo  Execute this command before the `script` section completes.
  script:
    - echo  An example script section.
  after_script:
    - echo  Execute this command after the `script` section completes.

有时候,script 命令需要被单引号或者是双引号包裹起来。举个例子,当命令中包含冒号(:)时,script 需要被包在双引号中,这样 YAML 解析器才可以正确解析为一个字符串而不是一个键值对(key:value)。使用这些特殊字符的时候一定要注意::,{,},[,],,,&,*,#,?,|,-,<,>,=,!。

only 和 except

only 和 except 是两个参数用分支策略来限制 jobs 构建:

  • only 定义哪些分支和标签的 git 项目将会被 job 执行。
  • except 定义哪些分支和标签的 git 项目将不会被 job 执行。

策略规则

  • only 和 except 可同时使用。如果 only 和 except 在一个 job 配置中同时存在,则以 only 为准,跳过 except
  • only 和 except 可以使用正则表达式。
  • only 和 except 允许使用特殊的关键字:branches,tags 和 triggers。
  • only 和 except 允许使用指定仓库地址但不是 forks 的仓库(查看示例 3)。
yaml
job:
  # use regexp
  only:
    - /^issue-.*$/
    - /^release(\/|-)?.*$/
    - tags
    - triggers
  # use special keyword
  except:
    - branches

only 用于定义何时执行 job,反之 except 用于定义何时执行 job; 它们有四个关键字可以一起配合使用:

  • ref:匹配 分支名称 或 分支名匹配的的正则;
  • variables:变量表达式;
  • changes:对应路径的文件是否修改;
yaml
job1:
  script: echo
  only: # or except
    # - main # ref可省略
    ref:
      - tags
      - /^feat-.*$/
      - merge_requests
    variables:
      - $RELEASE ==  staging
      - $STAGING
    changes:
      - Dockerfile
      - docker/scripts/*
      - dockerfiles/**/*
      - more_scripts/*.{rb,py,sh}
      - **/*.json

allow_failure

用于配置当前 job 失败时 pipeline 是否应继续运行:

yaml
job2:
  stage: test
  script:
    - execute_script_2
  allow_failure: true # or false (default)

cache

指定缓存的文件列表,用户在不同的 job 之间共享

yaml
rspec:
  script:
    - echo  This job uses a cache.
  cache:
    key: binaries-cache
    paths:
      - binaries/*.apk
      - .config

cache:key:可以给每个缓存一个唯一的标识键,如果未设置,则默认键为 default; cache:paths:指定要缓存的文件或目录

retry

设置在 job 执行失败时候重试次数:

yaml
job:
  script: rspec
  retry:
    max: 2
    when: # 搭配when关键字,在下列情况下重试
      - runner_system_failure
      - stuck_or_timeout_failure

when

用于配置 job 运行的条件:

  • on_success(默认):仅在之前 stage 的所有 job 都成功或配置了 allow_failure: true;
  • manual:仅在手动触发时运行 job;
  • always:无论之前 stage 的 job 状态如何,都运行;
  • on_failure:仅当至少一个之前 stage 的 job 失败时才运行;
  • delayed:延迟执行 job;
  • never: 永不执行 job;
yaml
cleanup_build_job:
  stage: cleanup_build
  script:
    - cleanup build when failed
  when: on_failure

tags

选择特定 tag 的 GitLab-runner 来执行

yaml
job:
  tags:
    - ruby
    - postgres

Stages

stages 用来定义一次 CI 有哪几个阶段, stages 中的元素顺序决定了对应 job 的执行顺序: 同时每个 stage 可以与若干个 job 关联,即一个阶段可以并行执行多个 job。在每个 job 中使用 stage 关键字关联到对应 stage

  1. 相同 stage 的 job 可以平行执行。
  2. 下一个 stage 的 job 会在前一个 stage 的 job 成功后开始执行。

接下仔细看看这个例子,它包含了 3 个 stage:

yaml
stages:
  - build
  - test
  - deploy

job_build:
  stage: build
  script:
    - scripts/build.sh

job_test:
  stage: test
  script:
    - scripts/test.sh

job_deploy:
  stage: deploy
  script:
    - scripts/deploy.sh
  • 首先,所有 build 的 jobs 都是并行执行的。
  • 所有 build 的 jobs 执行成功后,test 的 jobs 才会开始并行执行。
  • 所有 test 的 jobs 执行成功,deploy 的 jobs 才会开始并行执行。
  • 所有的 deploy 的 jobs 执行成功,commit 才会标记为 success
  • 任何一个前置的 jobs 失败了,commit 会标记为 failed 并且下一个 stages 的 jobs 都不会执行。

TIP

1.如果.gitlab-ci.yml 中没有定义 stages,那么 job’s stages 会默认定义为 build,test 和 deploy。

2.如果一个 job 没有指定 stage,那么这个任务会分配到 test stage。

Cache

yaml
variables:
  WEB_IMAGE: rm/rm-front
  ALI_WEB_IMAGE: xtepapp/rm-front
  DOCKER_BUILDER_IMAGE: rm_front_builder_image
  DOCKER_BUILDER_RUNNER: rm_front_builder_image_runner_$CI_COMMIT_REF_NAME-$CI_JOB_ID
  DOCKER_DIST_IMAGE: $REGISTRY/$WEB_IMAGE:dev
before_script:
  - echo "begin to run script"
  - docker login -u $HARBOR_USER -p $HARBOR_PASSWD $REGISTRY
  - docker login -u $ALI_USER -p $ALI_PASSWD $ALI_REGISTRY

stages:
  - dump
  - build
  - install
  - deploy
  - trigger

web:echo:
  stage: dump
  script:
    - echo $CI_BUILD_TAG
  only:
    - aliyun-dev
    - /^release(\/|-)?.*$/

web:dist:build:aliyun:dev:
  stage: build
  variables:
    SERVER_URL: https://47.110.222.89:18442
    EVN_CONFIG: build:dev
  before_script:
    - docker stop $DOCKER_BUILDER_RUNNER && docker rm $DOCKER_BUILDER_RUNNER
  script:
    - export TAG=aliyun-dev
    - docker build -t $DOCKER_BUILDER_IMAGE --build-arg SERVER_URL=$SERVER_URL --build-arg EVN_CONFIG=build:dev  -f ./Dockerfile.build .
    - docker stop $DOCKER_BUILDER_RUNNER && docker rm $DOCKER_BUILDER_RUNNER
    - docker run --name $DOCKER_BUILDER_RUNNER $DOCKER_BUILDER_IMAGE /bin/bash
    - docker cp $DOCKER_BUILDER_RUNNER:/src/app/backup-dev ./docker/dist
    - docker cp $DOCKER_BUILDER_RUNNER:/src/app/dist ./docker/dist/rm-front-pro
    - export ALI_DOCKER_IMAGE=$ALI_REGISTRY/$ALI_WEB_IMAGE:$CI_BUILD_REF_NAME
    - docker build --pull -t $ALI_DOCKER_IMAGE ./docker
    - docker push $ALI_DOCKER_IMAGE
  only:
    - aliyun-dev
  after_script:
    - docker stop $DOCKER_BUILDER_RUNNER && docker rm $DOCKER_BUILDER_RUNNER

web:cd:deploy:aliyun:dev:
  stage: deploy
  script:
    - docker pull $ALI_REGISTRY/xacr-basis/xtep-python3
    - docker run -v "$(pwd)/deploy":/deploy $ALI_REGISTRY/xacr-basis/xtep-python3 python3 /deploy/dockercdedas.py xrun-frontend
  only:
    - aliyun-dev

web:dist:build:aliyun:prod:
  stage: build
  variables:
    SERVER_URL: https://xrc.321go.com
    EVN_CONFIG: build:prod
  before_script:
    - docker stop $DOCKER_BUILDER_RUNNER && docker rm $DOCKER_BUILDER_RUNNER
  script:
    - export TAG=prod
    - docker build -t $DOCKER_BUILDER_IMAGE --build-arg SERVER_URL=$SERVER_URL --build-arg EVN_CONFIG=build -f ./Dockerfile.build .
    - docker stop $DOCKER_BUILDER_RUNNER && docker rm $DOCKER_BUILDER_RUNNER
    - docker run --name $DOCKER_BUILDER_RUNNER $DOCKER_BUILDER_IMAGE /bin/bash
    - docker cp $DOCKER_BUILDER_RUNNER:/src/app/backup-prod ./docker/dist
    - docker cp $DOCKER_BUILDER_RUNNER:/src/app/dist ./docker/dist/rm-front-pro
    - docker build -t $REGISTRY/$WEB_IMAGE:$TAG --build-arg CONT_IMG_VER=prod --pull ./docker
  only:
    - /^release(\/|-)?.*$/
  after_script:
    - docker stop $DOCKER_BUILDER_RUNNER && docker rm $DOCKER_BUILDER_RUNNER

web:dist:install:aliyun:prod:
  stage: install
  before_script:
    - echo 'push aliyun images'
  script:
    - export TAG=prod
    - export ALI_DOCKER_IMAGE=$ALI_REGISTRY/$ALI_WEB_IMAGE:$CI_BUILD_REF_NAME
    - docker tag $REGISTRY/$WEB_IMAGE:$TAG $ALI_DOCKER_IMAGE
    - docker push $ALI_DOCKER_IMAGE
  only:
    - /^release(\/|-)?.*$/
web:cd:deploy:aliyun:prod:
  stage: deploy
  script:
    - docker pull $ALI_REGISTRY/xacr-basis/xtep-python3
    - docker run -v "$(pwd)/deploy":/deploy $ALI_REGISTRY/xacr-basis/xtep-python3 python3 /deploy/dockercdedas.py xrun-frontend
  only:
    - feature-to-aliyun

GitLab CI 配置文件

variables

GitLab CI 允许在.gitlab-ci.yml 文件中添加变量,并在 job 环境中起作用。因为这些配置是存储在 git 仓库中,所以最好是存储项目的非敏感配置,例如:

yaml
variables: DATABASE_URL:"postgres://postgres@postgres/my_database"

这些变量可以被后续的命令和脚本使用。服务容器也可以使用 YAML 中定义的变量,因此我们可以很好的调控服务容器。变量也可以定义成 job level。

除了用户自定义的变量外,Runner 也可以定义它自己的变量。CI_COMMIT_REG_NAME 就是一个很好的例子,它的值表示用于构建项目的分支或 tag 名称。除了在.gitlab-ci.yml 中设置变量外,还有可以通过 GitLab 的界面上设置私有变量

可用于定义执行过程中的一些变量

yaml
variables:
  DEPLOY_SITE: https://example.com/

deploy_job:
  stage: deploy
  script:
    - deploy-script --url $DEPLOY_SITE --path  /

deploy_review_job:
  stage: deploy
  variables:
    REVIEW_PATH: /review
  script:
    - deploy-review-script --url $DEPLOY_SITE --path $REVIEW_PATH