gitlab网站使用
- 1. 注册
- 2. 提交issue
- 3. 提交合并请求
- 4. code review
- 5. gitlab-runner
- 5.1 注册
- 5.2
.gitlab-ci.yml
配置 ~ image和services ~ before_script ~ after_script ~ stages ~ variables ~ cache ~ 缓存key ~ Jobs ~ script ~ stage ~ only and except ~ Job variables ~ tags ~ allow_failure ~ when ~ Manual actions ~ enviroment ~ environment:name ~ environment:url ~ environment:on_stop ~ environment:action ~ dynamic environment ~ artifacts ~ artifacts:name ~ artifacts:when ~ artifacts:expire_in ~ dependencies ~ before_script 和 after_script ~ coverage ~ Git Strategy ~ Git Checout ~ Git Submodule Strategy ~ Job stages attempts ~ Shallow cloning ~ Hidden keys ~ Special YAML features ~ Anchors ~ Triggers ~ pages ~ Validate the .gitlab-ci.yml ~ Skipping jobs - Code Review
- 1 什么是Code Review
- 2 为什么要进行Code Review
- 3 Code Review的内容
- 4 Code Review方法及工具
- 5 Code Review 的几点实用性建议
- 6 GitLab Code Review 示例
- 7 IDE Merge Request 插件使用介绍
1. 注册
2. 提交issue
3. 提交合并请求
4. code review
5. gitlab-runner
安装方式参考 01_pre-require.md [第10节]
# 将/bin/sh 链接到bash
sudo dpkg-reconfigure dash
# 选择No
ls -l /bin/sh
5.1 注册
sudo gitlab-runner register \
--non-interactive \
--url "http://git.aubo-robotics.cn:8001/" \
--registration-token "获取的 token " \
--executor "shell" \
--description "runner" \
--tag-list "qt,your-name" \
--run-untagged \
--locked="false"
需要按照步骤输入:
1. 输入gitlab的服务URL,这个使用的是http://git.aubo-robotics.cn:8001/
2. 输入gitlab-ci的Token,获取方式参考下图
3. 关于集成服务中对于这个runner的描述
4. 给这个gitlab-runner输入一个标记,这个tag非常重要,在后续的使用过程中需要使用这个tag来指定gitlab-runner
5. 是否运行在没有tag的build上面。在配置gitlab-ci的时候,会有很多job,每个job可以通过tags属性来选择runner。这里为true表示如果job没有配置tags,也执行
6. 是否锁定runner到当前项目
7. 选择执行器,gitlab-runner实现了很多执行器,可用在不同场景中运行构建,详情可见GitLab Runner Executors,这里选用Shell模式
刷新页面就可以看到新增的一个Runner:
如果没有可以尝试sudo gitlab-runner restart
# 解决gitlab-runner权限,设置从root用户启动
# http://www.fidding.me/article/111
sudo gitlab-runner install --working-directory /home/gitlab-runner --service gitlab-runner --user root
cat /etc/systemd/system/gitlab-runner.service
sudo gitlab-runner restart
# 查看启动情况
ps aux | grep gitlab-runner
5.2 .gitlab-ci.yml
配置
为了配合ci能够正常使用
变量名称 | 说明 | 典型值 |
---|---|---|
MIRRORS_SERVER | mirrors服务器的地址 | |
MIRRORS_SERVER_PORT | ssh端口号 | |
SSH_PRIVATE_KEY | ssh私钥(配对的公钥拷贝到mirrors服务器) | |
QMAKE_PATH | QMAKE的目录 | /home/user/Qt5.12.9/5.12.9/gcc_64/bin |
ci配置文件
stages:
- build
- test
- deploy
variables:
GIT_SUBMODULE_STRATEGY: recursive
before_script:
- whoami
- 'which fakeroot || (apt-get update -y && apt-get install fakeroot)'
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - # 添加ssh会话私钥,公钥已经拷贝到MIRRORS服务器,这样SCP操作就能成功了
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -p $MIRRORS_SERVER_PORT $MIRRORS_SERVER >> ~/.ssh/known_hosts # 将MIRROS服务器的公钥添加到gitlab-runner
- chmod 644 ~/.ssh/known_hosts
build_job:
stage: build
script:
- export PATH=$QMAKE_PATH:$PATH # 这一步已经放到.profile中了
- ./deploy.sh
artifacts:
paths:
- build/*.zip
tags:
- qt
- vm
test_depoy_job:
stage: deploy
dependencies:
- build_job
tags:
- vm
script:
- scp -P $MIRRORS_SERVER_PORT build/*.zip root@$MIRRORS_SERVER:$DEPLOY_PATH
when: manual
depoy_job:
stage: deploy
dependencies:
- build_job
tags:
- vm
script:
- scp -P $MIRRORS_SERVER_PORT build/*.zip root@$MIRRORS_SERVER:$DEPLOY_PATH
only:
- tags # 只有tags才进行此job
参考: .gitlab-ci.yml
语法说明
关键字 | 是否必须 | 描述 |
---|---|---|
image | 否 | 用于docker镜像,查看docker文档 |
services | 否 | 用于docker服务,查看docker文档 |
stages | 否 | 定义构建阶段 |
before_script | 否 | 定义在每个job之前运行的命令 |
after_script | 否 | 定义在每个job之后运行的命令 |
variable | 否 | 定义构建变量 |
cache | 否 | 定义一组文件列表,可在后续运行中使用 |
image和services
这两个关键字允许使用一个自定义的Docker镜像和一系列的服务,并且可以用于整个job周期。详细配置文档请查看a separate document。
before_script
before_script
用来定义所有job之前运行的命令,包括deploy(部署) jobs,但是在修复artifacts之后。它可以是一个数组或者是多行字符串。
after_script
GitLab 8.7 开始引入,并且要求Gitlab Runner v1.2
after_script
用来定义所有job之后运行的命令。它必须是一个数组或者是多行字符串
stages
stages
用来定义可以被job调用的stages。stages的规范允许有灵活的多级pipelines。
stages中的元素顺序决定了对应job的执行顺序:
1. 相同stage的job可以平行执行。 2.下一个stage的job会在前一个stage的job成功后开始执行。
接下仔细看看这个例子,它包含了3个stage:
stages:
- build
- test
- deploy
- 首先,所有
build
的jobs都是并行执行的。 - 所有
build
的jobs执行成功后,test
的jobs才会开始并行执行。 - 所有
test
的jobs执行成功,deploy
的jobs才会开始并行执行。 - 所有的
deploy
的jobs执行成功,commit才会标记为success
- 任何一个前置的jobs失败了,commit会标记为
failed
并且下一个stages的jobs都不会执行。
这有两个特殊的例子值得一提:
- 如果
.gitlab-ci.yml
中没有定义stages
,那么job's stages 会默认定义为build
,test
和deploy
。 - 如果一个job没有指定
stage
,那么这个任务会分配到test
stage。
variables
GitLab Runner V0.5.0. 开始引入
GItLab CI 允许在.gitlab-ci.yml
文件中添加变量,并在job环境中起作用。因为这些配置是存储在git仓库中,所以最好是存储项目的非敏感配置,例如:
variables:
DATABASE_URL:"postgres://postgres@postgres/my_database"
这些变量可以被后续的命令和脚本使用。服务容器也可以使用YAML中定义的变量,因此我们可以很好的调控服务容器。变量也可以定义成job level。
除了用户自定义的变量外,Runner也可以定义它自己的变量。CI_COMMIT_REG_NAME
就是一个很好的例子,它的值表示用于构建项目的分支或tag名称。除了在.gitlab-ci.yml
中设置变量外,还有可以通过GitLab
的界面上设置私有变量。
cache
Gitlab Runner v0.7.0 开始引入。
cache
用来指定需要在job之间缓存的文件或目录。只能使用该项目工作空间内的路径。
从GitLab 9.0开始,pipelines和job就默认开启了缓存
如果cache
定义在jobs的作用域之外,那么它就是全局缓存,所有jobs都可以使用该缓存。
缓存binaries
和.config
中的所有文件:
rspec:
script: test
cache:
paths:
- binaries/
- .config
缓存git中没有被跟踪的文件:
rspec:
script: test
cache:
untracked: true
缓存binaries
下没有被git跟踪的文件:
rspec:
script: test
cache:
untracked: true
paths: - binaries/
job中优先级高于全局的。下面这个rspec
job中将只会缓存binaries/
下的文件:
cache:
paths:
- my/files
rspec:
script: test
cache:
key: rspec
paths:
- binaries/
注意,缓存是在jobs之前进行共享的。如果你不同的jobs缓存不同的文件路径,必须设置不同的cache:key,否则缓存内容将被重写。
缓存只是尽力而为之,所以别期望缓存会一直存在。查看更多详细内容,请查阅GitLab Runner。
缓存key
GitLab Runner v1.0.0 开始引入。
key
指令允许我们定义缓存的作用域(亲和性),可以是所有jobs的单个缓存,也可以是每个job,也可以是每个分支或者是任何你认为合适的地方。
它也可以让你很好的调整缓存,允许你设置不同jobs的缓存,甚至是不同分支的缓存。
cache:key
可以使用任何的预定义变量。
默认key是默认设置的这个项目缓存,因此默认情况下,每个pipelines和jobs中可以共享一切,从GitLab 9.0开始。
配置示例
缓存每个job:
cache:
key: "$CI_JOB_NAME"
untracked: true
缓存每个分支:
cache:
key: "$CI_COMMIT_REF_NAME"
untracked: true
缓存每个job且每个分支:
cache:
key: "$CI_JOB_NAME/$CI_COMMIT_REF_NAME"
untracked: true
缓存每个分支且每个stage:
cache:
key: "$CI_JOB_STAGE/$CI_COMMIT_REF_NAME"
untracked: true
如果使用的Windows Batch(windows批处理)来跑脚本需要用%
替代$
:
cache:
key: "%CI_JOB_STAGE%/%CI_COMMIT_REF_NAME%"
untracked: true
Jobs
.gitlab-ci.yml
允许指定无限量jobs。每个jobs必须有一个唯一的名字,而且不能是上面提到的关键字。job由一列参数来定义jobs的行为。
job_name:
script:
- rake spec
- coverage
stage: test
only:
- master
except:
- develop
tags:
- ruby
- postgres
allow_failure: true
Keyword | Required | Description |
---|---|---|
script | yes | Runner执行的命令或脚本 |
image | no | 所使用的docker镜像,查阅使用docker镜像 |
services | no | 所使用的docker服务,查阅使用docker镜像 |
stage | no | 定义job stage(默认:test ) |
type | no | stage 的别名(已弃用) |
variables | no | 定义job级别的变量 |
only | no | 定义一列git分支,并为其创建job |
except | no | 定义一列git分支,不创建job |
tags | no | 定义一列tags,用来指定选择哪个Runner(同时Runner也要设置tags) |
allow_failure | no | 允许job失败。失败的job不影响commit状态 |
when | no | 定义何时开始job。可以是on_success ,on_failure ,always 或者manual |
dependencies | no | 定义job依赖关系,这样他们就可以互相传递artifacts |
cache | no | 定义应在后续运行之间缓存的文件列表 |
before_script | no | 重写一组在作业前执行的命令 |
after_script | no | 重写一组在作业后执行的命令 |
environment | no | 定义此作业完成部署的环境名称 |
coverage | no | 定义给定作业的代码覆盖率设置 |
script
script
是Runner执行的yaml脚本。举个例子:
job:
script: "bundle exec rspec"
该参数也可以用数组包含多个命令:
job:
script:
- uname -a
- bundle exec rspec
有时候,script
命令需要被单引号或者是双引号包裹起来。举个例子,当命令中包含冒号(:
)时,script需要被包在双引号中,这样YAML解析器才可以正确解析为一个字符串而不是一个键值对(key:value)。使用这些特殊字符的时候一定要注意::
,{
,}
,[
,]
,,
,&
,*
,#
,?
,|
,-
,<
,>
,=
,!
。
stage
stage
允许一组jobs进入不同的stages。jobs在相同的stage
时会parallel
同时进行。查阅stages
更多的用法请查看stages。
only and except
only
和except是两个参数用分支策略来限制jobs构建:
only
定义哪些分支和标签的git项目将会被job执行。except
定义哪些分支和标签的git项目将不会被job执行。
下面是refs策略的使用规则:
only
和except
可同时使用。如果only
和except
在一个job配置中同时存在,则以only
为准,跳过except
(从下面示例中得出)。only
和except
可以使用正则表达式。only
和except
允许使用特殊的关键字:branches
,tags
和triggers
。only
和except
允许使用指定仓库地址但不是forks的仓库(查看示例3)。
在下面这个例子中,job
将只会运行以issue-
开始的refs(分支),然而except中设置将被跳过。
job:
# use regexp
only:
- /^issue-.*$/
# use special keyword
except:
- branches
在下面这个例子中,job
将只会执行有tags的refs,或者通过API触发器明确地请求构建。
job:
# use special keywords
only:
- tags
- triggers
仓库路径只能用于父级仓库执行jobs,而不是forks:
job:
only:
- branches@gitlab-org/gitlab-ce
except:
- master@gitlab-org/gitlab-ce
上面这个例子将会为所有的分支执行job
,但master
分支除外。
Job variables
在job中是可以使用关键字variables
来定义job变量。它的运行原理跟global-level是一样的,但是它允许设置特殊的job变量。
当设置了job级别的关键字variables
,它会覆盖全局YAML和预定义中的job变量。想要关闭全局变量可以在job中设置一个空数组:
job_name:
variables: []
Job变量的优先级关系可查看variables文档说明。
tags
tags
可以从允许运行此项目的所有Runners中选择特定的Runners来执行jobs。
在注册Runner的过程中,我们可以设置Runner的标签,比如ruby
,postgres
,development
。
tags
可通过tags来指定特殊的Runners来运行jobs:
job:
tags:
- ruby
- postgres
上面这个示例中,需要确保构建此job
的Runner必须定义了ruby
和postgres
这两个tags。
allow_failure
allow_failure
可以用于当你想设置一个job失败的之后并不影响后续的CI组件的时候。失败的jobs不会影响到commit状态。
当开启了允许job失败,所有的intents和purposes里的pipeline都是成功/绿色,但是也会有一个"CI build passed with warnings"信息显示在merge request或commit或job page。这被允许失败的作业使用,但是如果失败表示其他地方应采取其他(手动)步骤。
下面的这个例子中,job1
和job2
将会并列进行,如果job1
失败了,它也不会影响进行中的下一个stage,因为这里有设置了allow_failure: true
。
job1:
stage: test
script:
- execute_script_that_will_fail
allow_failure: true
job2:
stage: test
script:
- execute_script_that_will_succeed
job3:
stage: deploy
script:
- deploy_to_staging
when
when
is used to implement jobs that are run in case of failure or despite the failure.
when
可以设置以下值:
on_success
- 只有前面stages的所有工作成功时才执行。 这是默认值。on_failure
- 当前面stages中任意一个jobs失败后执行。always
- 无论前面stages中jobs状态如何都执行。manual
- 手动执行(GitLab8.10增加)。更多请查看手动操作。
举个例子:
stages:
- build
- cleanup_build
- test
- deploy
- cleanup
build_job:
stage: build
script:
- make build
cleanup_build_job:
stage: cleanup_build
script:
- cleanup build when failed
when: on_failure
test_job:
stage: test
script:
- make test
deploy_job:
stage: deploy
script:
- make deploy
when: manual
cleanup_job:
stage: cleanup
script:
- cleanup after jobs
when: always
脚本说明:
- 只有当
build_job
失败的时候才会执行`cleanup_build_job
。` 不管前一个job执行失败还是成功都会执行``cleanup_job
。- 可以从GitLab界面中手动执行
deploy_jobs
。
Manual actions
GitLab 8.10 开始引入手动执行。GitLab 9.0 开始引入手动停止。GitLab 9.2 开始引入保护手动操作。
手动操作指令是不自动执行的特殊类型的job;它们必须要人为启动。手动操作指令可以从pipeline,build,environment和deployment视图中启动。
部署到生产环境是手动操作指令的一个很好示例。
了解更多请查看environments documentation。
手动操作指令可以是可选的或阻塞。在定义了手动执行的那个stage中,手动操作指令将会停止pipline中的自动执行指令。当有人通过点击play按钮来执行需要手动执行的job时,可以来恢复pipeline的执行。
当pipeline被阻塞时,即使是pipeline是成功状态也不会merge。被阻塞的pipelines也有一个特殊的状态,叫manual
。
手动操作指令默认是不阻塞的。如果你想要手动操作指令产生阻塞,首先需要在job的配置文件.gitlab-ci.yml
中添加allow_failure:false
。
可选的手动操作指令默认设置allow_failure:true
。
可选动作的状态不影响整个pipeline的状态。
手动操作指令被认为是写操作,所以当前用户触发操作时,必须拥有操作保护分支的权限。换句话说,为了触发一个手动操作指令到pipeline中正在运行的指定分支,当前用户必须拥有推送到这分支的权限。
enviroment
注意:
- GitLab 8.9 开始引入。
- 更多关于environment说明或者示例可以查看 &####&35&####&。
environment
用于定义job部署到特殊的环境中。如果指定了environment
,并且没有该名称下的环境,则会自动创建新环境。
在最简单的格式中,环境关键字可以定义为:
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production
在上面这个例子中,deploy to profuction
job将会执行部署到production
环境的操作。
environment:name
注意
- GitLab 8.11 开始引入。
- 在GitLab8.11之前,环境名称定义为
environment:production
。现在推荐的做法是定义为name
关键字。
environment
名称可以包含:
- 英文字母(
letters
) - 数字(
digits
) - 空格(
spaces
) -
_
/
$
{
}
常用的名称有qa
,staging
,和production
,当然你可以在你的工作流中使用任意名字。
除了在environment
关键字右边紧跟name定义方法外,也是可以为环境名称单独设定一个值。例如,用name
关键字在environment
下面设置:
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production
environment:url
注意:
- GitLab 8.11 开始引用。
- 在GitLab 8.11之前,URL只能在GitLab's UI中添加。现在推荐的定义方法是在
.gitlab-ci.yml
。
这是设置一个可选值,它会显示在按钮中,点击它可以带你到设置的URL页面。
在下面这个例子中,如果job都成功完成了,在environment/deployments页面中将会创建一个合并请求的按钮,它将指向https://prod.example.com
。
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production
url: https:*//prod.example.com*
environment:on_stop
注意:
- GitLab 8.13中开始&####&39&####&。
- 从GitLab 8.14开始,当在environment中定义了一个stop操作,GitLab将会在相关联的分支本删除时自动触发一个stop操作。
关闭(停止)environments可以通过在environment
下定义关键字on_stop
来实现。它定义了一个不同的job,用于关闭environment。
请查看environment:action
模块中例子。
environment:action
Gitlab 8.13 开始&####&39&####&。
action
和on_stop
联合使用,定义在job中,用来关闭environment。
举个例子:
review_app:
stage: deploy
script: make deploy-app
environment:
name: review
on_stop: stop_review_app
stop_review_app:
stage: deploy
script: make delete-app
when: manual
environment:
name: review
action: stop
上面这个例子中,我们定义了review_app
job来部署到review
环境中,同时我们也定义了一个新stop_review_app
job在on_stop
中。一旦review_app
job执行完成并且成功,它将触发定义在when
中的stop_review_app
job。在这种情况下,我们设置为manual
,需要通过GitLab's web界面来允许manual action。
stop_review_app
job需要定义下面这些关键字:
when
- 说明environment:name
environment:action
stage
需要和review_app
相同,以便分支删除被删除的时候自动执行停止。
dynamic environment
注意:
- GitLab 8.12开始引入,并且要求GitLab Runner 1.6 。
- GitLab 8.15开始引入
$CI_ENVIRONMENT_SLUG
。
environment
也可以是代表配置项,其中包含name
和url
。这些参数可以使用任何的CI variables(包括预定义、安全变量和.gitlab-ci.yml
中的变量)。
举个例子:
deploy as review app:
stage: deploy
script: make deploy
environment:
name: review/$CI_COMMIT_REF_NAME
url: https:*//$CI_ENVIRONMENT_SLUG.example.com/*
当$CI_COMMIT_REF_NAME
被Runner设置为environment variable时,deply as review app
job将会被指定部署到动态创建revuew/$CI_COMMIT_REF_NAME
的环境中。$CI_ENVIRONMENT_SLUG
变量是基于环境名称的,最终组合成完整的URLs。在这种情况下,如果deploy as review app
job是运行在名称为pow
的分支下,那么可以通过URLhttps"//review-pw.example.com/
来访问这个环境。
这当然意味着托管应用程序的底层服务器已经正确配置。
常见的做法是为分支创建动态环境,并讲它们作为Review Apps。可以通过https://gitlab.com/gitlab-examples/review-apps-nginx/上查看使用Review Apps的简单示例。
artifacts
注意:
- 非Windows平台从GitLab Runner v0.7.0中引入。
- Windows平台从GitLab Runner V1.0.0中引入。
- 在GItLab 9.2之前,在artifacts之后存储缓存。
- 在GItLab 9.2之后,在artifacts之前存储缓存。
- 目前并不是所有的executors都支持。
- 默认情况下,job artifacts 只正对成功的jobs收集。
artifacts
用于指定成功后应附加到job的文件和目录的列表。只能使用项目工作间内的文件或目录路径。如果想要在不通的job之间传递artifacts,请查阅依赖关系。以下是一些例子:
发送binaries
和.config
中的所有文件:
artifacts:
paths:
- binaries/
- .config
发送所有没有被Git跟踪的文件:
artifacts:
untracked: true
发送没有被Git跟踪和binaries
中的所有文件:
artifacts:
untracked: true
paths:
- binaries/
定义一个空的dependencies可以禁用artifact传递:
job:
stage: build
script: make build
dependencies: []
有时候只需要为标签为releases创建artifacts,以避免将临时构建的artifacts传递到生产服务器中。
只为tags创建artifacts(default-job
将不会创建artifacts):
default-job:
script:
- mvn test -U
except:
- tags
release-job:
script:
- mvn package -U
artifacts:
paths: - target/*.war
only: - tags
在job成功完成后artifacts将会发送到GitLab中,同时也会在GitLab UI中提供下载。
artifacts:name
GitLab 8.6 和 Runner v1.1.0 引入。
name
允许定义创建的artifacts存档的名称。这样一来,我们可以为每个存档提供一个唯一的名称,当需要从GitLab中下载是才不会混乱。artifacts:name
可以使用任何的预定义变量(predefined variables)。它的默认名称为artifacts
,当下载是就变成了artifacts.zip
。
配置示例
通过使用当前job的名字作为存档名称:
job:
artifacts:
name: "$CI_JOB_NAME"
使用当前分支名称或者是tag作为存到名称,只存档没有被Git跟踪的文件:
job:
artifacts:
name: "$CI_COMMIT_REF_NAME"
untracked: true
使用当前job名称和当前分支名称或者是tag作为存档名称,只存档没有被Git跟踪的文件:
job:
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
untracked: true
使用当前stage和分支名称作为存档名称:
job:
artifacts:
name: "${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}"
untracked: true
如果是使用Windows批处理来运行yaml脚本,需要用%
替换$
:
job:
artifacts:
name: "%CI_JOB_STAGE%_%CI_COMMIT_REF_NAME%"
untracked: true
artifacts:when
GitLab 8.9和GitLab Runner v1.3.0 引入。
在job失败的时候,artifacts:when
用来上传artifacts或者忽略失败。
artifacts:when
可以设置一下值:
on_success
- 当job成功的时候上传artifacts。默认值。on_failure
- 当job失败的时候上传artifacts。always
- 不论job失败还是成功都上传artifacts。
示例配置
只在job失败的时候上传artifacts。
job:
artifacts:
when: on_failure
artifacts:expire_in
GitLab 8.9 和 GitLab Runner v1.3.0 引入。
artifacts:expire_in
用于过期后删除邮件上传的artifacts。默认情况下,artifacts都是在GitLab中永久保存。expire_in
允许设置设置artifacts的存储时间,从它们被上传存储到GitLab开始计算。
可以通过job页面的Keep来修改有效期。
过期后,artifacts会被通过一个默认每小时执行一次的定时job删除,所以在过期后无法访问artifacts。
expire_in
是一个时间区间。下面可设置的值:
- '3 mins 4 sec'
- '2 hrs 20 min'
- '2h20min'
- '6 mos 1 day'
- '47 yrs 6 mos and 4d'
- '3 weeks and 2 days'
示例配置
设置artifacts的有效期为一个星期:
job:
artifacts:
expire_in: 1 week
dependencies
GitLab 8.6 和 GitLab RUnner v1.1.1引入。
这个功能应该与artifacts
一起使用,并允许定义在不同jobs之间传递artifacts。
注意:所有之前的stages都是默认设置通过。
如果要使用此功能,应该在上下文的job中定义dependencies
,并且列出之前都已经通过的jobs和可下载的artifacts。你只能在当前执行的stages前定义jobs。你如果在当前stages或者后续的stages中定义了jobs,它将会报错。可以通过定义一个空数组是当前job跳过下载artifacts。
在接下来的例子中,我们定义两个带artifacts的jobs,build:osx
和build:linux
。当test:osx
开始执行的时候,build:osx
的artifacts就会开始下载并且会在build的stages下执行。同样的会发生在test:linux
,从build:linux
中下载artifacts。
因为stages的优先级关系,deploy
job将会下载之前jobs的所有artifacts:
build:osx:
stage: build
script: make
build:osx
artifacts:
paths:
- binaries/ build:linux:
stage: build
script: make
build:linux
artifacts:
paths: - binaries/
test:osx:
stage: test
script: make
test:osx
dependencies: - build:osx
test:linux:
stage: test
script: make
test:linux
dependencies:
- build:linux
deploy:
stage: deploy
script: make deploy
before_script 和 after_script
它可能会覆盖全局定义的before_script
和after_script
:
before_script:
- global before script
job:
before_script:
- execute this instead of global before script
script:
- my command
after_script:
- execute this after my script
coverage
注意:
GitLab 8.17 &####&60&####&。
coverage
允许你配置代码覆盖率将会从该job中提取输出。
在这里正则表达式是唯一有效的值。因此,字符串的前后必须使用/
包含来表明一个正确的正则表达式规则。特殊字符串需要转义。
一个简单的例子:
job1:
coverage: '/Code coverage: \d+\.\d+/'
Git Strategy
GitLab 8.9中以试验性功能引入。将来的版本中可能改变或完全移除。
GIT_STRATEGY
要求GitLab Runner v1.7+。
你可以通过设置GIT_STRATEGY
用于获取最新的代码,可以再全局variables
或者是在单个job的variables
模块中设置。如果没有设置,将从项目中使用默认值。
可以设置的值有:clone
,fetch
,和none
。
clone
是最慢的选项。它会从头开始克隆整个仓库,包含每一个job,以确保项目工作区是最原始的。
variables:
GIT_STRATEGY: clone
当它重新使用项目工作区是,fetch
是更快(如果不存在则返回克隆)。git clean
用于撤销上一个job做的任何改变,git fetch
用于获取上一个job到现在的的commit。
variables:
GIT_STRATEGY: fetch
none
也是重新使用项目工作区,但是它会跳过所有的Git操作(包括GitLab Runner前的克隆脚本,如果存在的话)。它主要用在操作job的artifacts(例如:deploy
)。Git数据仓库肯定是存在的,但是他肯定不是最新的,所以你只能依赖于从项目工作区的缓存或者是artifacts带来的文件。
variables:
GIT_STRATEGY: none
Git Checout
GitLab Runner 9.3 引入。
当GIT_STRATEGY
设置为clone
或fetch
时,可以使用GIT_CHECKOUT
变量来指定是否应该运行git checkout
。如果没有指定,它默认为true。就像GIT_STRATEGY
一样,它可以设置在全局variables
或者是单个job的variables
中设置。
如果设置为false
,Runner就会:
fetch
- 更新仓库并在当前版本中保留工作副本,clone
- 克隆仓库并在默认分支中保留工作副本。
Having this setting set to true
will mean that for both clone
and fetch
strategies the Runner will checkout the working copy to a revision related to the CI pipeline:
【如果设置这个为true
将意味着clone
和fetch
策略都会让Runner执行项目工作区更新到最新:】
variables:
GIT_STRATEGY: clone
GIT_CHECKOUT:
falsescript:
- git checkout master
- git merge $CI_BUILD_REF_NAME
Git Submodule Strategy
需要GitLab Runner v1.10+。
GIT_SUBMODULE_STRATEGY
变量用于在构建之前拉取代码时,Git子模块是否或者如何被引入。就像GIT_STRATEGY
一样,它可在全局variables
或者是单个job的variables
模块中设置。
它的可用值有:none
,normal
和recursive
:
none
意味着在拉取项目代码时,子模块将不会被引入。这个是默认值,与v1.10之前相同的。normal
意味着在只有顶级子模块会被引入。它相当于:
git submodule sync git submodule update --init
recursive
意味着所有的子模块(包括子模块的子模块)都会被引入,他相当于:
git submodule sync --recursive
git submodule update --init --recursive
注意:如果想要此功能正常工作,子模块必须配置(在.gitmodules
)下面中任意一个:
- 可访问的公共仓库http(s)地址,
- 在同一个GitLab服务器上有一个可访问到另外的仓库的真实地址。更多查看Git 子模块文档。
Job stages attempts
GitLab引入,要求GItLab Runner v1.9+。
正在执行的job将会按照你设置尝试次数依次执行下面的stages:
变量 | 描述 |
---|---|
GET_SOURCES_ATTEMPTS | 获取job源的尝试次数 |
ARTIFACT_DOWNLOAD_ATTEMPTS | 下载artifacts的尝试次数 |
RESTORE_CACHE_ATTEMPTS | 重建缓存的尝试次数 |
默认是一次尝试。
例如:
variables:
GET_SOURCES_ATTEMPTS: 3
你可以在全局variables
模块中设置,也可以在单个job的variables
模块中设置。
Shallow cloning
GitLab 8.9 以实验性功能引入。在将来的版本中有可能改变或者完全移除。
你可以通过GIT_DEPTH
来指定抓取或克隆的深度。它可浅层的克隆仓库,这可以显著加速具有大量提交和旧的大型二进制文件的仓库的克隆。这个设置的值会传递给git fetch
和git clone
。
注意:如果设置depth=1,并且有一个jobs队列或者是重试jobs,则jobs可能会失败。
由于Git抓取和克隆是基于一个REF,例如分支的名称,所以Runner不能指定克隆一个commit SHA。如果队列中有多个jobs,或者您正在重试旧的job,则需要测试的提交应该在克隆的Git历史记录中存在。设置GIT_DEPTH
太小的值可能会导致无法运行哪些旧的commits。在job日志中可以查看unresolved reference
。你应该考虑设置GIT_DEPTH
为一个更大的值。
当GIT_DEPTH
只设置了部分存在的记录时,哪些依赖于git describe
的jobs也许不能正确的工作。
只抓取或克隆最后的3次commits:
variables:
GIT_DEPTH: "3"
Hidden keys
GitLab 8.6 和 GitLab Runner v1.1.1引入。
Key 是以.
开始的,GitLab CI 将不会处理它。你可以使用这个功能来忽略jobs,或者用Special YAML features 转换隐藏键为模版。
在下面这个例子中,.key_name
将会被忽略:
.key_name:
script:
- rake spec
Hidden keys 可以是像普通CI jobs一样的哈希值,但你也可以利用special YAMLfeatures来使用不同类型的结构。
Special YAML features
使用special YAML features 像anchors(&
),aliases(*
)和map merging(<<
),这将使您可以大大降低.gitlab-ci.yml
的复杂性。
查看更多YAML features。
Anchors
GitLab 8.6 和 GitLab Runner v1.1.1引入。
YAML有个方便的功能称为"锚",它可以让你轻松的在文档中复制内容。Anchors可用于复制/继承属性,并且是使用hidden keys来提供模版的完美示例。
下面这个例子使用了anchors和map merging。它将会创建两个jobs,test1
和test2
,该jobs将集成.job_template
的参数,每个job都自定义脚本:
.job_template: &job_definition # Hidden key that defines an anchor named 'job_definition'
image: ruby:2.1
services:
- postgres
- redis
test1:
<<: *job_definition # Merge the contents of the 'job_definition' alias
script:
- test1 project
test2:
<<: *job_definition # Merge the contents of the 'job_definition' alias
script:
- test2 project
&
在anchor的名称(job_definition
)前设置,<<
表示"merge the given hash into the current one",*
包括命名的anchor(job_definition
)。扩展版本如下:
.job_template:
image: ruby:2.1
services:
- postgres
- redis
test1:
image: ruby:2.1
services:
- postgres
- redis
script:
- test1 project
test2:
image: ruby:2.1
services:
- postgres
- redis
script:
- test2 project
让我们来看另外一个例子。这一次我们将用anchors来定义两个服务。两个服务会创建两个job,test:postgres
和test:mysql
,他们会在.job_template
中共享定义的script
指令,以及分别在.postgres_services
和.mysql_services
中定义的service
指令:
.job_template: &job_definition
script:
- test project
.postgres_services:
services: &postgres_definition
- postgres
- ruby
.mysql_services:
services: &mysql_definition
- mysql
- ruby
test:postgres:
<<: *job_definition
services: *postgres_definition
test:mysql:
<<: *job_definition
services: *mysql_definition
扩展版本如下:
.job_template:
script:
- test project
.postgres_services:
services:
- postgres
- ruby
.mysql_services:
services:
- mysql
- ruby
test:postgres:
script:
- test project
services:
- postgres
- ruby
test:mysql:
script:
- test project
services:
- mysql
- ruby
你可以看到hidden keys被方便的用作模版。
Triggers
Triggers 可用于强制使用API调用重建特定分支,tag或commits。
pages
pages是一个特殊的job,用于将静态的内容上传到GitLab,可用于为您的网站提供服务。它有特殊的语法,因此必须满足以下两个要求:
- 任何静态内容必须放在
public/
目录下 artifacts
必须定义在public/
目录下
下面的这个例子是将所有文件从项目根目录移动到public/
目录。.public
工作流是cp
,并且它不会循环复制public/
本身。
pages:
stage: deploy
script:
- mkdir .public
- cp -r * .public
- mv .public public
artifacts:
paths:
- public only:
- master
更多内容请查看GitLab Pages用户文档。
Validate the .gitlab-ci.yml
GitLab CI的每个实例都有一个名为Lint的嵌入式调试工具。 你可以在gitlab实例的/ci/lint
下找到该链接。
Skipping jobs
如果你的commit信息中包含[ci skip]
或者[skip ci]
,不论大小写,那么这个commit将会创建但是jobs也会跳过。
docker权限问题 将jenkins和gitlab-runenr用户添加到docker组里面
sudo gpasswd -a jenkins docker
sudo gpasswd -a gitlab-runner docker
Code Review
参考: https://www.zhihu.com/question/41089988
1 什么是Code Review
当一个程序员写完了一段代码后,由另外的程序员花时间来浏览阅读这些代码,并进行审阅。
Code Review 是以轮转的方式进行的,所以参与代码审阅的人有两种,分别是作者(author)以及评审者(reviewer)。当作者将写好的代码提交给评审者后,评审者对这次变动作出反馈,作者根据反馈修改代码,并重新提交,经过一次或多次往返后,评审者同意(approve)这次代码变动,允许代码进入仓库保存,Code Review 就完成了。
2 为什么要进行Code Review
很多团队或个人不做Code Review,根源还是不觉得这是一件有意义的事情,不觉得有什么好处。这个问题要从几个角度来看。
2.1 团队知识共享
一个开发团队中,水平有高有低,每个人侧重的领域也有不同。怎么让高水平的帮助新人成长?怎么让大家都对自己侧重领域之外的知识保持了解?怎么能有人离职后其他人能快速接手?这些都是团队管理者关心的问题。
而代码审查,就是一个很好的知识共享的方式。通过代码审查,高手可以直接指出新手代码中的问题,新手可以马上从高手的反馈中学习到好的实践,得到更快的成长;通过代码审查,前端也可以去学习后端的代码,做功能模块A的可以去了解功能模块B的。
可能有些高手觉得给新手代码审查浪费时间,自己也没收获。其实不然,新人成长了,就可以更多的帮高手分担繁重的任务;代码审查中花时间,就少一些帮新人填坑擦屁股的时间;良好的沟通能力、发现问题的能力、帮助其他人成长,都是技术转管理或技术上更上一层楼必不可少的能力,而通过代码审查可以有效的去练习这些方面的能力。
2.2 代码质量提高
现实中的项目总是人手缺进度紧,所以被压缩的往往就是自动化测试和代码审查,结果影响代码质量,欠下技术债务,最后还是要加倍偿还。
也有人寄希望于开发后的人工测试,然而对于代码质量来说,很多问题通过测试是测试不出来的,只能通过代码审查。比如说代码的可读性可维护性,比如代码的结构,比如一些特定条件才触发的死循环、逻辑算法错误,还有一些安全上的漏洞也更容易通过代码审查发现和预防。
也有人觉得自己水平高就不需要代码审查了。对于高手来说,让别人审查自己的代码,可以让其他人学习到好的实践;在让其他人审查的同时,在给别人说明自己代码的时候,也等于自己对自己的代码进行了一次审查。这其实就跟我们上学时做数学题一样,真正能拿高分的往往是那些做完后还会认真检查的。
2.3 团队规范
每个团队都有自己的代码规范,有自己的基于架构设计的开发规范,然而时间一长,就会发现代码中出现很多不遵守代码规范的情况,有很多绕过架构设计的代码。比如难以理解和不规范的命名,比如三层架构里面UI层绕过业务逻辑层直接调用数据访问层代码。
如果这些违反规范的代码被纠正的晚了,后面再要修改就成本很高了,而且团队的规范也会慢慢的形同虚设。 通过代码审查,就可以及时的去发现和纠正这些问题,保证团队规范的执行。
3 Code Review的内容
1.功能逻辑。这个是大前提,检查代码是否存在漏洞,知否合乎功能流程。有问题的话,会提出来,先让他自己去琢磨,看看能否自查出问题,实在不行,我再点明,让他想办法来改。我不会帮他们写代码,最多在他们无能为力的情况下,给一点思路。
2.命名规范。 类名、方法名、临时变量名等命名是否合乎规范。
3.代码的耦合度。高类聚低耦合,是代码质量的一大标准之一,我希望他们能在从事这个行业的开始,就养成这个习惯。
4.相关注释是否齐全,规范,正确。现在很多开源项目,尤其是github上面,绝大部分代码都没多少注释,只是在一些关键点上,写下注释。这会给很多新手造成干扰,会让他们误以为注释没多少作用。那些项目代码,因为他们的命名是很规范的,所以对于有几年工作经验的人来说,一看变量名,就知道代表什么意思,一看方法名,就知道这个方法是用来干嘛的,是同步方法还是异步。可是这点,对新手并不是很适用。我还是希望他们能养成写注释这个好习惯。 举个例子,第二点里面给了一个反面教材,上面的属性名t1,t2,t3,如果没有文档注释,你能分得清每个属性分别代表什么吗? 而有些特殊属性,用来区分一个实体的类别的(如下图),如果没有注释,那么当一个实体对象的RoleType值为2,你是否可以立即知道这个2代表什么意思?
5.代码的简洁度。这个其实就比较抽象了点,简洁度,你可以理解为:在功能完善的前提下,代码简洁有效,没有重复、冗余、无效的代码。这里举两个例子,一个正面,一个反面的。
正面的例子:一个协议解析库,里面会大量的用到大小端数据转换(网络字节和本地字节的互转),于是把这个转换的过程,独立成一个方法,需要使用的时候直接调用方法即可。
4 Code Review方法及工具
4.1 版本对比 / 文件改动
在“上古”时代,代码作者在开始 Code Review 前,还需要手动做一份变更列表(changelist),来告诉评审者这一次提交做了什么改动。得益于 Git 的诞生,今天的我们可以借助基于 Git 版本控制系统的平台,来更轻松无痛地开展代码审阅:
借助 Git 自动实现精细的文件改动,红色代表删减,绿色代表新增,支持行级评论,再也不用在不同工位间来回走动,直接在具体代码下进行交流。
4.2 资源关联
代码不是孤立的一串文本字符串,而是实现目标的其中一项资源,那么必然需要与其他资源相互组合才能掌握全局。落实到代码审阅中也是如此,放到具体的上下文环境里方能见微知著:
4.3 多人协同审阅
不同的人有不同的思考方式与见解,对同一段代码能从不同的角度出发考虑。尽可能的让不同的人 reivew 你的代码,不仅会有更多的人日后有能力维护你的代码,也是一个增加团队凝聚力的好方法。
5 Code Review 的几点实用性建议
1. 对事不对人。大家是同事,在一个团队工作和气很重要。不要在 Code Review 中说“你写的什么垃圾东西这种话”,你可以说“这个变量名不好理解,咱们换成巴拉巴拉是不是更好”。 2. 每个 Review 至少给一条正面评价。Code Review 本意是改善代码质量,增强团队成员之间的沟通,但是我一提交代码就有人说我写的垃圾,这很打击自信心啊,也不利于团队成员和平相处。代码有问题,指出问题是必须的,要实事求是,但是有的时候也需要给队友一点鼓励,例如简单的 或者“赞一个”我都很开心了。 3. 保证发布的代码和评审意见的可读性。大家都是程序员,你提交代码的时候,在符合团队风格的同时,把代码弄的好看点,如果你明确自己这个代码哪个地方不足,Highlight 出来让大家给意见。如果你是来 Review 代码的,把意见写的通顺点,评论有条理一些。对反引号 (```) 嵌入代码或三个反引号 (`````) 写代码块,这样看的舒服得多,效率也高。 4. 用工具进行基础问题的自动化检查。用 Tab 还是空格,用两个空格还是四个空格,函数后面怎么换行等基础问题检查,可以使用 eslint 和Rubocop 等类似的工具进行,团队成员应该把更多精力放在代码规范,代码性能优化等地方。 5. 全员参加 Code Review,并设定各部分负责人。扩大 Code Review 参与面,参与不是说一定去审核别人的代码,可以是代码被审核,也可以是看别人审核意见,这都是学习的过程。并且每部分设定负责人,该负责人对这部分代码质量负责,负责人需要是资深工程师。全员参与 Code Review 可以让团队成员更快的成长,新人在看大佬 Review 代码的过程就能学到很多。 6. 每个代码 PR 内容一定要少。Code Review 效果和质量与 PR 代码量成反比,你一下提交这么多代码,我今天还下不下班了? 我女朋友你帮我陪?每次 PR 代码量小一些,看起来速度快,又不至于失去耐心,这样才能达到Code Review 的效果,所以要经常进行Code Review,但是每个 PR 代码量要少。我建议要少于 300 行/PR。 7. 在写新代码之前,先 Review 掉需要评审的代码。你让我去 Review 一周前的代码?我还得把思维和项目进度切换到一周前?大家肯定不愿意,所以要形成规定,写新代码之前先把旧的 Review 掉,提交 PR 的时候也保证代码量小,这样 Review 起来不需要大块时间,改起来也快。不能因为Code Review大幅耽误项目进度,进度是全团队的事,不是某个人的事。 8. 如果你有更好的方案,尽管提出来。在Code Review 中经常会发现写的不好的地方,如果你有更好的方法,欢迎提出来!首先能改进这个 PR 的代码,其次能体现你的能力,团队应该定期对这种提出好的解决方案的同事进行奖励。 9. 不要在 review 中讨论需求,review 就是 review。不要在 Code Review 里搞别的,有需要就另安排时间进行,要明确Code Review 是完善代码,不是需求和功能讨论,始终要以代码质量为中心。
6 GitLab Code Review 示例
参考: https://ken.io/note/gitlab-code-review-tutorial
6.1 变更Feature分支
在线修改feature-ken-test
分支README.md
文件,为Merge Request提供基础
这里随意更新一行内容,然后Commit changes
即可。
6.2 创建Merge Request
菜单:Merge Requests,然后点击:New Merge Request
Source branch选择:feature-ken-test
Target branch选择:develop-test
然后:Compare branches and continue
操作项/填写项说明:
操作项/填写项 | ken.io 的说明 |
---|---|
Title | 标题,没有特殊要求保持默认即可 |
Description | 描述,需要将变更的需求描述清楚,最好附件Code Review要点 |
Assignee | 分配到的人,被分配到的人将会收到邮件通知,跟Merge权限没有必然关系,仍然是项目的Maintainers(Masters)角色拥有Merge权限 |
Milestone | 里程碑,如果没有可不选 |
Label | 标签,如果没有可不选 |
Approvers user | 批准人/审批人,必须为项目所在组成员,如果选择了批准人,那此次合并必须经由批准人批准 |
Approvers group | 批准人组,方便同时选择多个批准人 |
Approvals required | 最少批准个数,如果选了个3个批准人,Approvals required设置为1,那么只需要1个批准人批准即可 |
Source branch | 源分支,跟上一步骤选择一致,这里主要用于确认 |
Target branch | 目标分支,跟上一步骤选择一致,这里主要用于确认 |
Approvers选项暂不适用于GitLab-CE(社区版)的最新稳定版(11.1.4),期望后续可以支持。 这里填写好Description,选择Assignee,然后Submit merge request即可。
6.3 Merge Request 操作
Merge Request 创建之后就会转到该页面,被分配到的人(Assignee)会收到邮件提醒,如果需要多个人进行 Code Review,只要将该页面的链接发给其他项目成员即可。项目成员可以查看变更并评论,只不过按照之前的配置,只有Maintainers(Masters)角色的成员才有Merge的权限。
在Changes选项卡中,我们可以看到所有的变更。将光标移动到行号处会出现评论按钮,我们可以点击评论按钮发起评论,这个评论是对项目成员可见的,大家可在讨论区进行讨论。最终讨论发起者有权将讨论标记为已解决resolved
当所有的问题已解决之后(如果选择了审批人也需要审批通过),Maintainers(Masters)成员点击Merge完成合并即可。
Merge完成之后,可以选择Remove Source Branch等操作。
develop分支合并到release分支,以及elease分支合并到master是不需要经过Code Review的,直接Merge即可。这里就省略了。
7 IDE Merge Request 插件使用介绍
前面介绍了通过GitLab网页创建Merge Request并发起Code Review,但作为开发人员,还是结合IDE来使用会更顺手,GitLab提供了相关的api,只要我们创建响应的token,就可以供IDE插件来访问GitLab,以便使用IDE代替在网页上操作。
7.1 Gitlab Access Token
菜单:User Settings-> Access Tokens 进入Access Token添加页面
项 | 说明 |
---|---|
Name | 名称,根据自己喜好来即可 |
Expires at | 过期时间,最远可以选择到10年后,根据自己需要填写即可 |
Scopes | 范围,这里选择api就够用了 |
创建完成后,麻烦暂时保存token。因为一旦刷新或者重开页面,token就不可见了。