說起來使用gitlab也有大半年了,每天都在跑pipeline,但是卻沒有好好研究過這個叫gitlab-ci.yml
的文件。這次借着發布流程升級的機會,好好入門了一下。
主要分以下內容:
- stages
- cache
- only
- when
- before_script,script, after_script
- artifacts
- hidden_job && extends
- reserved keywords - include
- tags
stages:
stages 是用來定義一個 pipeline 的,一個 pipeline 就像一個流水線,由一系列 stage 來構成。拿一個著名的故事來說,把大象裝進冰箱是一個pipeline,那么打開冰箱門,把大象裝進去,把冰箱🚪關上就是3個stage。再比如在發布(publish)之前要做 lint,test,build,那么這四個 stage 就構成一個pipeline,寫成下面的樣子:
stages
- lint
- test
- build
- publish
然后你在gitlab的pipeline下面就能看到下面的圖:
上面我們雖然定義了一個pipeline,和4個 stage 名稱,但是具體每個 stage 做什么還是不清楚的,stage具體要做什么是由 job 定義的。 接下來我們學習怎么定義一個job。
job
以上面的 lint 為例,我們需要執行npm run lint
命令來查看有沒有lint錯誤,那么這個job可以寫成:
job-lint:
stage: lint
script: npm run lint
這里job-lint
是任務名稱,script
是要在終端執行的命令,stage
表示這個 job 屬於哪個 stage(pipeline的某個節點)。關於 job 名稱這里要注意一點是,不能使用保留字。比如:不能把一個 job 的名字稱為 stages 或者 image,就像變量名不能用if一樣。相關文檔可以看這里。
一個 stage 下可以有多個 job,一個 job 可以進行多個 scripts。比如:打包的時候要打包到windows,mac,linux下,可以這樣:
job-build-mac:
stage: build
job-build-win;
stage: build
job-build-linux:
stage: build
有時候,我們希望一些任務是在某些場景下執行的,比如:打 tag 的時候再 build,這時候可以使用 only/except。
variables
在跑一個job的過程中,我們可能會需要環境變量,比如development,production,一個url,又或者是一個不希望顯示在控制台的token,都可以作為一個環境變量,設置一個環境變量通常有3種方式:在項目設置中,在yml文件中,或者通過api。
通過項目設置界面來配置環境變量的入口如下:
在variables下可以配置變量名和值,通常是需要保密的變量
當然我們也可以設置在yml中:
variables:
TEST: "HELLO WORLD"
然后就可以在腳本中引用:
script:
- echo $TEST
only/except
以上面的場景為例,我們可以這樣寫job-build:
job-build:
stage: build
script: npm run build
only:
- tags
這樣,上面的job就只有在我們push tags時才會觸發。如果我們希望一個job只在某一類分支有提交的時候觸發,可以這樣:
job-bugfix-build:
stage: build
script: npm run build
only:
- /^bugfix-.+$/
上面這個例子只有在bugfix為前綴的分支產生提交的時候,才會觸發job-bugfix-build。
然而,這樣並不足以讓這個任務跑起來,因為CI是跑在docker里面的,在執行run lint之前,我們需要把node環境搭起來,這就需要image保留字了:
image: node:12.18
添加了image之后,在任務開始之前,還要安裝依賴,我們使用before_script來完成這件事:
# 使用node鏡像
image: node:12.18
# 安裝依賴
before_script:
- npm install
有時候我們希望在某些場景下不執行某項任務,這時可以使用expect,比如不對hotfix進行lint:
job-lint-except-hotfix:
script:
- npm run lint
except: /^hotfix-.+$/
when
說了only,再說說when,when
是用來決定當前置任務失敗時,當前job是否執行,以及如何執行的問題。比如我們希望lint成功了再執行build:
build_job:
when: on_success
stage: build
needs: lint_job
再比如我們在執行發布的時候,希望手動點擊發布按鈕來執行發布:
publish_job:
when: manual
stage: publish
script: npm run deploy
artifacts
在前面提到的build job中,我們會使用webpack生成壓縮,混淆后的代碼,此時我們需要把它保存或者下載下來,這時就要用到artifacts了。用法如下:
build_job:
script: npm run build
artifacts:
name: "$CI_COMMIT_REF_NAME"
paths: dist/
artifacts最終會被打包成一個壓縮文件,這里的path表示要添加到壓縮文件的文件或文件夾,name表示生成的壓縮文件的名字。然后在對應的任務詳情特面就可以下載:
include
正如通過程序通過模塊來實現代碼復用一樣,CI的yml配置可以通過include實現配置復用:
include:
- remote: 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml'
- local: '/templates/.after-script-template.yml'
- template: Auto-DevOps.gitlab-ci.yml
這樣,我們可以把一些公用的環境變量或者job放到一個公共repo中,然后在其他項目中通過remote
來引用。
tags
我們已經知道,CI任務是跑在runner上的。那么,我們怎么告訴CI每個job到底用什么runner呢,這就要用到tags了。我們來看一個官方給出的例子:
windows job:
stage:
- build
tags:
- windows
script:
- echo Hello, %USERNAME%!
osx job:
stage:
- build
tags:
- osx
script:
- echo "Hello, $USER!"
上面的例子定義了兩個job,一個需要在windows上跑,另一個需要在mac上跑,我們為job加上tags,這樣CI就會找到有對應tags的runner來執行這個任務了。
最后,github actions與gitlab ci在概念上很相似,不過配置的寫法不太一樣,官方還貼心的出了遷移文檔:migrating-from-gitlab-cicd-to-github-actions