!!!實踐過程中請留意文件版本號跟你實際使用Gitlab的版本號
前置知識
- yaml語法,教程??YAML 入門教程
- Docker相關知識,教程??Docker教程
- linux命令,教程??Linux 命令大全
自定義配置目錄
預設配置檔案目錄是在mono repo
的根目錄,檔名為.gitlab-ci.yml
。
若需要自定義設定CI指令碼檔案的路徑,如下:
流水線配置
.gitlab-ci.yml
檔案中對流水線配置大致可以分為2個環節:
- 全域性配置,執行在單個
stage
之前或者之後。 - 單個
stage
配置
結構大致可以如下:
# 指定指令碼執行的映象環境,如下為node環境為14.17.1
image: node:14.17.1
# 單個job執行之前執行
before_script:
- echo '====== 準備構建中 ========='
# 配置單個stage的執行順序,序列
stages:
- install
- build
# 單個stage配置
# 安裝依賴
npm_install:
only:
- master
stage: install
script:
- yarn
- ls -al
# 單個stage配置
# 構建
webpack_build:
only:
- master
stage: build
script:
- yarn build
# 單個job全部執行完之後執行
after_script:
- echo "====== 構建結束 ========="
重要概念
Pipeline
流水線,一次流水線相當於一次構建任務,裡面可以包含多個階段,比如install -> eslint -> build -> deploy等流程 ;
stages
表示構建階段,每個stage序列同步執行。一旦有一個stage中的一個job失敗了,那麼下一個stage的任務便不會執行。如果當前stage定義了多個任務,那麼其中一個任務失敗,另外一個任務還是會被繼續執行。但是隻有當所有 stages 成功完成後,該構建任務 (Pipeline) 才算成功。
jobs
job表示某個stage裡面執行的工作 ,一個stage裡面可以定義多個job 。
jobs有如下特點 :
- 相同 stage 中的jobs 會並行執行
- 相同 stage 中的 jobs 都執行成功時,該 stage 才會成功
- 如果任何一個job 失敗,那麼該 stage 失敗,即該構建任務 (Pipeline) 失敗
gitlab runner
執行構建任務的一個服務,裡面包含了持續整合的的環境,一般由docker建立。它可以在不同的主機上部署,也可以在同一個主機上設定多個gitlab-runner ,還可以根據不同的環境設定不同的環境,比如我們需要區分研發環境,測試環境以及正式環境等。
關鍵字
image
CI/CD指令碼執行環境的docker映象,映象就是一種檔案儲存形式,可以理解為是一個環境的集合,內含多種檔案。如指定node環境映象:
# 最新版本node環境
image: node:@latest
tags
指定gitlab 在執行指令碼時使用哪個runner。
before_script
在單個stage
執行之前執行的指令碼內容,內容以陣列形式配置,如上例子中:
before_script:
- echo '====== 準備構建中 ========='
stages
CI允許我們進行自定義的流水線階段配置,可以將一個流水線拆分為多個階段(stage
),stages會序列執行。
stages:
- install
- build
script
執行指令碼,指令碼內容以陣列形式配置。如上例子中stage為npm_install階段執行的指令碼為:
script:
- yarn
- ls -al
先執行yarn命令安裝依賴,結束後檢視了當前目錄下檔案及目錄的具體資訊,是個序列執行的過程。
cache
快取多個流水線任務之間共用的檔案和目錄,快取相關概念下文詳情講述。
only & except
設定流水線任務執行時機:使用 only
來定義job
何時執行,使用 except
定義job
不 執行的時間。
指定分支觸發執行時機
job: only: - branches@gitlab-org/gitlab except: - main@gitlab-org/gitlab - /^release/.*$/@gitlab-org/gitlab
此示例為
gitlab-org/gitlab
上的所有分支執行job
,除了main
和以release/
開頭的分支。在合併請求時觸發
job1: script: - echo "This job runs in merge request pipelines" only: - merge_requests
在push的時候觸發
job1: script: - echo "branch push" only: - pushes
手動觸發
在Gitlab Runner/pipeline裡面點選run pipeline時觸發
job1: only: - web
根據git提交訊息或者判斷分支觸發執行時機
build: script: - yarn build except: variables: - $CI_COMMIT_MESSAGE =~ /test/ || $CI_COMMIT_BRANCH == "main"
git commit 訊息為”test“的push跟提交分支為”main“的push不觸發此job。
根據檔案修改判斷執行時機
build: script: yarn build except: changes: - "*.md"
只要有md檔案修改就不執行此job。
retry
job重試次數,預設為0,最大重試次數為2,其中when
可設定在特定失敗原因的情況下執行。
rules:if
此欄位可以在單個流水線job或者workflow欄位下進行配置。
rules
關鍵詞下可以進行if語句配置,如果if滿足的話可執行某些自定義配置。
rules:
- if: $CI_COMMIT_REF_NAME =~ /feature/
注意: only & except
和rules:if
都是用來決定單個job執行時機的,在配置時只能存在一個,否則會報錯。
workflow
和rules
配合用來控制流水線的執行動作,在最外層進行配置,workflow: rules
接受這些關鍵字:
if
:檢查此規則以確定何時執行流水線。when
:指定當if為 true 時要做什麼。- 要執行流水線,請設定為
always
。 - 要阻止流水線執行,請設定為
never
。
- 要執行流水線,請設定為
variables
:如果未定義,則使用在別處定義的變數。適用版本13.11 ~14.0
當沒有規則為 true 時,流水線不會執行。
以下示例中,前兩天規則都匹配到不執行時機,當else時,流水線執行。
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_PIPELINE_SOURCE == "push"'
when: never
- when: always
when
控制上一個stage成功或者失敗時,當前stage的行為。
on_success
(預設值): 上一個stage成功了才會執行當階段任務,或者之前失敗的任務配置了allow_failure: true
。on_failure
:只有上一個階段任務失敗了才會執行當前任務。always
:無論上一個階段的jobs狀態如何,都會觸發當前階段的任務。never
:不執行當前任務。manual
:在gitlab網頁中手動點選觸發。
模組化
使用關鍵字include
引入其他yml
檔案中的配置。
include:
- '/yml/job1_install.yml'
- '/yml/job2_lint.yml'
- '/yml/job3_build.yml'
- '/yml/job4_deploy.yml'
快取
重要概念
在 GitLab CI/CD 中,我們所使用的 runner 是以 docker 的形式執行不同的任務。普通的 cache 機制(即不指定URL,No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
),其 cache 是儲存在本地,所以如果兩個 job 實際執行的位置是不在宿主機上的,其相互之間的快取是無法共享的。
分散式快取
分散式快取需要runner配置支援,開啟後需要在cache中配置s3ServerAddress、s3BucketName等資訊進行快取跨runner共享。
快取路徑
在配置cache時,paths
跟files
的檔案/目錄都是以專案的根目錄為相對位置的,在store cache的時候也是以專案名區分快取路徑的,應用快取的時候會在專案下配合key值去應用快取,即使是分散式快取也是按照這個策略。
快取檔案資訊上會有最後更新時間(重要資訊)、檔案許可權、cache
中設定的key
等,其中更新時間跟快取策略有聯絡,如果惡意篡改伺服器時間,可能會出現依賴前後不一致導致打出來的包不符合預期的情況。
快取繫結檔案
快取繫結到當前版本的檔案。當這些檔案之一發生變化時,將計算一個新的快取鍵並建立一個新的快取,如下:
cache-job:
script:
- echo "This job uses a cache."
cache:
key:
files:
- Gemfile.lock
- package.json
paths:
- vendor/ruby
- node_modules
此時的 key
是根據最近更改了每個列出的檔案的提交計算得出的 SHA
。如果在任何提交中都沒有更改任何檔案,則key
就是預設值 default
。
多檔案快取
cache可以配置多個key
,適用於13.10 ~ 13.12版本,其他版本可以在key
下的files
和paths
配置多個路徑/檔案來實現。
禁用快取
使用cache: {}
來禁用快取。
繼承快取
快取配置可複用的情況下使用繼承寫法,可以在當前job下覆蓋(重寫)某個策略或者設定優先順序
cache: &global_cache
key: $CI_COMMIT_REF_SLUG
paths:
- node_modules/
- public/
- vendor/
policy: pull-push
job:
cache:
# 繼承全域性快取
<<: *global_cache
# 重寫快取策略
policy: pull
回退快取鍵
13.4版本以上可應用回退快取鍵,功能類似快取備份。你可以使用 CACHE_FALLBACK_KEY
變數來指定一個備份快取key,他會在你指定key的快取不存在時去查詢應用備份快取。
variables:
CACHE_FALLBACK_KEY: fallback-key
job1:
script:
- echo
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- binaries/
手動清除快取
您可以在 GitLab UI 中清除快取:
- 在頂部欄上,選擇 選單 > 專案 並找到您的專案。
- 在左側邊欄上,選擇 CI/CD > 流水線 頁面。
- 在右上角,選擇 清除 Runner 快取。
在下一次提交時,您的 CI/CD 作業使用新的快取。
實戰:構建釋出元件庫到npm倉庫
編寫.gitlab-ci.yml
基本流程,如下:
image: node:14.17.1
before_script:
- echo '====== 準備構建中 ========='
stages:
- install
- lint
- build
- deploy
### 配置快取
cache:
key:
files:
- package.json
- packages/ghost-weapp-ui/package.json
paths:
- node_modules/
- packages/ghost-weapp-ui/node_modules/
### 直接快取.npm,.npm中快取了所有依賴,因為gitlab快取是分專案的,所以兩種方法個人覺得沒有什麼區別
# - .npm/
# eslint檢測
job_lint:
only:
- master
stage: lint
before_script:
- echo 'eslint檢測'
- ls -a
script:
- cd packages/ghost-weapp-ui
- ls -a
- yarn lint
- echo 'eslint檢測完成'
retry: 0
when: 'on_success'
# 安裝依賴
job_install:
only:
- master
stage: install
before_script:
- echo '安裝依賴'
script:
- yarn config set registry https://registry.npm.taobao.org/
- yarn install
- cd packages/ghost-weapp-ui
- ls -a
- yarn install
- ls -a
- echo '依賴安裝完成'
retry: 0
# 打包編譯
job_build:
only:
- master
stage: build
before_script:
- echo '開始打包'
script:
- cd packages/ghost-weapp-ui
- ls -a
- yarn
- ls -a
- yarn build
- echo '構建完成'
when: 'on_success'
retry: 0
# 釋出
job_deploy:
only:
- master
stage: deploy
before_script:
- echo '更新補丁版本,準備釋出'
script:
- cd packages/ghost-weapp-ui
- node deploy.js ${CI_COMMIT_REF_NAME}
when: 'on_success'
retry: 0
after_script:
- echo "====== 釋出完成 ========="
編寫部署指令碼,其中主要是模擬npm login
流程替換為使用token進行登入並且執行npm publish
,釋出到npm的流程。
const fs = require('fs')
const path = require('path')
const os = require('os')
const { exec } = require('child_process')
// 替換為自己npm賬號的authToken
// token獲取方法:vim ~/.npmrc
const npmrcText = `registry=https://registry.npmjs.org/
home=https://www.npmjs.org
//registry.npmjs.org/:_authToken=${authToken}
`
// 獲取命令中第三個引數,此例子中為'master'
// node deploy.js ${CI_COMMIT_REF_NAME}, 分支名為master
const env = process.argv[2]
// 拼接命令,執行npm publish,打tag
function deploy() {
fs.writeFileSync(path.resolve(os.homedir(), '.npmrc'), npmrcText)
const argsArray = ['publish'].concat(['--tag', env === 'master' ? 'latest' : 'beta'])
execa('npm', argsArray);
}
async function execa(a, arry = []) {
return new Promise((resolve, reject) => {
exec(`${a} ${arry.join(' ')}`, (err, stdout, stderr) => {
if (err) {
console.error(err);
reject(err);
}
resolve(stdout)
})
})
}
deploy();
執行結果:
收到npm釋出成功反饋郵件:
以上就是gitlab CI/CD的相關知識點以及實戰釋出npm包的示例,感謝閱讀!