Gitlab CI 使用高級(jí)技巧

在.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):

  1. 所有的靜態(tài)資源必須在public/目錄下
  2. 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_scriptafter_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í)行的順序:

  1. 在同一個(gè)stage中指定的job將會(huì)同時(shí)運(yùn)行第步。
  2. 下一個(gè)stage將會(huì)在上一個(gè)stage完全成功后運(yùn)行。

讓我們思考如下示例藻雌,它定義了三個(gè)stage:

stages:
  - build
  - test
  - deploy

  1. 首先雌续,在build中的所有job將會(huì)同時(shí)運(yùn)行。
  2. 如果build中的所有job運(yùn)行成功胯杭,則test中的所有job將會(huì)同時(shí)運(yùn)行
  3. 如果build中的所有job運(yùn)行成功驯杜,則deploy中的job將會(huì)同時(shí)運(yùn)行。
  4. 如果deploy中的所有job運(yùn)行成功做个,則commit將會(huì)標(biāo)記為passed.
  5. 如果任何一個(gè)之前的job執(zhí)行失敗鸽心,則commit將會(huì)被標(biāo)記為失敗,并且之后stage中的所有job都不會(huì)執(zhí)行居暖。

這里還有兩個(gè)值得一提的邊緣例子:

  1. 如果.gitlab-ci.yml中沒(méi)有定義stages顽频,這樣的話(huà)默認(rèn)情況下build, test,deploy 可以在job的stage中被使用。
  2. 如果job沒(méi)有指定stage,那么job將被分配teststage.

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)

onlyexcept是用來(lái)設(shè)置job策略限時(shí)何時(shí)創(chuàng)建job的兩個(gè)參數(shù):

  1. only定義job運(yùn)行的分支的名字轧粟,或者定義為tags(譯者注:打tag的時(shí)候會(huì)運(yùn)行)
  2. except定義不運(yùn)行job的分支名稱(chēng)或者tags
    這里有一些規(guī)則適用于工作策略的使用:
  • onlyexcept都包括策治。如果onlyexcept在一個(gè)job中都被定義,ref將會(huì)被onlyexcept過(guò)濾兰吟。
  • onlyexcept允許使用常規(guī)表達(dá)式(使用Ruby regexp syntax).
  • onlyexcept允許指定倉(cāng)庫(kù)地址去過(guò)濾fork的倉(cāng)庫(kù)通惫。
    另外,onlyexcept允許使用特殊的關(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)

refskubernetes策略在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定義了rubypostgres的標(biāo)簽。
Tags也是一個(gè)在不同的平臺(tái)上運(yùn)行不同job的好方法变骡,比如給OSX Runner的tag賦值osx給Window Runner賦值windowstag,下面的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!"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末离赫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子塌碌,更是在濱河造成了極大的恐慌渊胸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件台妆,死亡現(xiàn)場(chǎng)離奇詭異翎猛,居然都是意外死亡胖翰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)切厘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)萨咳,“玉大人,你說(shuō)我怎么就攤上這事疫稿∨嗨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵遗座,是天一觀的道長(zhǎng)舀凛。 經(jīng)常有香客問(wèn)我,道長(zhǎng)途蒋,這世上最難降的妖魔是什么猛遍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮号坡,結(jié)果婚禮上螃壤,老公的妹妹穿的比我還像新娘。我一直安慰自己筋帖,他們只是感情好奸晴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著日麸,像睡著了一般寄啼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上代箭,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天墩划,我揣著相機(jī)與錄音,去河邊找鬼嗡综。 笑死乙帮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的极景。 我是一名探鬼主播察净,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼盼樟!你這毒婦竟也來(lái)了氢卡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤晨缴,失蹤者是張志新(化名)和其女友劉穎译秦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筑悴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年们拙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阁吝。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡睛竣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出求摇,到底是詐尸還是另有隱情射沟,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布与境,位于F島的核電站验夯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏摔刁。R本人自食惡果不足惜挥转,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望共屈。 院中可真熱鬧绑谣,春花似錦、人聲如沸拗引。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)矾削。三九已至壤玫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哼凯,已是汗流浹背欲间。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留断部,地道東北人猎贴。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蝴光,于是被迫代替她去往敵國(guó)和親她渴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355