一、GitLab
GitLab 是一個(gè)用于倉(cāng)庫(kù)管理系統(tǒng)的開(kāi)源項(xiàng)目,使用 Git 作為代碼管理工具,并在此基礎(chǔ)上搭建起來(lái)的 Web 服務(wù)。
安裝方法是參考 GitLab 在 GitHub 上的 Wiki 頁(yè)面。Gitlab 是被廣泛使用的基于 git 的開(kāi)源代碼管理平臺(tái), 基于 Ruby on Rails 構(gòu)建, 主要針對(duì)軟件開(kāi)發(fā)過(guò)程中產(chǎn)生的代碼和文檔進(jìn)行管理,。
Gitlab 主要針對(duì) group 和 project 兩個(gè)維度進(jìn)行代碼和文檔管理,:
- 其中 group 是群組, project 是工程項(xiàng)目, 一個(gè) group 可以管理多個(gè) project, 可以理解為一個(gè)群組中有多項(xiàng)軟件開(kāi)發(fā)任務(wù)
- 一個(gè) project 中可能包含多個(gè) branch, 意為每個(gè)項(xiàng)目中有多個(gè)分支, 分支間相互獨(dú)立, 不同分支可以進(jìn)行歸并。
Git的家族成員
- Git:是一種版本控制系統(tǒng),是一個(gè)命令,是一種工具,詳解介紹。
- Gitlib:是用于實(shí)現(xiàn) Git 功能的開(kāi)發(fā)庫(kù)。
- Github:是一個(gè)基于Git實(shí)現(xiàn)的在線代碼托管倉(cāng)庫(kù),包含一個(gè)網(wǎng)站界面,向互聯(lián)網(wǎng)開(kāi)放。
- GitLab:是一個(gè)基于Git實(shí)現(xiàn)的在線代碼倉(cāng)庫(kù)托管軟件,你可以用gitlab自己搭建一個(gè)類(lèi)似于Github一樣的系統(tǒng),一般用于在企業(yè)、學(xué)校等內(nèi)部網(wǎng)絡(luò)搭建git私服。
二、GitLab-CI/CD
官方文檔
GitLab CI/CD 是一個(gè)內(nèi)置在 GitLab 中的工具,用于通過(guò)持續(xù)方法進(jìn)行軟件開(kāi)發(fā),這些方法使得可以在開(kāi)發(fā)周期的早期發(fā)現(xiàn) bugs 和 errors,從而確保部署到生產(chǎn)環(huán)境的所有代碼都符合為應(yīng)用程序建立的代碼標(biāo)準(zhǔn):
- Continuous Integration(CI):持續(xù)集成,工作原理是將小的代碼塊推送到 Git 倉(cāng)庫(kù)中托管的應(yīng)用程序代碼庫(kù)中,并且每次推送時(shí),都要運(yùn)行一系列腳本來(lái)構(gòu)建、測(cè)試和驗(yàn)證代碼更改,然后再將其合并到主分支中。
- Continuous Delivery(CD):持續(xù)交付
- Continuous Deployment(CD):持續(xù)部署,持續(xù)交付和部署相當(dāng)于更進(jìn)一步的 CI,可以在每次推送到倉(cāng)庫(kù)默認(rèn)分支的同時(shí)將應(yīng)用程序部署到生產(chǎn)環(huán)境。
GitLab CI/CD 怎么執(zhí)行:GitLab Runner 執(zhí)行
GitLab CI/CD 由一個(gè)名為 .gitlab-ci.yml
的文件進(jìn)行配置,該文件需要位于倉(cāng)庫(kù)的根目錄下并配置 GitLab Runner,每次提交代碼的時(shí)候,gitlab 就會(huì)自動(dòng)識(shí)別文件中指定的腳本由 GitLab Runner 執(zhí)行。
2.1 gitlab-ci.yml
在這個(gè)文件中,可以定義要運(yùn)行的腳本,定義包含的依賴項(xiàng),選擇要按順序運(yùn)行的命令和要并行運(yùn)行的命令,定義要在何處部署應(yīng)用程序,以及指定是否 要自動(dòng)運(yùn)行腳本或手動(dòng)觸發(fā)腳本。
為了可視化處理過(guò)程,假設(shè)添加到配置文件中的所有腳本與在計(jì)算機(jī)的終端上運(yùn)行的命令相同。
一旦已經(jīng)添加了 .gitlab-ci.yml
到倉(cāng)庫(kù)中,GitLab 將檢測(cè)到該文件,并使用名為 GitLab Runner 的工具運(yùn)行腳本。該工具的操作與終端類(lèi)似。
2.1.1 基礎(chǔ)概念
1、Pipeline:
每個(gè)推送到 Gitlab 的提交都會(huì)產(chǎn)生一個(gè)與該提交關(guān)聯(lián)的 pipeline,若一次推送包含了多個(gè)提交,則 pipeline 與最后那個(gè)提交相關(guān)聯(lián),pipeline 就是一個(gè)分成不同 stage 的 job 的集合。
整個(gè) pipeline 如下圖所示,由 3 個(gè) stage 組成。
2、Stage:
stage 是對(duì)批量的作業(yè)的一個(gè)邏輯上的劃分,每個(gè) GitLab CI/CD 都必須包含至少一個(gè) Stage。多個(gè) Stage 是按照順序執(zhí)行的,如果其中任何一個(gè) Stage 失敗,則后續(xù)的 Stage 不會(huì)被執(zhí)行,整個(gè) CI 過(guò)程被認(rèn)為失敗。
下圖中共 3 個(gè) stage,多個(gè) stage 組成 pipeline,每個(gè) stage 里邊又包括了很多 job。
3、Job
Job 就是 Runner 要執(zhí)行的指令集合,Job 可以被關(guān)聯(lián)到一個(gè) Stage。當(dāng)一個(gè) Stage 執(zhí)行的時(shí)候,與其關(guān)聯(lián)的所有 Job 都會(huì)被執(zhí)行。在有足夠運(yùn)行器的前提下,同一階段的所有作業(yè)會(huì)并發(fā)執(zhí)行。Job 狀態(tài)與 Stage 狀態(tài)是一樣的,實(shí)際上,Stage 的狀態(tài)就是繼承自 job 的。
Job 必須包含 script(由 Runner 執(zhí)行的 shell 腳本),隨著項(xiàng)目越來(lái)越大,Job 越來(lái)越多,Job 中包含的重復(fù)邏輯可能會(huì)讓配置文件臃腫不堪, .gitlab-ci.yml
中提供了 before_script 和 after_script 兩個(gè)全局配置項(xiàng)。這兩個(gè)配置項(xiàng)在所有 Job 的 script 執(zhí)行前和執(zhí)行后調(diào)用。
Job 的執(zhí)行過(guò)程中往往會(huì)產(chǎn)生一些數(shù)據(jù),默認(rèn)情況下 GitLab Runner 會(huì)保存 Job 生成的這些數(shù)據(jù),然后在下一個(gè) Job 執(zhí)行之前(甚至不局限于當(dāng)次 CI/CD)將這些數(shù)據(jù)恢復(fù)。這樣即便是不同的 Job 運(yùn)行在不同的 Runner 上,它也能看到彼此生成的數(shù)據(jù)。
如下圖所示,每個(gè) stage 包含多個(gè) job。
2.1.2 創(chuàng)建 yml 文件
創(chuàng)建:在對(duì)應(yīng)分支上,點(diǎn)擊 + 號(hào),然后點(diǎn)擊 New file,然后填寫(xiě) file name,.gitlab-ci.yml
創(chuàng)建成功后就會(huì)生成如下文件:
.gitlab-ci.yml 一個(gè)簡(jiǎn)單的文件內(nèi)容示例如下:
build-job:
stage: build
script:
- echo "Hello, $GITLAB_USER_LOGIN!"
test-job1:
stage: test
script:
- echo "This job tests something"
test-job2:
stage: test
script:
- echo "This job tests something, but takes more time than test-job1."
- echo "After the echo commands complete, it runs the sleep command for 20 seconds"
- echo "which simulates a test that runs 20 seconds longer than test-job1"
- sleep 20
deploy-prod:
stage: deploy
script:
- echo "This job deploys something from the $CI_COMMIT_BRANCH branch."
environment: production
上面的例子中包含了 4 個(gè) jobs:
- build-job
- test-job1
- test-job2
- deploy-prod
2.1.3 yml 文件中的關(guān)鍵字
1、全局關(guān)鍵字
-
default
:自定義 job 關(guān)鍵字的默認(rèn)值 -
include
:從其他 yaml 文件中 import 配置 -
stage
:pipeline 每個(gè) stage 的名字和順序 -
variables
:定義所有 job 的 CI/CD 變量 -
workflow
:控制 pipeline 運(yùn)行的類(lèi)型
① default
:
default:
image: ruby:3.0
rspec:
script: bundle exec rspec
rspec 2.7:
image: ruby:2.7
script: bundle exec rspec
-
ruby:3.0
是 pipeline 中所有 job 的默認(rèn) image,respec 2.7 中定義了自己的特定值,在該 job 中使用自己定義的ruby:2.7
- 創(chuàng)建 pipeline 時(shí),每個(gè)默認(rèn)值都會(huì)復(fù)制到未定義該關(guān)鍵字的 job 中
- 如果 job 中有了其中一個(gè)關(guān)鍵字,則優(yōu)先使用 job 中的配置,不會(huì)被默認(rèn)值替換
- 控制 job 中默認(rèn)關(guān)鍵字的繼承
inherit:default
② include
:
可以從外部 include 其他 yaml 文件到 .gitlab-ci.yml
中,文件拆分可以增加可讀性,或減少在多個(gè)地方重復(fù)的配置。最多可以包含 100 個(gè) include。
參數(shù):
1、include: local,用于引入和 .gitlab-ci.yml 位于相同倉(cāng)庫(kù)中的文件
include:
- local: '/templates/.gitlab-ci-template.yml'
2、include: project,用于引入其他項(xiàng)目中的文件,project 后跟文件夾
include: file,文件的完整路徑,相對(duì)于根目錄(/)
include: ref,可選的參數(shù),tag
include:
- project: 'my-group/my-project'
ref: main # Git branch
file: '/templates/.gitlab-ci-template.yml'
- project: 'my-group/my-project'
ref: v1.0.0 # Git Tag
file: '/templates/.gitlab-ci-template.yml'
- project: 'my-group/my-project'
ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA
file: '/templates/.gitlab-ci-template.yml'
3、include: remote,使用 url 從其他地方引入文件
include:
- remote: 'https://gitlab.com/example-project/-/raw/main/.gitlab-ci.yml'
4、include: template,引入 .gitlab-ci.yml 模版
include:
- template: Android-Fastlane.gitlab-ci.yml
- template: Auto-DevOps.gitlab-ci.yml
- job 中的配置比 include 的文件配置優(yōu)先級(jí)更高
- 可以在 job 中重寫(xiě) included 的配置,使用相同的 job name 或全局 keyword
- 如果對(duì) job 重新運(yùn)行,則 include 文件不會(huì)被重新讀取,所有的配置是在 pipeline 創(chuàng)建的時(shí)候讀取的,所以 include 的東西不會(huì)重新讀取
- 如果對(duì) pipeline 重新運(yùn)行,則 include 文件會(huì)被重新讀取,如果更改了后,會(huì)生效
③ stages
:可以定義一系列 job 在哪個(gè) stage 中執(zhí)行
如果 stages 沒(méi)有在 yml 中定義,則默認(rèn)的順序如下:
- .pre → build → test → deploy → .post
- 一個(gè) stage 中的 job,是并行執(zhí)行的
- 下一個(gè) stage 中的 job 要等上一個(gè) stage 全部執(zhí)行完之后才能執(zhí)行
- 如果一個(gè) pipeline 只包含 .pre 或 .post 中的 job,則不會(huì)執(zhí)行
示例:
stages:
- build
- test
- deploy
在這個(gè)例子中:
- build 并行執(zhí)行的所有 job。
- 如果所有 job 都 build 成功,??則 test job 并行執(zhí)行。
- 如果所有 job 都 test 成功,??則 deploy job 并行執(zhí)行。
- 如果所有 job 都 deploy 成功,??pipeline 將標(biāo)記為 passed。
- 如果任何 job 失敗,??pipeline 將被標(biāo)記為 failed 并且后續(xù)階段的 job 不會(huì)啟動(dòng)。當(dāng)前階段的 job 不會(huì)停止并繼續(xù)運(yùn)行。
- 如果 job 未指定 stage,則默認(rèn)分配到 test 階段
④ workflow
:控制 pipeline 的行為
workflow: name,為 pipeline 定義一個(gè)名稱(chēng)
workflow:
name: 'Pipeline for branch: $CI_COMMIT_BRANCH'
variables:
PIPELINE_NAME: 'Default pipeline name'
workflow:
name: '$PIPELINE_NAME'
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
variables:
PIPELINE_NAME: 'MR pipeline: $CI_COMMIT_BRANCH'
- if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby3/'
variables:
PIPELINE_NAME: 'Ruby 3 pipeline'
workflow: rules,用來(lái)控制是否創(chuàng)建整個(gè) pipeline
rules: if.
rules: changes.
rules: exists.
when, can only be always or never when used with workflow.
variables.
示例:
workflow:
rules:
- if: $CI_COMMIT_TITLE =~ /-draft$/ # 當(dāng) pipeline 的 commit title 不是以 -draft 結(jié)尾,pipeline 就會(huì)運(yùn)行
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
workflow: rules: variables,使用 variables 來(lái)定義特殊條件下生效的變量,當(dāng)條件吻合時(shí),創(chuàng)建變量并用于所有 jobs。
variables:
DEPLOY_VARIABLE: "default-deploy"
workflow:
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables:
DEPLOY_VARIABLE: "deploy-production" # Override globally-defined DEPLOY_VARIABLE
- if: $CI_COMMIT_REF_NAME =~ /feature/
variables:
IS_A_FEATURE: "true" # Define a new variable.
- when: always # Run the pipeline in other cases
job1:
variables:
DEPLOY_VARIABLE: "job1-default-deploy"
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
variables: # Override DEPLOY_VARIABLE defined
DEPLOY_VARIABLE: "job1-deploy-production" # at the job level.
- when: on_success # Run the job in other cases
script:
- echo "Run script with $DEPLOY_VARIABLE as an argument"
- echo "Run another script if $IS_A_FEATURE exists"
job2:
script:
- echo "Run script with $DEPLOY_VARIABLE as an argument"
- echo "Run another script if $IS_A_FEATURE exists"
When the branch is the default branch:
job1’s DEPLOY_VARIABLE is job1-deploy-production.
job2’s DEPLOY_VARIABLE is deploy-production.
When the branch is feature:
job1’s DEPLOY_VARIABLE is job1-default-deploy, and IS_A_FEATURE is true.
job2’s DEPLOY_VARIABLE is default-deploy, and IS_A_FEATURE is true.
When the branch is something else:
job1’s DEPLOY_VARIABLE is job1-default-deploy.
job2’s DEPLOY_VARIABLE is default-deploy.
2、Job 關(guān)鍵字
-
after_script
:定義所有 job 執(zhí)行過(guò)后需要執(zhí)行的命令,可以接受一個(gè)數(shù)組或者多行字符串 -
allow_failure
:允許 job 失敗,失敗的 job 不會(huì)導(dǎo)致 pipeline 失敗。 -
artifacts
:成功時(shí)附加到作業(yè)的文件和目錄列表 -
before_script
:定義所有 job 執(zhí)行之前需要執(zhí)行的命令 -
cache
:緩存的文件列表 -
coverage
:job 的代碼覆蓋率 -
dast_configuration
:在 job level 使用的 DAST 配置文件中的配置 -
dependencies
:任務(wù)依賴。指定 job 的前置 job。添加該參數(shù)后,可以獲取到前置 job 的 artifacts。注意如果前置 job 執(zhí)行失敗, 導(dǎo)致沒(méi)能生成 artifacts, 則 job 也會(huì)直接失敗 -
environment
:job 部署使用的環(huán)境 -
except
:控制什么時(shí)候 job 不生效 -
extends
:job 繼承自的配置 -
image
:使用的 Docker 鏡像 -
inherit
:所有 job 繼承全局默認(rèn)值 -
interruptible
:當(dāng)一個(gè)分支的 pipeline 多次被觸發(fā)時(shí),是否自動(dòng)取消舊的流水線 -
needs
:定義 job 的執(zhí)行順序 -
only
:控制創(chuàng)建 job 的時(shí)間 -
pages
:上傳結(jié)果并和 gitlab pages 一起使用 -
parallel
:并行運(yùn)行幾個(gè) job -
release
:創(chuàng)建一個(gè)發(fā)布 -
resource_group
:限制 job 的并發(fā) -
retry
:job 失敗后重新啟動(dòng)的次數(shù) -
rules
:當(dāng)前作業(yè)運(yùn)行失敗后,是否不停止 pipeline,繼續(xù)往下執(zhí)行 -
script
:由 runner 執(zhí)行的 shell 腳本 -
secrets
:CI/CD 保密工作需要 -
services
:使用 docker 服務(wù)鏡像 -
stage
:定義 job 的階段 -
tags
:選擇 runner 的標(biāo)簽 -
timeout
:定義優(yōu)先于 project 設(shè)置的 job-level 的超時(shí)時(shí)長(zhǎng) -
trigger
:定義下游 pipeline 觸發(fā)器 -
variables
:在 job-level 定義 job 變量 -
when
:運(yùn)行 job 的時(shí)間
1) after_scripts
:
job:
script:
- echo "An example script section."
after_script:
- echo "Execute this command after the `script` section completes."
2)allow_failure
:true → 某些 job 失敗后,pipeline 繼續(xù)執(zhí)行,false→ 某些 job 失敗后,pipeline 停止執(zhí)行
job1:
stage: test
script:
- execute_script_1
job2:
stage: test
script:
- execute_script_2
allow_failure: true
job3:
stage: deploy
script:
- deploy_to_staging
environment: staging
In this example, job1 and job2 run in parallel:
If job1 fails, jobs in the deploy stage do not start.
If job2 fails, jobs in the deploy stage can still start.
allow_failure: exit_codes
,后面跟參數(shù),控制什么時(shí)候 job 允許失敗
test_job_1:
script:
- echo "Run a script that results in exit code 1. This job fails."
- exit 1
allow_failure:
exit_codes: 137
test_job_2:
script:
- echo "Run a script that results in exit code 137. This job is allowed to fail."
- exit 137
allow_failure:
exit_codes:
- 137
- 255
3)artifacts
:指定需要保存的結(jié)果
artifacts: paths 指定結(jié)果保存的路徑
artifacts: name 指定文件保存的名稱(chēng),未指定的話就是 artifacts.zip
artifacts: exclude 不保存的文件
job:
artifacts:
paths:
- binaries/
- .config
# 保存 binary 中的所有文件,除過(guò) *.o 的文件外
artifacts:
paths:
- binaries/
exclude:
- binaries/**/*.o
4) before_script
:在每個(gè) job 的 script 運(yùn)行前需要運(yùn)行的東西
job:
before_script:
- echo "Execute this command before any 'script:' commands."
script:
- echo "This command executes after the job's 'before_script' commands."
5) cache
:
cache: paths,用于配置要緩存的文件路徑
rspec:
script:
- echo "This job uses a cache."
cache:
key: binaries-cache
paths:
- binaries/*.apk
- .config
cache: key,讓每個(gè)緩存都有特有的 key
cache-job:
script:
- echo "This job uses a cache."
cache:
key: binaries-cache-$CI_COMMIT_REF_SLUG
paths:
- binaries/
6) coverage
:用于提前日志中的覆蓋率,你可以設(shè)置一個(gè)正則表達(dá)式,如果當(dāng)前作業(yè)的日志命中了該表達(dá)式,覆蓋率將會(huì)被提取出來(lái)。如果命中了多個(gè),將以最后一個(gè)為準(zhǔn),提取出來(lái)的覆蓋率可以顯示到項(xiàng)目 UI 上。
7) dependencies
:任務(wù)依賴。指定 job 的前置 job。添加該參數(shù)后,可以獲取到前置 job 的 artifacts。注意如果前置 job 執(zhí)行失敗,導(dǎo)致沒(méi)能生成 artifacts, 則 job 也會(huì)直接失敗
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
environment: production
本例中,build osc
和 build linux
有 artifacts,當(dāng) test osx 執(zhí)行后,會(huì)下載 build osx 的 artifacts
8)environment
:定義 job 部署的環(huán)境
deploy to production:
stage: deploy
script: git push production HEAD:main
environment: production
environment: name,給 environment 設(shè)置一個(gè)名稱(chēng)
deploy to production:
stage: deploy
script: git push production HEAD:main
environment:
name: production
environment: url,給 environment 設(shè)置一個(gè) url
deploy to production:
stage: deploy
script: git push production HEAD:main
environment:
name: production
url: https://prod.example.com
9) extends
:替代了 YAML Anchors,可讀性好,而且更加靈活。它定義一個(gè)可以讓 job 去繼承的模板,這樣可以讓我們把一些共同的 key 進(jìn)行抽象,方便以后的維護(hù)與擴(kuò)展
輸入:pipeline 中其他 job 的名稱(chēng)
下面的例子中,rspec
job 使用 .test
模版 job 中的配置
.tests:
script: rake test
stage: test
only:
refs:
- branches
rspec:
extends: .tests
script: rake rspec
only:
variables:
- $RSPEC
rspec
job 的配置最終如下:
rspec:
script: rake rspec
stage: test
only:
refs:
- branches
variables:
- $RSPEC
10) image
:指定 job 使用的 docker image
default:
image: ruby:3.0
rspec:
script: bundle exec rspec
rspec 2.7:
image: registry.example.com/my-group/my-project/ruby:2.7
script: bundle exec rspec
11)inherit
:控制是否繼承 default 的關(guān)鍵字和變量
inherit: default
inherit: default: [keywords1, keywords2] #也可以使用 list 定義繼承的關(guān)鍵字
default:
retry: 2
image: ruby:3.0
interruptible: true
job1:
script: echo "This job does not inherit any default keywords."
inherit:
default: false
job2:
script: echo "This job inherits only the two listed default keywords. It does not inherit 'interruptible'."
inherit:
default:
- retry
- image
inherit: variables, 控制全局變量關(guān)鍵字是否繼承
inherit: variables: [VARIABLE1, VARIABLE2] # 也可以使用 list 參與繼承的全局變量
variables:
VARIABLE1: "This is variable 1"
VARIABLE2: "This is variable 2"
VARIABLE3: "This is variable 3"
job1:
script: echo "This job does not inherit any global variables."
inherit:
variables: false
job2:
script: echo "This job inherits only the two listed global variables. It does not inherit 'VARIABLE3'."
inherit:
variables:
- VARIABLE1
- VARIABLE2
12)interruptible
:當(dāng) pipeline 重新運(yùn)行時(shí),job 是否中斷,true/false(默認(rèn))
stages:
- stage1
- stage2
- stage3
step-1:
stage: stage1
script:
- echo "Can be canceled."
interruptible: true
step-2:
stage: stage2
script:
- echo "Can not be canceled."
step-3:
stage: stage3
script:
- echo "Because step-2 can not be canceled, this step can never be canceled, even though it's set as interruptible."
interruptible: true
上面示例中:
- 如果只有 step-1 執(zhí)行或等待,則停止
- 如果在 step-2 開(kāi)始之后,則不停止
13)needs
:使用 needs
能不依據(jù)順序來(lái)執(zhí)行 jobs
- [] 表示當(dāng) pipeline 創(chuàng)建的時(shí)候,就開(kāi)始執(zhí)行
- [linux: build] 表示在
linux: build
后執(zhí)行
linux:build:
stage: build
script: echo "Building linux..."
mac:build:
stage: build
script: echo "Building mac..."
lint:
stage: test
needs: []
script: echo "Linting..."
linux:rspec:
stage: test
needs: ["linux:build"]
script: echo "Running rspec on linux..."
mac:rspec:
stage: test
needs: ["mac:build"]
script: echo "Running rspec on mac..."
production:
stage: deploy
script: echo "Running production..."
environment: production
needs: artifacts, true / false,控制 job 的 artifacts 是否下載
test-job1:
stage: test
needs:
- job: build_job1 # test-job1 下載 build-job1 的 artifacts
artifacts: true
test-job2:
stage: test
needs:
- job: build_job2 # test-job2 不下載 build-job2 的 artifacts
artifacts: false
test-job3:
needs:
- job: build_job1 # test-job3 下載 3 個(gè) build-job 的所有 artifacts
artifacts: true
- job: build_job2
- build_job3
needs: project,下載某個(gè)項(xiàng)目,某個(gè) job,某個(gè)分支的 artifacts
build_job:
stage: build
script:
- ls -lhR
needs:
- project: namespace/group/project-name
job: build-1
ref: main
artifacts: true
- project: namespace/group/project-name-2
job: build-2
ref: main
artifacts: true
13.3 版本之后,可以使用全局變量來(lái)定義:
build_job:
stage: build
script:
- ls -lhR
needs:
- project: $CI_PROJECT_PATH
job: $DEPENDENCY_JOB_NAME
ref: $ARTIFACTS_DOWNLOAD_REF
artifacts: true
14)only/except
:用來(lái)控制什么時(shí)候?qū)?job 添加到 pipeline
-
only
:定義什么時(shí)候 job 開(kāi)始執(zhí)行 -
except
:定義什么時(shí)候 job 不執(zhí)行 -
only/refs
:基于 branch name 或 pipeline type 來(lái)定義什么時(shí)候 job 開(kāi)始執(zhí)行 -
except/refs
:基于 branch name 或 pipeline type 來(lái)定義什么時(shí)候 job 不執(zhí)行 -
only/variables
:基于 variables 來(lái)定義什么時(shí)候 job 開(kāi)始執(zhí)行 -
except/variables
:基于 variables 來(lái)定義什么時(shí)候 job 不執(zhí)行 -
only:changes
:當(dāng)某些參數(shù)變化時(shí),執(zhí)行 job -
except:changes
:除過(guò)某些參數(shù)變化,才會(huì)執(zhí)行 job
job1:
script: echo
only:
- main
- /^issue-.*$/
- merge_requests
job2:
script: echo
except:
- main
- /^stable-branch.*$/
- schedules
variables 示例:
deploy:
script: cap staging deploy
only:
variables:
- $RELEASE == "staging"
- $STAGING
change 示例:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
only:
refs:
- branches
changes:
- Dockerfile
- docker/scripts/*
- dockerfiles/**/*
- more_scripts/*.{rb,py,sh}
- "**/*.json"
15)pages
:能夠定義一個(gè) gitlab pages,上傳相關(guān)內(nèi)容,在網(wǎng)站上發(fā)布
pages:
stage: deploy
script:
- mkdir .public
- cp -r * .public
- mv .public public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
environment: production
上面的例子,將project 的 root 下所有文件都移到了 public/ 文件夾下
16)parallel
:并行執(zhí)行某個(gè) job N 次
并行創(chuàng)建 5 個(gè) jobs,名字為 test 1/5 到 test 5/5
test:
script: rspec
parallel: 5
parallel: matrix,并行執(zhí)行一個(gè) job,每個(gè)實(shí)例都使用不同的參數(shù)
deploystacks:
stage: deploy
script:
- bin/deploy
parallel:
matrix:
- PROVIDER: aws
STACK:
- monitoring
- app1
- app2
- PROVIDER: ovh
STACK: [monitoring, backup, app]
- PROVIDER: [gcp, vultr]
STACK: [data, processing]
environment: $PROVIDER/$STACK
上面的示例會(huì)生成 10 個(gè)并行的 deploystacks jobs,每個(gè) job 有不同的 PROVIDER 和 STACK:
deploystacks: [aws, monitoring]
deploystacks: [aws, app1]
deploystacks: [aws, app2]
deploystacks: [ovh, monitoring]
deploystacks: [ovh, backup]
deploystacks: [ovh, app]
deploystacks: [gcp, data]
deploystacks: [gcp, processing]
deploystacks: [vultr, data]
deploystacks: [vultr, processing]
17)release
:創(chuàng)建一個(gè)版本
release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG # Run this job when a tag is created manually
script:
- echo "Running the release job."
release:
tag_name: $CI_COMMIT_TAG
name: 'Release $CI_COMMIT_TAG'
description: 'Release created using the release-cli.'
18)resource_group
:創(chuàng)建一個(gè) resource_group,以確保同一項(xiàng)目的 job 在不同 pipeline 之間是互斥的。
19)retry
:配置一個(gè) job 失敗后自動(dòng)重新開(kāi)始的次數(shù),如果沒(méi)有定義的話,默認(rèn)為 0,即不會(huì)自動(dòng)重新開(kāi)始
輸入有三種:0/1/2,默認(rèn)為 0
test:
script: rspec
retry: 2
retry: when,和 retry: max 聯(lián)合使用,當(dāng)某種失敗的時(shí)候(when 后面跟的),retry 的最大次數(shù)
單個(gè)失敗類(lèi)型:
test:
script: rspec
retry:
max: 2
when: runner_system_failure
多種失敗類(lèi)型:
test:
script: rspec
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
19)rules
:用 rules 來(lái)指定 pipeline 中是否包含該 job
rules: if,特定條件下,將 job 添加到 pipeline 中
If an if statement is true, add the job to the pipeline.
If an if statement is true, but it’s combined with when: never, do not add the job to the pipeline.
If no if statements are true, do not add the job to the pipeline.
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
when: never
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/
when: manual
allow_failure: true
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
rules: changes,如果檢測(cè)到特定的文件有變化,則將 job 添加到 pipeline 中
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- Dockerfile
when: manual
allow_failure: true
20)script
:指定需要執(zhí)行的命令,所有的 job(除過(guò) trigger job)以外,都需要 script
關(guān)鍵字
job1:
script: "bundle exec rspec"
job2:
script:
- uname -a
- bundle exec rspec
21)secrets
:秘鑰
22)services
:指定另外的 docker image 來(lái)執(zhí)行腳本
下面示例中,job 使用 Ruby container,然后,又使用另外的 container 來(lái)執(zhí)行 PG
default:
image:
name: ruby:2.6
entrypoint: ["/bin/bash"]
services:
- name: my-postgres:11.7
alias: db-postgres
entrypoint: ["/usr/local/bin/db-postgres"]
command: ["start"]
before_script:
- bundle install
test:
script:
- bundle exec rake spec
23)stage
:定義 job 在哪個(gè)階段運(yùn)行,同一個(gè) stage 中的 job 可以并行執(zhí)行
- 如果沒(méi)有定義 stage,則默認(rèn)該 job 是 test stage
-
.pre
:如果某個(gè) job 的 stage 為.pre
,則該 job 總會(huì)先于所有的 stage 執(zhí)行,不是必須要定義.pre
-
.post
:如果某個(gè) job 的 stage 為.post
,則該 job 會(huì)在其他 stage 的 job 執(zhí)行完成后執(zhí)行,也就是 pipeline 中的最后一個(gè)執(zhí)行的 stage - 如果一個(gè) pipeline 中只包含
.pre
或.post
,則是不會(huì)執(zhí)行的
stages:
- build
- test
- deploy
job1:
stage: build
script:
- echo "This job compiles code."
job2:
stage: test
script:
- echo "This job tests the compiled code. It runs when the build stage completes."
job3:
script:
- echo "This job also runs in the test stage".
job4:
stage: deploy
script:
- echo "This job deploys the code. It runs when the test stage completes."
environment: production
.pre 示例
stages:
- build
- test
job1:
stage: build
script:
- echo "This job runs in the build stage."
first-job:
stage: .pre
script:
- echo "This job runs in the .pre stage, before all other stages."
job2:
stage: test
script:
- echo "This job runs in the test stage."
.post 示例
stages:
- build
- test
job1:
stage: build
script:
- echo "This job runs in the build stage."
last-job:
stage: .post
script:
- echo "This job runs in the .post stage, after all other stages."
job2:
stage: test
script:
- echo "This job runs in the test stage."
24)tags
:從一系列 runners 中指定特定的 runner 來(lái)運(yùn)行 job
下面的例子中,只有 tages 為 ruby 和 postgres 的 runners 可以運(yùn)行 job
job:
tags:
- ruby
- postgres
25)timeout
:指定特定的 job 運(yùn)行的時(shí)間限制,超過(guò)時(shí)間還沒(méi)有完成的話會(huì)失敗
build:
script: build.sh
timeout: 3 hours 30 minutes
test:
script: rspec
timeout: 3h 30m
26)trigger
:用于創(chuàng)建 downstream pipeline,即下游的流水線,包括:
- multi-project pipeline
- child pipeline
trigger(觸發(fā)) jobs 能使用的關(guān)鍵字較少,包括:
- allow_failure.
- extends.
- needs, but not needs:project.
- only and except.
- rules.
- stage.
- trigger.
- variables.
- when (only with a value of on_success, on_failure, or always).
trigger: include,用于聲明一個(gè) job 是 trigger job,且是開(kāi)始了一個(gè) child pipeline
trigger: include: artifact,用于觸發(fā)一個(gè)動(dòng)態(tài) child pipeline
輸入:child pipeline 的 yml 的路徑
trigger-child-pipeline:
trigger:
include: path/to/child-pipeline.gitlab-ci.yml
trigger: project,用于聲明一個(gè) job 是 trigger job,且是開(kāi)始了一個(gè) multi-project pipeline
輸入:下游 project 的路徑
trigger-multi-project-pipeline:
trigger:
project: my-group/my-project
不同 branch 的示例:
trigger-multi-project-pipeline:
trigger:
project: my-group/my-project
branch: development
trigger: strategy,強(qiáng)制讓 trigger job 等待下游 pipeline 全部完成后,再標(biāo)記為 success
default 的設(shè)置:當(dāng)下游 pipeline 開(kāi)始的時(shí)候,本 job 就被標(biāo)記為 success 了
下面的示例中,后面 stage 的 jobs 會(huì)等待被觸發(fā)的 pipeline 全部成功后,才開(kāi)始
trigger_job:
trigger:
include: path/to/child-pipeline.yml
strategy: depend
trigger: forward,指定將什么傳遞到下游 pipeline
輸入:yaml_variables,pipeline_variables
variables: # default variables for each job
VAR: value
# Default behavior:
# - VAR is passed to the child
# - MYVAR is not passed to the child
child1:
trigger:
include: .child-pipeline.yml
# Forward pipeline variables:
# - VAR is passed to the child
# - MYVAR is passed to the child
child2:
trigger:
include: .child-pipeline.yml
forward:
pipeline_variables: true
# Do not forward YAML variables:
# - VAR is not passed to the child
# - MYVAR is not passed to the child
child3:
trigger:
include: .child-pipeline.yml
forward:
yaml_variables: false
27)variables
:是根據(jù)不同 job 可配置的參數(shù),使用關(guān)鍵字 variables 來(lái)創(chuàng)建變量
-
variables: description
:定義 pipeline-level 的變量,該變量在手動(dòng)運(yùn)行時(shí)被預(yù)填充 -
variables: expand
:定義變量是否可擴(kuò)展(true / false)
variables:
DEPLOY_SITE: "https://example.com/"
deploy_job:
stage: deploy
script:
- deploy-script --url $DEPLOY_SITE --path "/"
environment: production
deploy_review_job:
stage: deploy
variables:
REVIEW_PATH: "/review"
script:
- deploy-review-script --url $DEPLOY_SITE --path $REVIEW_PATH
environment: production
variables: description
variables:
DEPLOY_ENVIRONMENT:
description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
value: "staging"
variables: expand
variables:
VAR1: value1
VAR2: value2 $VAR1
VAR3:
value: value3 $VAR1
expand: false
VAR2 的結(jié)果是 value2 value1
VAR3 的結(jié)果是 value3 $VAR1
28)when
:配置 job 運(yùn)行的時(shí)間,如果沒(méi)有定義的話,則默認(rèn)的值為 when: on_succes
可能的輸入:
- on_success (default): Run the job only when all jobs in earlier stages succeed or have allow_failure: true.
- manual: Run the job only when triggered manually.
- always: Run the job regardless of the status of jobs in earlier stages. Can also be used in workflow:rules.
- on_failure: Run the job only when at least one job in an earlier stage fails.
- delayed: Delay the execution of a job for a specified duration.
- never: Don’t run the job. Can only be used in a rules section or workflow: rules.
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
environment: production
cleanup_job:
stage: cleanup
script:
- cleanup after jobs
when: always
上面的實(shí)例中:
- 當(dāng)
build_job
失敗時(shí),會(huì)執(zhí)行cleanup_build_job
- 無(wú)論失敗還是成功,都會(huì)在 pipeline 的最后一步執(zhí)行
cleanup_job
- 當(dāng)手動(dòng)在 gitlab UI 中執(zhí)行
deploy_job
時(shí),該 job 才會(huì)被執(zhí)行
29)在全局設(shè)置中已經(jīng)棄用的關(guān)鍵字
image, services, cache, before_script, after_script
如果要使用的話,要使用 default
:
default:
image: ruby:3.0
services:
- docker:dind
cache:
paths: [vendor/]
before_script:
- bundle config set path vendor/bundle
- bundle install
after_script:
- rm -rf tmp/
2.2 GitLab Runner
官方文檔
當(dāng)在項(xiàng)目的根目錄添加了 .gitlab-ci.yml
后,在每次提交的時(shí)候,gitlab 就能自動(dòng)檢測(cè)到需要進(jìn)行 CI,就會(huì)調(diào)用 GitLab Runner 來(lái)執(zhí)行 Job 中定義的 scripts(也就是腳本,即需要執(zhí)行的東西)
GitLab Runner 是一個(gè)開(kāi)源項(xiàng)目,用于運(yùn)行您的作業(yè)并將結(jié)果發(fā)送回 GitLab。它與 GitLab CI 一起使用,GitLab CI 是 GitLab 隨附的開(kāi)源持續(xù)集成服務(wù),用于協(xié)調(diào)作業(yè)。
GitLab Runner 是用 Go 編寫(xiě),可以作為單個(gè)二進(jìn)制文件運(yùn)行,不需要語(yǔ)言特定的要求,能夠運(yùn)行在目前常用的平臺(tái)上,例如:
- Linux/Unix
- Windows
- MacOS
- Kubernetes
GitLab Runner 的三種類(lèi)型:
- shared:運(yùn)行整個(gè)平臺(tái)項(xiàng)目的 job (gitlab)
- group:運(yùn)行特定group下的所有項(xiàng)目的 job (group)
- specific:運(yùn)行指定的項(xiàng)目 job (project)
GitLab Runner 兩種狀態(tài):
- locked:無(wú)法運(yùn)行項(xiàng)目作業(yè)
- paused:不會(huì)運(yùn)行作業(yè)
GitLab Runner 安裝(這里只介紹使用 docker 的方式):
$ mkdir -p /data/gitlab-runner/config
$ docker run -itd --restart=always --name gitlab-runner \
-v /data/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
$ docker exec -it gitlab-runner bash
root@24dc60abee0b:/# gitlab-runner -v
Version: 13.8.0
Git revision: 775dd39d
Git branch: 13-8-stable
GO version: go1.13.8
Built: 2021-01-20T13:32:47+0000
OS/Arch: linux/amd64
Runner 的注冊(cè):
- 將Runner在選擇的機(jī)器上安裝好了以后,需要將 Runner 注冊(cè)到你部署的 Gitlab 上,這樣 Gitlab 才能知道有多少管理的 Runner,同時(shí) Runner 也能根據(jù) CI/CD 里的配置來(lái)選擇自己對(duì)應(yīng)的任務(wù)去執(zhí)行。
- 如果使用 docker 安裝,則注冊(cè)的時(shí)候也要進(jìn)入 docker 容器里邊進(jìn)行
- runner 注冊(cè)完成后會(huì)在 /etc/gitlab-runner 目錄下生成一個(gè) config.toml 的文件。這個(gè)就是 runner 的配置文件
- 注冊(cè)完成后 gitlab UI 能夠查看注冊(cè)的 runner
docker exec -it gitlab-runner bash
gitlab-runner register
執(zhí)行器(Executor):
- Runner 根據(jù) CI/CD 上的配置選擇自己對(duì)應(yīng)的任務(wù),將任務(wù)內(nèi)容讀取到它所在的機(jī)器上。但是實(shí)際執(zhí)行任務(wù)的并不是 Runner,它只負(fù)責(zé)取任務(wù)并在任務(wù)執(zhí)行成功或者失敗的時(shí)候,返回對(duì)應(yīng)的結(jié)果。
- 實(shí)際執(zhí)行任務(wù)的是執(zhí)行器(Executor),執(zhí)行器是一個(gè)造出來(lái)的概念,實(shí)際上就是機(jī)器上的 shell,例如 linux 上的 bash shell、Windows 上的 PowerShell 等。
- 在 CI/CD 的任務(wù)里面,無(wú)非也都是代碼編譯、打包,而編譯打包的命令都來(lái)自 shell 環(huán)境。而在注冊(cè) Runner 的時(shí)候,會(huì)要求你為這個(gè) Runner 選擇一個(gè)執(zhí)行器,即這個(gè) Runner 可以提供一個(gè)什么樣的 shell 環(huán)境讓你運(yùn)行命令。因此 Bash Shell 類(lèi)型的 Runner 只能運(yùn)行 bash 命令,如果你給它傳一個(gè) powershell 的命令,就直接報(bào)錯(cuò)。
Runner 的執(zhí)行流程:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-765206.html
- Runner向/api/v4/runners 發(fā)送 POST 請(qǐng)求,請(qǐng)求里帶有注冊(cè) Token
- 注冊(cè)成功后返回 runner_token
- Runner 通過(guò)循環(huán)向 /api/v4/rquest 發(fā)送 POST 請(qǐng)求,請(qǐng)求里帶上 runner_token
- 認(rèn)證通過(guò)后接口返回帶有任務(wù)信息的 payload 和任務(wù)相關(guān)的 job_token
- 然后將任務(wù)信息發(fā)送給執(zhí)行器,執(zhí)行器使用 job_token來(lái)克隆所需的代碼,下載配置或組件
- 執(zhí)行器執(zhí)行完成后,返回任務(wù)輸出和任務(wù)狀態(tài)信息
- Runner 向 GitLab 返回任務(wù)輸出、任務(wù)狀態(tài)以及 job_token
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-765206.html
到了這里,關(guān)于【git】2、gitlab CICD 模型部署自動(dòng)化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!