02: gitlab-ci.yml 文件编写

文章目录

    • 什么是gitlab-ci.yml文件
    • 创建第一个 gitlab-ci.yml 文件
    • 特殊指令
      • before_script
      • after_script
      • variables
      • stages
      • rules and only/except
      • cache
      • artifacts
      • include
      • extends

什么是gitlab-ci.yml文件

gitlab-ci.yml 文件是 GitLab CI/CD 的配置文件,它描述了各项任务如何和何时在版本控制过程中执行。文件中定义了一系列的任务或"jobs",这些jobs可以被组织到各个阶段,并在触发某些事件时自动运行,如代码提交或代码合并。每次提交或推送都会触发一个新的 CI/CD “pipeline”,gitlab-ci.yml 文件便是负责协调和控制这个 pipeline 执行过程的大脑。

创建第一个 gitlab-ci.yml 文件

文件结构示例

stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  script: 
    - echo "This is the build stage"

test_job:
  stage: test
  script:
    - echo "This is the test stage"

deploy_job:
  stage: deploy
  script:
    - echo "This is the deploy stage"

stages 定义一组阶段,然后在每个工作描述中使用 stage 关键字指定其属于哪个阶段。GitLab CI/CD将会按照 stages 定义的阶段顺序以及每个阶段内的作业并行度来执行作业。

特殊指令

before_script

通常before_script在gitlab-ci.yml 文件的顶层定义,作为全局设置。这样定义的 before_script 会在每个作业(job)执行前都会运行。before_script 虽然有全局配置的偏好,但也可以根据需要在单独的作业中定义。

# 在这个配置中,全局 before_script 会在 job1 和 job2 两个作业之前都执行一次。
stages:
  - build
  
before_script:
  - echo "This is a global before_script."
  
job1:
  stage: build
  script: echo "This is job1."

job2:
  stage: build
  script: echo "This is job2."

也可以在具体的作业中定义 before_script,这样设置的 before_script 会只影响这个作业。

# job1 的 before_script 被重写为 "echo "This is a job-specific before_script."",并且只在 job1 执行前运行。
# 全局的 before_script 不会在 job1 之前执行,但会在 job2 之前执行。 
# 作业特定的 before_script 会覆盖全局的定义。
stages:
  - build
  
before_script:
  - echo "This is a global before_script."

job1:
  stage: build
  before_script:
    - echo "This is a job-specific before_script."
  script: echo "This is job1."

job2:
  stage: build
  script: echo "This is job2."

after_script

after_script:它类似于 before_script,定义在这里的命令会在每个作业(job)的 script 部分执行完毕后运行。这常常用来在作业完成之后清理环境或存储日志等。

variables

可以定义一组环境变量,这些变量会在所有作业中可用。例如,你可能需要在多个作业中使用同一个数据库的链接地址。

stages:
  - build
variables:
  DATABASE_URL: "postgres://user:[email protected]:5432/dbname"
job1:
  stage: build
  script: echo "The database url is $DATABASE_URL."

stages

定义作业的执行阶段。GitLab CI/CD 会按照 stages 的顺序执行作业。

stages:
  - build
  - test
job1:
  stage: build
  script: echo "Build stage"
job2:
  stage: test
  script: echo "Test stage"

rules and only/except

这两个指令都用于定义作业执行的条件。例如,你可以设置一个作业只在特定分支的提交时运行。

stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  script: echo "This is building stage."
  only:
    - master

test_job:
  stage: test
  script: echo "This is testing stage."
  except:
    - master

deploy_job:
  stage: deploy
  script: echo "This is deploying stage."
  rules:
    - if: '$CI_COMMIT_BRANCH == "master"'
      when: always
    - if: '$CI_COMMIT_BRANCH != "master"'
      when: never

build_job 仅在主分支(master)上运行。相反,test_job会在所有分支上运行,除非是主分支。deploy_job 也仅在主分支上运行,使用了 rules 指令来实现这个条件,这是一个更复杂的条件判断,不同的规则 (if 语句)可以应对更为复杂的情况。

cache

允许你定义一个缓存,这个缓存可以在作业之间共享。这常常用于缓存依赖,以加快构建的速度。

stages:
  - install
  - build

variables:
  BUNDLE_PATH: vendor/bundle

cache: 
  paths:
    - vendor/bundle

install:
  stage: install
  script:
    - bundle install --path vendor/bundle

build:
  stage: build
  script:
    - bundle exec rake build

在这个示例中,我们将 Ruby gems 安装到 vendor/bundle 目录下,然后在 cache 指令中声明这个路径来缓存这些 gems。

这样做的好处是,当在后续的作业或者后续的 pipeline 运行时,不需要重新下载和安装这些 gems,在此 .gitlab-ci.yml 文件的配置中,如果 cache 设置正确并且有效,然后在 vendor/bundle 路径下的gems没有发生变化(即 Gemfile 和 Gemfile.lock 文件没有发生改变),那么 bundle install --path vendor/bundle 命令就不会再次下载已经缓存的 gems。这是因为 Bundler(Ruby的依赖管理工具)会检查 gems 是否已经存在,如果已经存在并且版本匹配,那么就不会再次下载。

综上,对于重复的 install 作业,如果 Gemfile 和 Gemfile.lock 中的内容没有发生变化,那么即使在 pipeline 再次运行此作业,也不会再次下载已经缓存的 gems,从而可以加快构建的速度。可以大大减少构建的时间。

install 和 build 两个作业分别在 install 和 build 阶段运行。install 阶段会使用 bundle install 命令来下载和安装 gems,build 阶段则使用 bundle exec 来执行构建命令。
通过这个配置,我们就可以在多个作业之间,以及多次 pipeline 运行之间共享这些 gem 的缓存,以此来加快构建的速度。

对于重复的 install 作业,在下次pipeline中会再次运行吗?
如果 cache 设置正确并且有效,然后在 vendor/bundle 路径下的gems没有发生变化(即 Gemfile 和 Gemfile.lock 文件没有发生改变),那么 bundle install --path vendor/bundle 命令就不会再次下载已经缓存的 gems。这是因为 Bundler(Ruby的依赖管理工具)会检查 gems 是否已经存在,如果已经存在并且版本匹配,那么就不会再次下载。

综上,对于重复的 install 作业,如果 Gemfile 和 Gemfile.lock 中的内容没有发生变化,那么即使在 pipeline 再次运行此作业,也不会再次下载已经缓存的 gems,从而可以加快构建的速度。

artifacts

声明一些构建产物,这些产物将会在 gitlab-ci.yml 文件中其他作业或后续阶段的作业中可用,或者可供直接下载查看。

stages:
  - build
  - test

build:
  stage: build
  script: 
    - mkdir build
    - echo "Build artifacts" > build/artifacts.txt
  artifacts:
    paths:
      - build/

test:
  stage: test
  script: 
    - cat build/artifacts.txt

在这个示例中,我们的 pipeline 分为两个阶段:build 和 test。在 build 阶段运行的 build 作业中,我们创建了一个 build 目录,并在其中生成了一个名为 artifacts.txt 的文件。

然后,我们使用 artifacts 指令声明了 build/ 路径下的所有文件都是构建产物,GitLab CI/CD 将会在构建完成后收集这些产物。

在后续的 test 阶段的 test 作业中,我们可以直接访问到这个 artifacts.txt 文件。也就是说,通过 artifacts 允许我们在后续阶段的作业中使用到前一阶段的构建产物。

include

用于在当前 .gitlab-ci.yml 文件中引入其他的 CI/CD 配置文件,可以实现配置的模块化和共享。被引入的文件可以位于同一项目的其它位置,也可以位于其他项目,甚至可以从远程的 HTTP(S) URL 中引入。引入的文件将像是在主配置文件中一样被解析和执行,这对于大型项目或需要共享 CI/CD 配置的情况很有用。
比如说,你有一个库 my-great-library。该库有自己的 .gitlab-ci.yml 文件,如下:

variables:
  BUILD_DIR: build

stages:
  - build
  - test

build:
  stage: build
  script:
    - mkdir ${BUILD_DIR}
    - echo "Building the library" > ${BUILD_DIR}/result.txt

test:
  stage: test
  script:
    - echo "Testing the library"

而你在其他许多项目里都依赖这个库,并且需要对这个库进行构建和测试。这时,你可以在其他项目的 CI 标记 include,将这个库的 CI/CD 配置包含进来,例如:
项目 project-1 的 .gitlab-ci.yml:

include:
  - project: 'yourusername/my-great-library'
    file: '.gitlab-ci.yml'

这样就可以实现在多个项目中共享一个统一的 CI/CD 配置,避免了每个项目都需要重复编写相同的配置,从而大大提高了效率。同时也有利于集中管理和修改这个共享的配置。

extends

用于复用已经定义的特定配置。在 GitLab CI/CD 配置中,我们可以定义一些通用的配置作为模板,例如设定重用的 script 块或者 before_script 块等,然后在需要的地方使用 extends 进行引用。不同于 include 关键词,extends 并不会引入新的文件,而是仅仅在当前文件内部进行配置的重用。

# 我们首先声明一个 '.base_job',这个定义包含了所有作业共有的部分
.base_job:
  before_script:
    - echo "Setting up the job environment"
  after_script:
    - echo "Cleaning up after job"

# '.build_template' 扩展了 '.base_job',并添加了构建阶段特有的设定
.build_template:
  extends: .base_job
  variables:
    BUILD_DIR: build
  script:
    - mkdir ${BUILD_DIR}
    - echo "Building the project" > ${BUILD_DIR}/output.txt
  stage: build

# '.test_template' 也扩展了 '.base_job',然后添加了测试阶段特有的设定
.test_template:
  extends: .base_job
  script:
    - echo "Testing the project"
  stage: test

# 现在我们定义具体的构建和测试作业,它们分别扩展了 '.build_template' 和 '.test_template'
job1:
  extends: .build_template
  variables:
    JOB_NAME: JOB1

job2:
  extends: .test_template
  variables:
    JOB_NAME: JOB2

stages:
  - build
  - test

通过 .base_job,我们为所有作业指定了公共的 before_script 和 after_script。然后,对于构建和测试阶段,我们又分别创建了扩展了 .base_job 的 .build_template 和 .test_template。最后,我们创建了两个具体的作业 job1 和 job2,它们扩展了各自的模板并添加了一些特定的配置。.base_job作为模板,.build_template和.test_template去继承它,如果二者都有相同的key,则使用子类的value覆盖父类,同理job1和job2。

你可能感兴趣的:(GitLab,CI,入门,gitlab,ci/cd,git)