目录
cache 缓存
cache:paths
cache:key 缓存标记
cache:key:files 文件变化自动创建缓存
cache:key:prefix 组合生产 SHA 校验和
cache:policy 缓存策略
综合实例(一) 全局缓存
Pipeline 日志分析
Runner 缓存
综合实例(二)
artifacts 制品
artifacts:paths 制品创建
artifacts:expose_as 展示制品
artifacts:name 制品名称
artifacts:when 制品创建条件
artifacts:expire_in 制品保留时间
artifacts:reports
artifacts:reports:junit 单元测试报告
artifacts:reports:cobertura 覆盖率
maven 集成 cobertura 插件
dependencies
综合实例(三)
cache 缓存
用来指定需要在 job 之间缓存的文件或目录。只能使用该项目工作空间内的路径。不要使用缓存在阶段之间传递工件,因为缓存旨在存储编译项目所需的运行时依赖项。
如果在 job 范围之外定义了 cache
,则意味着它是全局设置,所有 job 都将使用该定义。如果未全局定义或未按 job 定义则禁用该功能。
cache:paths
使用 paths
指令选择要缓存的文件或目录,路径是相对于项目目录,不能直接链接到项目目录之外。
$CI_PROJECT_DIR
项目目录。
在 job build 中定义缓存,将会缓存 target 目录下的所有 .jar 文件。
build:
script: test
cache:
paths:
- target/*.jar
当在全局定义了 cache:paths 会被 job 中覆盖。以下实例将缓存 binaries 目录。
cache:
paths:
- my/files
build:
script: echo "hello"
cache:
key: build
paths:
- target/
由于缓存是在 job 之间共享的,如果不同的 job 使用不同的路径就出现了缓存覆盖的问题。如何让不同的 job 缓存不同的 cache 呢?可以设置不同的 cache:key
。
cache:key 缓存标记
为缓存做个标记,可以配置 job、分支为 key 来实现分支、作业特定的缓存。为不同 job 定义了不同的 cache:key
时, 会为每个 job 分配一个独立的 cache。cache:key 变量可以使用任何预定义变量,默认
default ,从 GitLab 9.0 开始,默认情况下所有内容都在管道和作业之间共享。
按照分支设置缓存:
cache:
key: ${CI_COMMIT_REF_SLUG}
cache:key:files 文件变化自动创建缓存
files:文件发生变化自动重新生成缓存(files 最多指定两个文件),提交的时候检查指定的文件。
根据指定的文件生成密钥计算 SHA 校验和,如果文件未改变值为 default。
cache:
key:
files:
- Gemfile.lock
- package.json
paths:
- vendor/ruby
- node_modules
cache:key:prefix 组合生产 SHA 校验和
prefix: 允许给定 prefix 的值与指定文件生成的秘钥组合。
在这里定义了全局的 cache,如果文件发生变化则值为 rspec-xxx111111111222222 ,未发生变化为 rspec-default。
cache:
key:
files:
- Gemfile.lock
prefix: ${CI_JOB_NAME}
paths:
- vendor/ruby
rspec:
script:
- bundle exec rspec
例如,添加 $CI_JOB_NAME
prefix
将使密钥看起来像: rspec-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5
,并且作业缓存在不同分支之间共享,如果分支更改了 Gemfile.lock
,则该分支将为 cache:key:files
具有新的 SHA 校验和. 将生成一个新的缓存密钥,并为该密钥创建一个新的缓存。如果 Gemfile.lock
未发生变化 ,则将前缀添加 default
,因此示例中的键为 rspec-default
。
cache:policy 缓存策略
默认:在执行开始时下载文件,并在结束时重新上传文件。称为 pull-push
缓存策略.
policy: pull
跳过下载步骤
policy: push
跳过上传步骤
stages:
- setup
- test
prepare:
stage: setup
cache:
key: gems
paths:
- vendor/bundle
script:
- bundle install --deployment
rspec:
stage: test
cache:
key: gems
paths:
- vendor/bundle
policy: pull
script:
- bundle exec rspec ...
综合实例(一) 全局缓存
before_script:
- echo "before-script!!"
variables:
DOMAIN: example.com
cache:
paths:
- target/
stages:
- build
- test
- deploy
build:
before_script:
- echo "before-script in job"
stage: build
tags:
- build
only:
- master
script:
- ls
- id
- mvn clean package -DskipTests
- ls target
- echo "$DOMAIN"
- false && true ; exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
- sleep 2;
after_script:
- echo "after script in job"
unittest:
stage: test
tags:
- build
only:
- master
script:
- echo "run test"
- echo 'test' >> target/a.txt
- ls target
retry:
max: 2
when:
- script_failure
deploy:
stage: deploy
tags:
- build
only:
- master
script:
- echo "run deploy"
- ls target
retry:
max: 2
when:
- script_failure
after_script:
- echo "after-script"
Pipeline 日志分析
build 作业运行时会对项目代码打包,然后生成 target 目录。作业结束创建缓存。
开始第二个作业 test,此时会把当前目录中的 target 目录删除掉(因为做了 git 对比)。
获取到第一个作业生成的缓存 target 目录。
开始第三个作业,同样先删除了 target 目录,然后获取了第二个作业的缓存。最后生成了当前的缓存。
Runner 缓存
在做本次实验的时候我先在本地 runner 上清除了项目的工作目录和历史缓存。
[root@run01 ~]# cd /home/gitlab-runner/builds/1Cxihk7-/0/demo/demo-maven-service/
[root@run01 demo-maven-service]# ls
Jenkinsfile README.md aaaaa jenkins pom.xml src target
[root@run01 demo-maven-service]# cd ..
[root@run01 demo]# ls
demo-maven-service demo-maven-service.tmp
[root@run01 demo]# rm -fr demo-maven-service
[root@run01 demo]# rm -fr demo-maven-service.tmp/
[root@run01 demo]# cd
[root@run01 ~]# cd /home/gitlab-runner/cache/
[root@run01 cache]# ls
demo
[root@run01 cache]# rm -rf *
项目代码默认不会删除,可以发现是第二次作业的缓存。(因为上面的例子中第三次作业并没有修改缓存内容)
[root@run01 cache]# cd /home/gitlab-runner/builds/1Cxihk7-/0/demo/demo-maven-service/
[root@run01 demo-maven-service]# ls
Jenkinsfile README.md aaaaa jenkins pom.xml src target
[root@run01 demo-maven-service]# cd ..
[root@run01 demo]# ls
demo-maven-service demo-maven-service.tmp
[root@run01 demo]# rm -fr *
[root@run01 demo]# ls
[root@run01 demo]# ls
demo-maven-service demo-maven-service.tmp
[root@run01 demo]# cd demo-maven-service
[root@run01 demo-maven-service]# ls
Jenkinsfile README.md aaaaa jenkins pom.xml src target
[root@run01 demo-maven-service]# cat target/a.txt
test
进入 runner 缓存目录中查看缓存。
[root@run01 ~]# cd /home/gitlab-runner/cache/demo/demo-maven-service/default/
[root@run01 default]# ls
cache.zip
[root@run01 default]# unzip cache.zip
Archive: cache.zip
creating: target/
inflating: target/a.txt
creating: target/classes/
creating: target/classes/com/
creating: target/classes/com/mycompany/
creating: target/classes/com/mycompany/app/
inflating: target/classes/com/mycompany/app/App.class
creating: target/maven-archiver/
inflating: target/maven-archiver/pom.properties
creating: target/maven-status/
creating: target/maven-status/maven-compiler-plugin/
creating: target/maven-status/maven-compiler-plugin/compile/
creating: target/maven-status/maven-compiler-plugin/compile/default-compile/
inflating: target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
inflating: target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
creating: target/maven-status/maven-compiler-plugin/testCompile/
creating: target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/
inflating: target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
inflating: target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
inflating: target/my-app-1.1-SNAPSHOT.jar
creating: target/test-classes/
creating: target/test-classes/com/
creating: target/test-classes/com/mycompany/
creating: target/test-classes/com/mycompany/app/
inflating: target/test-classes/com/mycompany/app/AppTest.class
[root@run01 default]# ls
cache.zip target
[root@run01 default]# cd target/
[root@run01 target]# ls
a.txt classes maven-archiver maven-status my-app-1.1-SNAPSHOT.jar test-classes
[root@run01 target]# cat a.txt
test
此时此刻再次运行流水线作业,第一个作业用的是上个作业最后生成的缓存。
进入 runner 缓存目录查看,cache.zip 时间已经发生的变化。
[root@run01 default]# ll
total 12
-rw------- 1 gitlab-runner gitlab-runner 9172 July 19 10:27 cache.zip
drwxrwxr-x 6 root root 127 July 19 10:05 target
结论:全局缓存生效于未在作业中定义缓存的所有作业,这种情况如果每个作业都对缓存目录做了更改,会出现缓存被覆盖的场景。
综合实例(二)
控制缓存策略:例如 build 阶段我们需要生成新的 target 目录内容,可以优化设置 job 运行时不下载缓存。
before_script:
- echo "before-script!!"
variables:
DOMAIN: example.com
cache:
paths:
- target/
stages:
- build
- test
- deploy
build:
before_script:
- echo "before-script in job"
stage: build
tags:
- build
only:
- master
script:
- ls
- id
- cat target/a.txt
- mvn clean package -DskipTests
- ls target
- echo "$DOMAIN"
- false && true ; exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
- sleep 2;
after_script:
- echo "after script in job"
cache:
policy: pull #不下载缓存
unittest:
stage: test
tags:
- build
only:
- master
script:
- echo "run test"
- echo 'test' >> target/a.txt
- ls target
- cat target/a.txt
retry:
max: 2
when:
- script_failure
deploy:
stage: deploy
tags:
- build
only:
- master
script:
- cat target/a.txt
- echo "run deploy"
- ls target
- echo "deploy" >> target/a.txt
retry:
max: 2
when:
- script_failure
after_script:
- echo "after-script"
artifacts 制品
用于指定在作业成功或者失败时应附加到作业的文件或目录的列表。作业完成后,工件将被发送到 GitLab,并可在 GitLab UI 中下载。
artifacts:paths 制品创建
路径是相对于项目目录的,不能直接链接到项目目录之外。
将制品设置为 target 目录:
artifacts:
paths:
- target/
禁用工件传递
job:
stage: build
script: make build
dependencies: []
您可能只想为标记发行版的创建构件,以避免用临时构建构件填充构建服务器存储。仅为标签创建工件( default-job
不会创建工件):
default-job:
script:
- mvn test -U
except:
- tags
release-job:
script:
- mvn package -U
artifacts:
paths:
- target/*.war
only:
- tags
artifacts:expose_as 展示制品
关键字 expose_as
可用于在合并请求 UI 中公开作业工件。
例如,要匹配单个文件:
test:
script:
- echo 1
artifacts:
expose_as: 'artifact 1'
paths:
- path/to/file.txt
使用此配置,GitLab 将在指向的相关合并请求中添加链接 file1.txt
。
制品浏览:
请注意以下几点:
-
每个合并请求最多可以公开 10 个作业工件。
-
如果指定了目录,那么如果目录中有多个文件,则该链接将指向指向作业工件浏览器。
-
如果开启 GitlabPages 可以对.html .htm .txt .json .log 扩展名单个文件工件渲染工件。
artifacts:name 制品名称
通过 name
指令定义所创建的工件存档的名称。可以为每个存档使用唯一的名称。 artifacts:name
变量可以使用任何预定义变量。默认名称是 artifacts
,下载 artifacts
改为artifacts.zip
。
使用当前作业的名称创建存档:
job:
artifacts:
name: "$CI_JOB_NAME"
paths:
- binaries/
使用内部分支或标记的名称(仅包括 binaries 目录)创建存档,:
job:
artifacts:
name: "$CI_COMMIT_REF_NAME"
paths:
- binaries/
使用当前作业的名称和当前分支或标记(仅包括二进制文件目录)创建存档 :
job:
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
paths:
- binaries/
要创建一个具有当前阶段名称和分支名称的存档 :
job:
artifacts:
name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME"
paths:
- binaries/
artifacts:when 制品创建条件
用于在作业失败时或尽管失败而上传工件。on_success 仅在作业成功时上载工件,这是默认值;on_failure 仅在作业失败时上载工件;always 上载工件,无论作业状态如何。
要仅在作业失败时上传工件:
job:
artifacts:
when: on_failure
artifacts:expire_in 制品保留时间
制品的有效期,从上传和存储到GitLab的时间开始算起。如果未定义过期时间,则默认为30天。
expire_in
的值以秒为单位的经过时间,除非提供了单位。可解析值的示例:
‘42’
‘3 mins 4 sec’
‘2 hrs 20 min’
‘2h20min’
‘6 mos 1 day’
‘47 yrs 6 mos and 4d’
‘3 weeks and 2 days’
一周后过期:
job:
artifacts:
expire_in: 1 week
artifacts:reports
用于从作业中收集测试报告,代码质量报告和安全报告。在 GitLab 的 UI 中显示这些报告。
注意:无论作业结果(成功或失败),都将收集测试报告。
artifacts:reports:junit 单元测试报告
收集 junit 单元测试报告,收集的 JUnit 报告将作为工件上传到 GitLab,并将自动显示在合并请求中。
build:
stage: build
tags:
- build
only:
- master
script:
- mvn test
- mvn cobertura:cobertura
- ls target
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
when: on_success
expose_as: 'artifact 1'
paths:
- target/*.jar
reports:
junit: target/surefire-reports/TEST-*.xml
注意:如果您使用的 JUnit 工具导出到多个XML文件,则可以在一个作业中指定多个测试报告路径,它们将被自动串联到一个文件中。使用文件名模式( junit: rspec-*.xml
),文件名数组( junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]
)或其组合( junit: [rspec.xml, test-results/TEST-*.xml]
)。
如果无法显示此页面,需要更改系统设置。此选项可能会加大资源占用,默认禁用了需要启用。
登录gitlab
su - git
$ gitlab-rails console
--------------------------------------------------------------------------------
GitLab: 12.9.0 (9a382ff2c82) FOSS
GitLab Shell: 12.0.0
PostgreSQL: 10.12
--------------------------------------------------------------------------------
Feature.enable(:junit_pipeline_view)Loading production environment (Rails 6.0.2)
irb(main):001:0>
irb(main):002:0>
irb(main):003:0> Feature.enable(:junit_pipeline_view)
=> true
irb(main):004:0>
artifacts:reports:cobertura 覆盖率
收集的 Cobertura 覆盖率报告将作为工件上传到 GitLab,并在合并请求中自动显示。
build:
stage: build
tags:
- build
only:
- master
script:
- mvn test
- mvn cobertura:cobertura
- ls target
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
when: on_success
expose_as: 'artifact 1'
paths:
- target/*.jar
reports:
junit: target/surefire-reports/TEST-*.xml
cobertura: target/site/cobertura/coverage.xml
$ gitlab-rails console
--------------------------------------------------------------------------------
GitLab: 12.9.0 (9a382ff2c82) FOSS
GitLab Shell: 12.0.0
PostgreSQL: 10.12
--------------------------------------------------------------------------------
Loading production environment (Rails 6.0.2)
irb(main):001:0>
irb(main):002:0>
irb(main):003:0> Feature.enable(:coverage_report_view)
=> true
maven 集成 cobertura 插件
<plugins>
<!-- cobertura plugin start -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
</configuration>
</plugin>
<!-- cobertura plugin end -->
</plugins>
执行 mvn cobertura:cobertura 运行测试并产生 Cobertura 覆盖率报告。
dependencies
定义要获取工件的作业列表,只能从当前阶段之前执行的阶段定义作业。定义一个空数组将跳过下载该作业的任何工件不会考虑先前作业的状态,因此,如果它失败或是未运行的手动作业,则不会发生错误。
如果设置为依赖项的作业的工件已过期或删除,那么依赖项作业将失败。
综合实例(三)
before_script:
- echo "before-script!!"
variables:
DOMAIN: example.com
cache:
paths:
- target/
stages:
- build
- test
- deploy
build:
before_script:
- echo "before-script in job"
stage: build
tags:
- build
only:
- master
script:
- ls
- id
- mvn test
- mvn cobertura:cobertura
- ls target
- echo "$DOMAIN"
- false && true ; exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
- sleep 2;
after_script:
- echo "after script in job"
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
when: on_success
#expose_as: 'artifact 1'
paths:
- target/*.jar
#- target/surefire-reports/TEST*.xml
reports:
junit: target/surefire-reports/TEST-*.xml
cobertura: target/site/cobertura/coverage.xml
coverage: '/Code coverage: \d+\.\d+/'
unittest:
dependencies:
- build
stage: test
tags:
- build
only:
- master
script:
- echo "run test"
- echo 'test' >> target/a.txt
- ls target
retry:
max: 2
when:
- script_failure
deploy:
stage: deploy
tags:
- build
only:
- master
script:
- echo "run deploy"
- ls target
retry:
max: 2
when:
- script_failure
after_script:
- echo "after-script"
上一篇文章:【基于 GitLab 的 CI/CD 实践】03、GitLab Pipeline 实践(上)_Stars.Sky的博客-CSDN博客
下一篇文章:【基于 GitLab 的 CI/CD 实践】05、GitLab Pipeline 实践(下)_Stars.Sky的博客-CSDN博客