在.gitlab-ci.yml中配置你的工作流
這篇文章描述了.gitlab-ci.yml
的用法准脂,.gitlab-ci.yml文件被Gitlab Runner用來(lái)管理你的jobs曹抬。
從7.12版本開(kāi)始娃循,Gitlab CI 用YAML文件(.gitlab-ci.yml
)來(lái)配置項(xiàng)目惰瓜。它被放置在你倉(cāng)庫(kù)的根目錄并且應(yīng)該包含YAML如何構(gòu)建你項(xiàng)目的定義叠聋。如果你先要Gitlab CI的快速介紹讯私,可以看下我們的快速快開(kāi)始指導(dǎo)
注意:如果你有鏡像倉(cāng)庫(kù)需要Gitlab去拉取柒爸,你可能需要開(kāi)啟pipeline triggering准浴,在你的項(xiàng)目中設(shè)置Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates.
Jobs
YAML文件定義了一些job,這些job限制了他們應(yīng)該被運(yùn)行的時(shí)間。你可以在文件的頂層中指定無(wú)限的job,他們可以隨意命名捎稚,并且至少包含一個(gè)script條目
job1:
script: "execute-script-for-job1"
job2:
script: "execute-script-for-job2"
上面的例子是CI/CD配置可以的最簡(jiǎn)單的配置乐横,有兩個(gè)分離的job,每一個(gè)job執(zhí)行不同的命令,當(dāng)然命令可以直接在倉(cāng)庫(kù)中執(zhí)行代碼(./configure; make;make install
)或者運(yùn)行腳本(test.sh
).
Job被Runner挑選出來(lái)今野,并且在Runner環(huán)境中執(zhí)行葡公,最重要的是每個(gè)Job相對(duì)與其他Job是獨(dú)立運(yùn)行的。
每個(gè)Job必須包含唯一的名字条霜,但是這里有一些保留的關(guān)鍵字不能被用作Job的名稱(chēng):
- image
- services
- stages
- types
- before_script
- after_script
- variables
- cache
一個(gè)job通過(guò)以下一些定義job行為的參數(shù)定義而成催什。
關(guān)鍵字 | 是否必須 | 描述 |
---|---|---|
script | yes | 定義Runner執(zhí)行的shell腳本 |
extends | no | 定義當(dāng)前job繼承配置的入口 |
image | no | 定義腳本鏡像,涵蓋在Docker鏡像使用 |
services | no | 使用docker services,涵蓋在使用Docker鏡像 |
stage | no | 定義job的stage(默認(rèn):test) |
type | no | stage的別名 |
variables | no | 在job層定義變量 |
only | no | 定義創(chuàng)建job的git refs的列表 |
except | no | 定義不創(chuàng)建job的git refs的列表 |
tags | no | 定義用來(lái)選擇Runner的tag列表 |
allow_failure | no | 允許job失敗宰睡,失敗的job無(wú)助于commit的狀態(tài) |
when | no | 定義何時(shí)運(yùn)行job可以是on_success ,on_failure ,always 或者manual
|
dependencies | no | 定義另外的job作為當(dāng)前job的依賴(lài)蒲凶,這樣你就可以在他們之間傳遞工件 |
artifacts | no | 定義job工件列表 |
cache | no | 定義應(yīng)該被緩存起來(lái)的東西,以便在下次run的時(shí)候使用 |
before_script | no | 定義在job之前執(zhí)行的命令列表 |
after_script | no | 定義在job之后執(zhí)行的命令列表 |
environment | no | 定義由該job完成發(fā)布的環(huán)境的名稱(chēng) |
converage | no | 定義該job代碼覆蓋率的設(shè)置 |
retry | no | 定義在失敗的情況下可以自動(dòng)重試多少次 |
parallel | no | 定義多少job實(shí)例可以同時(shí)運(yùn)行 |
extends
在Gitlab11.3中引入
extends定義繼承的job的名稱(chēng)拆内。他是使用YAML anchors的替代方案旋圆,它更加靈活,并且可讀性更強(qiáng):
.tests:
script: rake test
stage: test
only:
refs:
- branches
rspec:
extends: .tests
script: rake rspec
only:
variables:
- $RSPEC
在上面的例子中rspc
這個(gè)job繼承了.tests
這個(gè)模版job矛纹。GitLab將會(huì)根據(jù)keys執(zhí)行反向深度合并臂聋。Gitlab將會(huì):
- 遞歸合并rspec的內(nèi)容到.tests
- 不合并鍵的值
rspec job的結(jié)果如下:
rspec:
script: rake rspec
stage: test
only:
refs:
- branches
variables:
- $RSPEC
注意:
script: rake test
已經(jīng)被script:rake rspec
合并了光稼。
如果你想要包含rake test
,看看before_script-and-after_script.
.tests
在這個(gè)例子中是一個(gè)隱藏的key,但是它也可以繼承自正常的job.
extends
支持多層繼承或南,但是不建議超過(guò)三層的繼承。最多支持的嵌套層級(jí)是10層艾君。下面的例子有兩個(gè)層級(jí)的嵌套采够。
.tests:
only:
- pushes
.rspec:
extends: .tests
script: rake rspec
rspec 1:
variables:
RSPEC_SUITE: '1'
extends: .rspec
rspec 2:
variables:
RSPEC_SUITE: '2'
extends: .rspec
spinach:
extends: .tests
script: rake spinach
跨文件的extend
結(jié)合include一起使用
pages
pages
是一個(gè)特殊的job,它被用來(lái)上傳一些服務(wù)網(wǎng)站的靜態(tài)資源到GitLab.它有特殊的語(yǔ)法冰垄,必須滿(mǎn)足以下兩點(diǎn):
- 所有的靜態(tài)資源必須在
public/
目錄下 -
artifacts
的path地址必須被定義成public/
下面的例子簡(jiǎn)單的將所有文件從根目錄下移動(dòng)到public/
文件下蹬癌。使用.public
所以cp
命令不會(huì)無(wú)限循環(huán)的拷貝public/
到它自己目錄下
pages:
stage: deploy
script:
- mkdir .public
- cp -r * .public
- mv .public public
artifacts:
paths:
- public
only:
- master
詳情閱讀GitLab Pages user documentation.
image 和 services
該字段允許指定在job工作時(shí)間可用的自定義的Docker鏡像和services列表。此功能的介紹在單獨(dú)的文章中介紹虹茶。
before_script 和 after_script
注意:在GitLab8.7中引入逝薪,并且需要Runner V1.2
before_script
被用來(lái)定義一些需要在所有job之前執(zhí)行的命令,包括發(fā)布job,但是在artifacts恢復(fù)之后蝴罪。它可以是數(shù)組或者多行字符串董济。after_script
被用來(lái)定義一些在所有job運(yùn)行之后執(zhí)行的命令,包括失敗的那些要门。它必須是數(shù)組或者多行字符串虏肾。
before_script
和主 script
在一個(gè)上下文/容器中運(yùn)行廓啊。after_script
是分離運(yùn)行的,所以根據(jù)執(zhí)行程序的不同封豪,在工作樹(shù)之外的改變可能不可見(jiàn)谴轮。比如:在before_script
安裝軟件。
它可以覆蓋掉你在全局設(shè)置的before_script
和after_script
:
before_script:
- global before script
job:
before_script:
- execute this instead of global before script
script:
- my commandling
after_script:
- execute this after my script
stages
stages
被用來(lái)在全局定義可用的job.
指定的stages允許擁有靈活的多個(gè)stage的pipelines吹埠。節(jié)點(diǎn)定義的順序就是job執(zhí)行的順序:
- 在同一個(gè)stage中指定的job將會(huì)同時(shí)運(yùn)行第步。
- 下一個(gè)stage將會(huì)在上一個(gè)stage完全成功后運(yùn)行。
讓我們思考如下示例藻雌,它定義了三個(gè)stage:
stages:
- build
- test
- deploy
- 首先雌续,在
build
中的所有job將會(huì)同時(shí)運(yùn)行。 - 如果
build
中的所有job運(yùn)行成功胯杭,則test
中的所有job將會(huì)同時(shí)運(yùn)行 - 如果
build
中的所有job運(yùn)行成功驯杜,則deploy
中的job將會(huì)同時(shí)運(yùn)行。 - 如果
deploy
中的所有job運(yùn)行成功做个,則commit將會(huì)標(biāo)記為passed
. - 如果任何一個(gè)之前的job執(zhí)行失敗鸽心,則commit將會(huì)被標(biāo)記為失敗,并且之后stage中的所有job都不會(huì)執(zhí)行居暖。
這里還有兩個(gè)值得一提的邊緣例子:
- 如果
.gitlab-ci.yml
中沒(méi)有定義stages
顽频,這樣的話(huà)默認(rèn)情況下build
,test
,deploy
可以在job的stage中被使用。 - 如果job沒(méi)有指定
stage
,那么job將被分配test
stage.
stage
stage
定義每一個(gè)job依賴(lài)的在全局stages
中定義的stage
.它允許一組job定義在不同的stage中太闺,同一個(gè)stage
中的job同時(shí)執(zhí)行糯景。比如:
stages:
- build
- test
- deploy
job 1:
stage: build
script: make build dependencies
job 2:
stage: build
script: make build artifacts
job 3:
stage: test
script: make test
job 4:
stage: deploy
script: make deploy
types
Deprecated:
types
已經(jīng)被棄用了,并且可能會(huì)在未來(lái)的某個(gè)版本中移除省骂,用stages
代替
script
script
是job中唯一一個(gè)必須要有的蟀淮。這是一段Runner執(zhí)行的shell腳本。比如:
job:
script: "bundle exec rspec"
此參數(shù)還可以用數(shù)組包含一系列命令腳本:
job:
script:
- uname -a
- bundle exec rspec
有些時(shí)候钞澳,script
腳本可能需要用單引號(hào)或者雙引號(hào)來(lái)包裹怠惶。比如:命令包含冒號(hào)(:
)需要用引號(hào)包裹這樣的化YAML解析器在解析的時(shí)候知道這是一個(gè)字符串而不是"key:value"這樣的鍵值對(duì)。使用這些特殊字符串的時(shí)候要小心: :, {, }, [, ], , &, *, #, ?, |, -, <, >, =, !, %, @, , `.
only 和 except (simplified)
only
和except
是用來(lái)設(shè)置job策略限時(shí)何時(shí)創(chuàng)建job的兩個(gè)參數(shù):
-
only
定義job運(yùn)行的分支的名字轧粟,或者定義為tags(譯者注:打tag的時(shí)候會(huì)運(yùn)行) -
except
定義不運(yùn)行job的分支名稱(chēng)或者tags
這里有一些規(guī)則適用于工作策略的使用:
-
only
和except
都包括策治。如果only
和except
在一個(gè)job中都被定義,ref將會(huì)被only
和except
過(guò)濾兰吟。 -
only
和except
允許使用常規(guī)表達(dá)式(使用Ruby regexp syntax). -
only
和except
允許指定倉(cāng)庫(kù)地址去過(guò)濾fork的倉(cāng)庫(kù)通惫。
另外,only
和except
允許使用特殊的關(guān)鍵字:
Value | Description |
---|---|
branched | 當(dāng)git refrence在pipeline中是一個(gè)分支的時(shí)候 |
tag | git refrence在pipeline中是一個(gè)tag的時(shí)候 |
api | 當(dāng)pipeline被第二個(gè)pipeline觸發(fā)的api(不是觸發(fā)API) |
external | 當(dāng)使用的CI服務(wù)不是gitLab |
pipelines | 對(duì)于多項(xiàng)目觸發(fā)混蔼,創(chuàng)建使用有CI_JOB_TOKEN 的API |
pushes | 當(dāng)用戶(hù)使用git push 的時(shí)候Pipeline觸發(fā) |
schedules | 看( scheduled pipelines)[https://docs.gitlab.com/ee/user/project/pipelines/schedules.html] |
triggers: 使用trigger token創(chuàng)建pipelines
web|使用Gitlab UI上的Run pipeline創(chuàng)建pipeline(在你項(xiàng)目的Pipelines中)
merge_requests|當(dāng)merge request被創(chuàng)建或者更新的時(shí)候(看pipelines for merge requests)
在下面的例子中履腋,job只會(huì)在以issue-
開(kāi)頭的refs中運(yùn)行,然而所有的分支將會(huì)被跳過(guò)
job:
# use regexp
only:
- /^issue-.*$/
# use special keyword
except:
- branches
在下面的例子中拄丰,job只會(huì)在被打過(guò)tag或者明確指定通過(guò)觸發(fā)API請(qǐng)求構(gòu)建或者Pipeline Schedule被的refs中被引用:
job:
# use special keywords
only:
- tags
- triggers
- schedules
倉(cāng)庫(kù)地址能夠被用來(lái)指定只有父?jìng)}庫(kù)能夠執(zhí)行job而fork的不行:
job:
only:
- branches@gitlab-org/gitlab-ce
except:
- master@gitlab-org/gitlab-ce
上面的例子將會(huì)在gitlab-org/gitlab-ce
的所有分支上運(yùn)行job,而排除master分支
如果job既沒(méi)有only
也沒(méi)有except
規(guī)則府树,默認(rèn)設(shè)置為:only: ['branches', 'tags']
比如:
job:
script: echo 'test'
被翻譯成:
job:
script: echo 'test'
only: ['branches', 'tags']
only 和 except (complex)
refs
和kubernetes
策略在Gitlab10.0中被引入
variables
策略在10.7中被引用
changes
策略在11.4中被引入
Warning:這是一個(gè)alpha的功能俐末,它在任何時(shí)候都有可能在沒(méi)有提前通知的情況下改變。
從Gitlab10.0開(kāi)始o(jì)nly/except job策略可以被定義的更加細(xì)致奄侠。
Gitlab現(xiàn)在支持simple和complex兩種策略卓箫,所以可以使用數(shù)組和哈希配置方案。
四個(gè)鍵現(xiàn)在是有效的refs
,kubernetes
,variables
,changes
.
refs 和 kubernetes
Refs策略和簡(jiǎn)單模式下的only/except配置一樣垄潮,而kubernetes策略和只接受active
關(guān)鍵字烹卒。
only:variables
variables
關(guān)鍵字被用來(lái)定義變量表達(dá)式。換句話(huà)說(shuō)可以被用來(lái)與定義變量/項(xiàng)目/組或者環(huán)境范圍變量去定義一個(gè)表達(dá)式Gitlab將會(huì)去評(píng)估弯洗,決定job是否需要被創(chuàng)建旅急。
看下面的例子。job只會(huì)在pipeline有scheduled或者運(yùn)行的master
分支牡整,并且kubernetes在項(xiàng)目中是active的時(shí)候會(huì)被創(chuàng)建藐吮。
job:
only:
refs:
- master
- schedules
kubernetes: active
變量表達(dá)式的例子:
deploy:
script: cap staging deploy
only:
refs:
- branches
variables:
- $RELEASE == "staging"
- $STAGING
執(zhí)行job依賴(lài)commit message的用例(在11.0中增加):
end-to-end:
script: rake test:end-to-end
except:
variables:
- $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/
學(xué)習(xí)更多的變量表達(dá)式在另一個(gè)單獨(dú)的頁(yè)面
only:changes
在only
或者except
關(guān)鍵字使得根據(jù)git push的文件是否修改來(lái)判斷job是否應(yīng)該被創(chuàng)建成為可能。
比如:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
only:
changes:
- Dockerfile
- docker/scripts/*
- dockerfiles/**/*
- more_scripts/*.{rb,py,sh}
在上面的例子中逃贝,如果你push 多個(gè)commit到GitLab現(xiàn)有的分支上谣辞,只要提供的commit中有一個(gè)包含以下改變,Gitlab將會(huì)創(chuàng)建并出發(fā)docker build
:
-
Dockerfile
文件 - 任何在
docker/scripts/
文件夾下的文件 - 任何在
dockerfiles
文件夾下面的文件或者子文件夾 - 任何在
more_scripts
文件夾下以rb, py, sh
為擴(kuò)展名的文件
Warning:在新的分支或者tags上面使用這個(gè)功能的時(shí)候沐扳,這里有一些注意事項(xiàng)泥从,看一下面一個(gè)章節(jié)。
在新的分支或者tags上面使用changes
如果你push新的分支或者tag到Gitlab上面沪摄,這個(gè)策略將會(huì)總是被評(píng)估為true,并且Gitlab將會(huì)創(chuàng)建job.到目前為止躯嫉,這個(gè)功能還沒(méi)有于merge requests聯(lián)系在一起,因?yàn)镚itLab創(chuàng)建pipeline是在用戶(hù)創(chuàng)建merge request之前杨拐,在這個(gè)時(shí)候我們無(wú)法知道目標(biāo)分支是哪個(gè)祈餐。
沒(méi)有目標(biāo)分支,不可能知道共同的祖先是誰(shuí)戏阅,因此在這種情況下我們總是創(chuàng)建job.這個(gè)功能最好在穩(wěn)定的分支上工作昼弟,因?yàn)樵谶@中情況下Gitlab使用分支中上次commit的結(jié)果于這次push的SHA做比較啤它。
tags
tags
被用來(lái)從Runner列表中選擇允許在這個(gè)項(xiàng)目中運(yùn)行的Runner.
在注冊(cè)Runner期間你可以指定Runner的tag,比如ruby, postgres, development
.
tags允許你在job中運(yùn)行指定的job:
job:
tags:
- ruby
- postgres
在上面的例子中奕筐,我們確保job構(gòu)建的Runner定義了ruby
和postgres
的標(biāo)簽。
Tags也是一個(gè)在不同的平臺(tái)上運(yùn)行不同job的好方法变骡,比如給OSX Runner的tag賦值osx
給Window Runner賦值windows
tag,下面的job運(yùn)行在各自的平臺(tái):
windows job:
stage:
- build
tags:
- windows
script:
- echo Hello, %USERNAME%!
osx job:
stage:
- build
tags:
- osx
script:
- echo "Hello, $USER!"