GitLab CI/CD中.gitlab-ci.yml的使用

基本概念

CI/CD

CI,Continuous Integration,持续集成。即在代码构建过程中持续地进行代码的集成、构建、以及自动化测试等;有了 CI 工具,我们可以在代码提交的过程中通过单元测试等尽早地发现引入的错误;

CD,Continuous Deployment,持续部署。在代码构建完毕后,可以方便地将新版本部署上线,这样有利于快速迭代并交付产品。

GitLab CI/CD

GitLab CI/CD(后简称 GitLab CI)是一套基于 GitLab 的 CI/CD 系统,可以让开发人员通过 .gitlab-ci.yml 在项目中配置 CI/CD 流程,在提交后,系统可以自动/手动地执行任务,完成 CI/CD 操作。而且,它的配置非常简单,CI Runner 由 Go 语言编写,最终打包成单文件,所以只需要一个 Runner 程序、以及一个用于运行 jobs 的执行平台(如裸机+SSH,Docker 或 Kubernetes 等,我推荐用 Docker,因为搭建相当容易)即可运行一套完整的 CI/CD 系统。

下面针对 Gitlab CI 平台的一些基本概念做一个简单介绍:

Job

Job 为任务,是 GitLab CI 系统中可以独立控制并运行的最小单位。 在提交代码后,开发者可以针对特定的 commit 完成一个或多个 job,从而进行 CI/CD 操作。

Pipeline

Pipeline 即流水线,可以像流水线一样执行多个 Job. 在代码提交或 MR 被合并时,GitLab 可以在最新生成的 commit 上建立一个 pipeline,在同一个 pipeline 上产生的多个任务中,所用到的代码版本是一致的。

Stage

Stage 即阶段。一般的流水线通常会分为几段;在 pipeline中,可以将多个任务划分在多个阶段中,只有当前一阶段的所有任务都执行成功后,下一阶段的任务才可被执行。

如果某一阶段的任务均被设定为“允许失败”,那这个阶段的任务执行情况,不会影响到下一阶段的执行。

CI Pipeline

20190308085430788.png
上图中,整条流水线从左向右依次执行,每一列均为一个阶段,而列中的每个可操控元素均为任务。 左边两个阶段的任务是自动执行的任务,在 commit 提交后即可自动开始运行,执行成功或失败后,可以点击任务右边的按钮重试;而右边两个是手动触发任务,需要人工点击右边的“播放”按钮来手动运行。

.gitlab-ci.yml的作用

  • 要实现GitLab CI / CD,首先需要的是一个名为.gitlab-ci.yml放置在您网站根目录下的配置文件。
  • 这个文件实际上做的是告诉GitLab Runner像在命令行中那样运行脚本。Runner充当终端。GitLab CI / CD告诉Runner要运行哪些命令。两者都内置在GitLab中,无需为它们设置任何工作。

.gitlab-ci.yml的结构

Job

GitLab中的每一个都由若干个job来组织,这是一组要应用于该特定任务的脚本和设置。

job:
    script: 
        - dotnet test

对于GitLab dotNet Core,这个job名称有一个特定的名称test,他告诉Runner希望该任务使用dotnet部署该项目:

test:
    script: 
      - dotnet test

artifacts回传生成文件

我们还需要告诉Runner这个项目会生成文件,这些文件的存储位置用paths来指定目录位置。例如下面的代码就将生成文件指定在了项目根目录的bin文件夹中。

test:
    script:
      - dotnet build
    artifacts:
      paths:
        - bin/

Image镜像指定

在这一点上,你可能会问自己:“好吧,但是要部署C#项目我需要dotnet。dotnet在那个脚本上的位置是什么?”。答案很简单:GitLab Runner将在您.gitlab-ci.yml的头脑中寻找的第一件事是Docker镜像,指明在容器中运行该脚本需要什么:

 image: microsoft/dotnet:latest

本例中制定了GitLab Runner采用dotNet最新版镜像。

Stages阶段

要记住的另一个有趣的概念是构建阶段Stage。你的项目可能需要通过大量测试和其他任务,直到它部署到临时或生产环境。GitLab CI有三个默认阶段:构建(build),测试(test)和部署(deploy)。要指定作业运行的阶段,只需在CI中添加另一行:stages: - build

image: microsoft/dotnet:latest

stages:
    - build

build:
    stage: build
    script:
      - dotnet build
    artifacts:
      paths:
        - bin/

将阶段(stages)应用于不同工作(job)的最大好处是同一阶段(stage)的每个工作(job)都是并行构建的。因此,如果项目在部署之前需要多个测试,你可以同时运行所有测试,没有必要等待一个测试完成再进行另一个测试。

image: microsoft/dotnet:latest
stages:
    - build
    - test
build:
    stage: build
    script:
      - dotnet build
    artifacts:
      paths:
        - bin/
    only:
      - master
      
test1:
    stage: test
    script:
      - dotnet build
    artifacts:
      paths:
        - feature1/
    only:
      - feature1
      
test2:
    stage: test
    script:
      - dotnet build
    artifacts:
      paths:
        - feature2/
    only:
      - feature2
      
test3:
    stage: test
    script:
      - dotnet build
    artifacts:
      paths:
        - feature3/
    only:
      - feature3

在本例中,test1test2test3三个job都在同一个stagetest中,因此可以同步并行执行,即同步并行构建3个对应的分支feature1feature2feature3.

分支策略

如果使用GitLab作为版本控制平台,你将拥有分支策略来管理项目。这意味着,你的项目中将有其他分支,但如果你只需要推送到默认分支(通常master)以部署到您的网站。为此,我们需要在CI中添加另一行,告诉Runner只执行在分支上调用的作业:only: - master

image: microsoft/dotnet:latest
stages:
    - build
build:
    stage: build
    script:
      - dotnet build
    artifacts:
      paths:
        - bin/
    only:
      - master

假设你希望能够在将站点部署到生产环境之前测试脚本并检查构建的项目。那么就需要完全按照脚本在推送时执行的操作运行测试master。这很简单,我们的另一个任务可通过添加job来实现,告诉它测试每个除了master以外的分支,添加一行:stages: - build

本例中,我们添加了一个名为testjob,构建master分支以外的所有其他分支

image: microsoft/dotnet:latest

stages:
    - build
    - test

build:
    stage: build
    script:
      - dotnet build
    artifacts:
      paths:
        - bin/
    only:
      - master

test:
    stage: test
    script: 
        - dotnet test
    except:
      - master

before_script 脚本执行前的操作

要避免在不同的job中多次运行相同的脚本,可以添加before_script参数,在该参数中指定要为每个job都统一运行的命令。在我们的示例中,显示Python版本、通过pip命令安装virtualenv包等操作,都将会在test和run中首先执行,我们也无需在每个job中重复它。

image: python:latest

before_script:
   # 以下代码为两个job:test和run共同执行
   - python -V  # 显示Python版本以供调试
   - pip install virtualenv
   - virtualenv venv
   - source venv/bin/activate

test:
  script:
    - python fibonacci.py test

run:
  artifacts:
    paths:
       - bin/
  script:
    - python fibonacci.py run
    - echo $VERSION

Cache 缓存依赖项

如果要缓存项目依赖项的安装文件,为了更快地构建,可以使用该参数cache。对于此示例,我们将在pip安装运行时将pip依赖项缓存在.cache/pip目录中,同时,在virtualenv venv命令运行时,将virtualenv执行项缓存在venv/目录中。

image: python:latest

cache:
  paths:
    - .cache/pip
    - venv/

before_script:
   # 以下代码为两个job:test和run共同执行
   - python -V  # 显示Python版本以供调试
   - pip install virtualenv
   - virtualenv venv
   - source venv/bin/activate

test:
  script:
    - python fibonacci.py test

run:
  artifacts:
    paths:
       - bin/
  script:
    - python fibonacci.py run
    - echo $VERSION

tag 为项目指定执行CI/CD任务的Runner

当注册一个runner后,它的默认行为是只能挑选具有指定标签(tag)的工作。

注意:更改Runner设置需要维护者(maintainer)权限。

要使Runner执行无标签的作业:

  1. 访问项目的设置> CI / CD> Runners
  2. 找到要执行无标签的作业的Runner,并确保它已启用;
  3. 单击铅笔按钮;
  4. 选中Run untagged jobs选项;
  5. 单击“保存更改”按钮以使更改生效。

注意:当不允许选择未标记的作业时,Runner标签列表不能为空。

在.gitlab-ci.yml文件中可以为项目的特定job指定特定的Runner以执行任务,只需使用如下代码,tags: - tag1 - tag2 - tag3

image: python:latest

test:
  tags:
    - python
    - web
  script:
    - python fibonacci.py test

在本例中,通过tags标签指定了具有pythonweb标签的runners运行本job。需特别注意,在tags参数中指定的tag名称必须在注册的runner标签中出现。如下图红框中所示,在Runners管理界面可以找到具有pythonweb标签的runners。
Annotation 2019-07-22 122529.png

.gitlab-ci.yml配置举例

C/C++

核心编译和运行语句如下:
对于C++程序,采用g++编译,

  script:
    - gcc main.c -o main #编译并输出main文件
    - ./main  #在当前目录下执行main文件,输出显示结果

对于C语言程序,采用gcc编译,

  script:
    - g++ main.cpp -o main #编译并输出main文件
    - ./main  #在当前目录下执行main文件,输出显示结果

下为完整的C++程序示例.gitlab-ci.yml配置模板

image: gcc

stages:
    - build
    - run


build:
  stage: build
  script:
    - g++ main.cpp -o main

run:
  stage: run
  artifacts:
    paths:
      - ./   #将执行的当前目录下的所有文件当作产物传回
  script:
    - g++ main.cpp -o main
    - ./main

C#和dotNet Core

核心编译和运行语句:script: - dotnet build
此语句只能测试程序是否有语法错误,是否能够通过编译,但无法输出显示运行结果。

image: microsoft/dotnet:latest

stages:
    - build
    - test

build:
    stage: build
    script:
        - dotnet build
    artifacts:
      paths:
        - bin/

test:
    stage: test
    script: 
        - dotnet test

Python

核心编译和运行语句:script: - python main.py myPythonProgram

image: python:latest

stages:
  - test
  - run

variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

cache:
  paths:
    - .cache/pip
    - venv/

before_script:
   - python -V  # Print out python version for debugging
   - pip install virtualenv
   - virtualenv venv
   - source venv/bin/activate

test:
  stage: test
  script:
    - python fibonacci.py test

coverage:
  # 本阶段用于统计Python项目的覆盖率
  stage: test
  script:
    - pip install coverage
    - coverage run fibonacci.py
    - coverage report -m #显示覆盖率报告
    - coverage html -d report #保存覆盖率报告到HTML
  artifacts:
    paths:
       - ./report/ #覆盖率报告存放在report文件夹中


run:
  stage: run
  script:
    - python fibonacci.py run

LaTeX

核心编译和运行语句:script: - xetex maththesis.dtx

image: blang/latex

build:
  tags:
    - LaTeX
  script:
    - xetex maththesis.dtx  #根据实际情况选择用哪种方式编译
    - xelatex maththesis.dtx
    - xelatex maththesis.tex
    - xetex maththesis.tex
  artifacts:
    paths:
      - ./maththesis.pdf  #返回生成的pdf文件
Last modification:September 20th, 2019 at 02:06 pm