GitLabPipeline語法


流水線語法檢測

GitLab CI的每個實例都有一個稱為Lint的嵌入式調試工具,該工具可以驗證.gitlab-ci.yml文件的內容.

流水線參數列表

Keyword Description
script 運行的Shell命令或腳本。
image 使用docker映像.
services 使用docker服務映像.
before_script 在作業運行前運行腳本。
after_script 在作業運行后運行腳本。
stages 定義管道中的階段,運行順序。
stage 為工作定義一個階段,可選,未指定默認為test階段。
only 限制創建作業的時間.
except 限制未創建作業的時間.
rules 條件列表,用於評估和確定作業的選定屬性,以及是否創建該作業.
allow_failure 允許作業失敗. 失敗的工作不會影響提交狀態.
when 什么時候開始工作.
environment 作業部署到的環境的名稱.
cache 在后續運行之間應緩存的文件列表.
artifacts 成功時附加到作業的文件和目錄列表.
dependencies 通過提供要從中獲取工件的作業列表,限制將哪些工件傳遞給特定作業.
coverage 給定作業的代碼覆蓋率設置.
retry 發生故障時可以自動重試作業的時間和次數。
timeout 定義自定義作業級別的超時,該超時優先於項目范圍的設置。
parallel 多少個作業實例應並行運行.
trigger 定義下游管道觸發器.
include 允許此作業包括外部YAML文件.
extends 該作業將要繼承的配置條目.
pages 上載作業結果以用於GitLab頁面.
variables 在作業級別上定義作業變量.
interruptible 定義在通過新的運行使其冗余時是否可以取消作業.
resource_group 限制作業並發.

job/script/before_script/after_script/stages/stage/variables

job

在每個項目中,我們使用名為.gitlab-ci.yml的YAML文件配置GitLab CI / CD 管道。

這里在pipeline中定義了兩個作業,每個作業運行不同的命令。命令可以是shell或腳本。

job1:
  script: "execute-script-for-job1"

job2:
  script: "execute-script-for-job2"
  • 可以定義一個或多個作業(job)。
  • 每個作業必須具有唯一的名稱(不能使用關鍵字)。
  • 每個作業是獨立執行的。
  • 每個作業至少要包含一個script。

script

job:
  script:
    - uname -a
    - bundle exec rspec

注意:有時, script命令將需要用單引號或雙引號引起來. 例如,包含冒號命令( : )需要加引號,以便被包裹的YAML解析器知道來解釋整個事情作為一個字符串,而不是一個”鍵:值”對. 使用特殊字符時要小心: :{}[],&*#?|-<>= !%@ .


before_script

用於定義一個命令,該命令在每個作業之前運行。必須是一個數組。指定的script與主腳本中指定的任何腳本串聯在一起,並在單個shell中一起執行。

after_script

用於定義將在每個作業(包括失敗的作業)之后運行的命令。這必須是一個數組。指定的腳本在新的shell中執行,與任何before_scriptscript腳本分開。

可以在全局定義,也可以在job中定義。在job中定義會覆蓋全局。

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com

stages:
  - build
  - deploy
 

build:
  before_script:
    - echo "before-script in job"
  stage: build
  script:
    - echo "mvn clean "
    - echo "mvn install"
  after_script:
    - echo "after script in job"


deploy:
  stage: deploy
  script:
    - echo "hello deploy"
    
after_script:
  - echo "after-script"

after_script失敗不會影響作業失敗。

before_script失敗導致整個作業失敗,其他作業將不再執行。作業失敗不會影響after_script運行。


stages

用於定義作業可以使用的階段,並且是全局定義的。同一階段的作業並行運行,不同階段按順序執行。

stages:
  - build
  - test
  - deploy

這里定義了三個階段,首先build階段並行運行,然后test階段並行運行,最后deploy階段並行運行。deploy階段運行成功后將提交狀態標記為passed狀態。如果任何一個階段運行失敗,最后提交狀態為failed。

未定義stages

全局定義的stages是來自於每個job。如果job沒有定義stage則默認是test階段。如果全局未定義stages,則按順序運行 build,test,deploy。

如果作業中定義了其他階段,例如”codescan”則會出現錯誤。原因是因為除了build test deploy階段外的其他階段作為.pre運行(也就是作為第一個階段運行,需要將此作業的stage指定為.pre)。

codescan:
  stage: .pre
  script:
    - echo "codescan"

定義stages控制stage運行順序

一個標准的yaml文件中是需要定義stages,可以幫助我們對每個stage進行排序。

stages:
  - build
  - test
  - codescan
  - deploy

.pre & .post

.pre始終是整個管道的第一個運行階段,.post始終是整個管道的最后一個運行階段。 用戶定義的階段都在兩者之間運行。.pre.post的順序無法更改。如果管道僅包含.pre.post階段的作業,則不會創建管道。


stage

是按JOB定義的,並且依賴於全局定義的stages 。 它允許將作業分為不同的階段,並且同一stage作業可以並行執行(取決於特定條件 )。

unittest:
  stage: test
  script:
    - echo "run test"
    
interfacetest:
  stage: test
  script:
    - echo "run test"

可能遇到的問題: 階段並沒有並行運行。

在這里我把這兩個階段在同一個runner運行了,所以需要修改runner每次運行的作業數量。默認是1,改為10.

vim /etc/gitlab-runner/config.toml 更改后自動加載無需重啟。

concurrent = 10

variables

定義變量,pipeline變量、job變量、Runner變量。job變量優先級最大。

變量具體用法示例:
.gitlab-ci.yml文件中設置的變量會覆蓋下面設置的變量




綜合實例

綜合實例:

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com
  
stages:
  - build
  - test
  - codescan
  - deploy

build:
  before_script:
    - echo "before-script in job"
  stage: build
  script:
    - echo "mvn clean "
    - echo "mvn install"
    - echo "$DOMAIN"
  after_script:
    - echo "after script in buildjob"

unittest:
  stage: test
  script:
    - echo "run test"

deploy:
  stage: deploy
  script:
    - echo "hello deploy"
    - sleep 2;
  
codescan:
  stage: codescan
  script:
    - echo "codescan"
    - sleep 5;
 
after_script:
  - echo "after-script"
  - ech

實驗效果

可能遇到的問題: pipeline卡主,為降低復雜性目前沒有學習tags,所以流水線是在共享的runner中運行的。需要設置共享的runner運行沒有tag的作業。

tags/allow_failure/when/retry/timeout/parallel

tags

用於從允許運行該項目的所有Runner列表中選擇特定的Runner,在Runner注冊期間,您可以指定Runner的標簽。

tags可讓您使用指定了標簽的runner來運行作業,此runner具有ruby和postgres標簽。

job:
  tags:
    - ruby
    - postgres

給定帶有osx標簽的OS X Runner和帶有windows標簽的Windows Runner,以下作業將在各自的平台上運行。

windows job:
  stage:
    - build
  tags:
    - windows
  script:
    - echo Hello, %USERNAME%!

osx job:
  stage:
    - build
  tags:
    - osx
  script:
    - echo "Hello, $USER!"


allow_failure

allow_failure允許作業失敗,默認值為false 。啟用后,如果作業失敗,該作業將在用戶界面中顯示橙色警告. 但是,管道的邏輯流程將認為作業成功/通過,並且不會被阻塞。 假設所有其他作業均成功,則該作業的階段及其管道將顯示相同的橙色警告。但是,關聯的提交將被標記為”通過”,而不會發出警告。

job1:
  stage: test
  script:
    - execute_script_that_will_fail
  allow_failure: true


when

on_success前面階段中的所有作業都成功(或由於標記為allow_failure而被視為成功)時才執行作業。 這是默認值。

on_failure當前面階段出現失敗則執行。

always -執行作業,而不管先前階段的作業狀態如何,放到最后執行。總是執行。

manual 手動

manual -手動執行作業,不會自動執行,需要由用戶顯式啟動. 手動操作的示例用法是部署到生產環境. 可以從管道,作業,環境和部署視圖開始手動操作。

此時在deploy階段添加manual,則流水線運行到deploy階段為鎖定狀態,需要手動點擊按鈕才能運行deploy階段。

delayed 延遲

delayed 延遲一定時間后執行作業(在GitLab 11.14中已添加)。

有效值'5',10 seconds,30 minutes, 1 day, 1 week

實驗demo

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com
  
stages:
  - build
  - test
  - codescan
  - deploy

build:
  before_script:
    - echo "before-script in job"
  stage: build
  script:
    - echo "mvn clean "
    - echo "mvn install"
    - echo "$DOMAIN"
  after_script:
    - echo "after script in buildjob"

unittest:
  stage: test
  script:
    - ech "run test"
  when: delayed
  start_in: '30'
  allow_failure: true
  

deploy:
  stage: deploy
  script:
    - echo "hello deploy"
    - sleep 2;
  when: manual
  
codescan:
  stage: codescan
  script:
    - echo "codescan"
    - sleep 5;
  when: on_success
 
after_script:
  - echo "after-script"
  - ech
  

retry

配置在失敗的情況下重試作業的次數。

當作業失敗並配置了retry ,將再次處理該作業,直到達到retry關鍵字指定的次數。如果retry設置為2,並且作業在第二次運行成功(第一次重試),則不會再次重試. retry值必須是一個正整數,等於或大於0,但小於或等於2(最多兩次重試,總共運行3次).

unittest:
  stage: test
  retry: 2
  script:
    - ech "run test"

默認情況下,將在所有失敗情況下重試作業。為了更好地控制retry哪些失敗,可以是具有以下鍵的哈希值:

  • max :最大重試次數.
  • when :重試失敗的案例.

根據錯誤原因設置重試的次數。

always :在發生任何故障時重試(默認).
unknown_failure :當失敗原因未知時。
script_failure :腳本失敗時重試。
api_failure :API失敗重試。
stuck_or_timeout_failure :作業卡住或超時時。
runner_system_failure :運行系統發生故障。
missing_dependency_failure: 如果依賴丟失。
runner_unsupported :Runner不受支持。
stale_schedule :無法執行延遲的作業。
job_execution_timeout :腳本超出了為作業設置的最大執行時間。
archived_failure :作業已存檔且無法運行。
unmet_prerequisites :作業未能完成先決條件任務。
scheduler_failure :調度程序未能將作業分配給運行scheduler_failure。
data_integrity_failure :檢測到結構完整性問題。

實驗

定義當出現腳本錯誤重試兩次,也就是會運行三次。

unittest:
  stage: test
  tags:
    - build
  only:
    - master
  script:
    - ech "run test"
  retry:
    max: 2
    when:
      - script_failure

效果


timeout 超時

特定作業配置超時,作業級別的超時可以超過項目級別的超時,但不能超過Runner特定的超時。

build:
  script: build.sh
  timeout: 3 hours 30 minutes

test:
  script: rspec
  timeout: 3h 30m

項目設置流水線超時時間

超時定義了作業可以運行的最長時間(以分鍾為單位)。 這可以在項目的“設置”>” CI / CD”>“常規管道”設置下進行配置 。 默認值為60分鍾。

runner超時時間

此類超時(如果小於項目定義的超時 )將具有優先權。此功能可用於通過設置大超時(例如一個星期)來防止Shared Runner被項目占用。未配置時,Runner將不會覆蓋項目超時。

此功能如何工作:

示例1-運行程序超時大於項目超時

runner超時設置為24小時,項目的CI / CD超時設置為2小時。該工作將在2小時后超時。

示例2-未配置運行程序超時

runner不設置超時時間,項目的CI / CD超時設置為2小時。該工作將在2小時后超時。

示例3-運行程序超時小於項目超時

runner超時設置為30分鍾,項目的CI / CD超時設置為2小時。工作在30分鍾后將超時


parallel

配置要並行運行的作業實例數,此值必須大於或等於2並且小於或等於50。

這將創建N個並行運行的同一作業實例. 它們從job_name 1/Njob_name N/N依次命名。

codescan:
  stage: codescan
  tags:
    - build
  only:
    - master
  script:
    - echo "codescan"
    - sleep 5;
  parallel: 5


綜合實例

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com
  
stages:
  - build
  - test
  - codescan
  - deploy

build:
  before_script:
    - echo "before-script in job"
  stage: build
  script:
    - echo "mvn clean "
    - echo "mvn install"
    - echo "$DOMAIN"
  after_script:
    - echo "after script in buildjob"

unittest:
  stage: test
  script:
    - ech "run test"
  when: delayed
  start_in: '5'
  allow_failure: true
  retry:
    max: 1
    when:
      - script_failure
  timeout: 1 hours 10 minutes
  
  

deploy:
  stage: deploy
  script:
    - echo "hello deploy"
    - sleep 2;
  when: manual
  
codescan:
  stage: codescan
  script:
    - echo "codescan"
    - sleep 5;
  when: on_success
  parallel: 5
 
after_script:
  - echo "after-script"
  - ech

only/except/rules/workflow

only & except

only和except是兩個參數用分支策略來限制jobs構建:

  1. only定義哪些分支和標簽的git項目將會被job執行。

  2. except定義哪些分支和標簽的git項目將不會被job執行。

    job:
    # use regexp
    only:
    - /^issue-.*$/
    # use special keyword
    except:
    - branches
    

rules

rules允許按順序評估單個規則對象的列表,直到一個匹配並為作業動態提供屬性. 請注意, rules不能only/exceptonly/except組合使用。

可用的規則條款包括:

rules:if

如果DOMAIN的值匹配,則需要手動運行。不匹配on_success。 條件判斷從上到下,匹配即停止。多條件匹配可以使用&& ||

variables:
  DOMAIN: example.com

codescan:
  stage: codescan
  tags:
    - build
  script:
    - echo "codescan"
    - sleep 5;
  #parallel: 5
  rules:
    - if: '$DOMAIN == "example.com"'
      when: manual
    - when: on_success

rules:changes

接受文件路徑數組。 如果提交中Jenkinsfile文件發生的變化則為true。

codescan:
  stage: codescan
  tags:
    - build
  script:
    - echo "codescan"
    - sleep 5;
  #parallel: 5
  rules:
    - changes:
      - Jenkinsfile
      when: manual
    - if: '$DOMAIN == "example.com"'
      when: on_success
    - when: on_success

rules:exists

接受文件路徑數組。當倉庫中存在指定的文件時操作。

codescan:
  stage: codescan
  tags:
    - build
  script:
    - echo "codescan"
    - sleep 5;
  #parallel: 5
  rules:
    - exists:
      - Jenkinsfile
      when: manual 
    - changes:
      - Jenkinsfile
      when: on_success
    - if: '$DOMAIN == "example.com"'
      when: on_success
    - when: on_success

rules:allow_failure

使用allow_failure: true rules:在不停止管道本身的情況下允許作業失敗或手動作業等待操作.

job:
  script: "echo Hello, Rules!"
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
      when: manual
      allow_failure: true

在此示例中,如果第一個規則匹配,則作業將具有以下when: manualallow_failure: true


workflow:rules

頂級workflow:關鍵字適用於整個管道,並將確定是否創建管道。when :可以設置為alwaysnever . 如果未提供,則默認值always

variables:
  DOMAIN: example.com

workflow:
  rules:
    - if: '$DOMAIN == "example.com"'
    - when: always

綜合實例

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com
  
workflow:
  rules:
    - if: '$DOMAIN == "example.com"'
      when: always
    - when: never
    
stages:
  - build
  - test
  - codescan
  - deploy

build:
  before_script:
    - echo "before-script in job"
  stage: build
  script:
    - echo "mvn clean "
    - echo "mvn install"
    - ech "$DOMAIN"
  after_script:
    - echo "after script in buildjob"
  rules:
    - exists:
      - Dockerfile
      when: on_success 
      allow_failure: true

    - changes:
      - Dockerfile
      when: manual
    - when: on_failure

unittest:
  stage: test
  script:
    - ech "run test"
  when: delayed
  start_in: '5'
  allow_failure: true
  retry:
    max: 1
    when:
      - script_failure
  timeout: 1 hours 10 minutes
  
  

deploy:
  stage: deploy
  script:
    - echo "hello deploy"
    - sleep 2;
  rules:
    - if: '$DOMAIN == "example.com"'
      when: manual
    - if: '$DOMAIN == "aexample.com"'
      when: delayed
      start_in: '5'
    - when: on_failure
  
codescan:
  stage: codescan
  script:
    - echo "codescan"
    - sleep 5;
  when: on_success
  parallel: 5
 
after_script:
  - echo "after-script"
  - ech

cache

cache 緩存

用來指定需要在job之間緩存的文件或目錄。只能使用該項目工作空間內的路徑。不要使用緩存在階段之間傳遞工件,因為緩存旨在存儲編譯項目所需的運行時依賴項。

如果在job范圍之外定義了cache ,則意味着它是全局設置,所有job都將使用該定義。如果未全局定義或未按job定義則禁用該功能。

cache:paths

使用paths指令選擇要緩存的文件或目錄,路徑是相對於項目目錄,不能直接鏈接到項目目錄之外。

$CI_PROJECT_DIR 項目目錄

在job build中定義緩存,將會緩存target目錄下的所有.jar文件。

build:
  script: test
  cache:
    paths:
      - target/*.jar

當在全局定義了cache:paths會被job中覆蓋。以下實例將緩存binaries目錄。

cache:
  paths:
    - my/files

build:
  script: echo "hello"
  cache:
    key: build
    paths:
      - target/

由於緩存是在job之間共享的,如果不同的job使用不同的路徑就出現了緩存覆蓋的問題。如何讓不同的job緩存不同的cache呢?設置不同的cache:key


cache:key 緩存標記

為緩存做個標記,可以配置job、分支為key來實現分支、作業特定的緩存。為不同 job 定義了不同的 cache:key 時, 會為每個 job 分配一個獨立的 cache。cache:key變量可以使用任何預定義變量,默認default ,從GitLab 9.0開始,默認情況下所有內容都在管道和作業之間共享。

按照分支設置緩存

cache:
  key: ${CI_COMMIT_REF_SLUG}

files: 文件發生變化自動重新生成緩存(files最多指定兩個文件),提交的時候檢查指定的文件。

根據指定的文件生成密鑰計算SHA校驗和,如果文件未改變值為default。

cache:
  key:
    files:
      - Gemfile.lock
      - package.json
  paths:
    - vendor/ruby
    - node_modules

prefix: 允許給定prefix的值與指定文件生成的秘鑰組合。

在這里定義了全局的cache,如果文件發生變化則值為 rspec-xxx111111111222222 ,未發生變化為rspec-default。

cache:
  key:
    files:
      - Gemfile.lock
    prefix: ${CI_JOB_NAME}
  paths:
    - vendor/ruby

rspec:
  script:
    - bundle exec rspec

例如,添加$CI_JOB_NAME prefix將使密鑰看起來像: rspec-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5 ,並且作業緩存在不同分支之間共享,如果分支更改了Gemfile.lock ,則該分支將為cache:key:files具有新的SHA校驗和. 將生成一個新的緩存密鑰,並為該密鑰創建一個新的緩存. 如果Gemfile.lock未發生變化 ,則將前綴添加default ,因此示例中的鍵為rspec-default


cache:policy 策略

默認:在執行開始時下載文件,並在結束時重新上傳文件。稱為” pull-push緩存策略.

policy: pull 跳過下載步驟

policy: push 跳過上傳步驟

stages:
  - setup
  - test

prepare:
  stage: setup
  cache:
    key: gems
    paths:
      - vendor/bundle
  script:
    - bundle install --deployment

rspec:
  stage: test
  cache:
    key: gems
    paths:
      - vendor/bundle
    policy: pull
  script:
    - bundle exec rspec ...

綜合實例(一) 全局緩存

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com

cache: 
  paths:
   - target/

stages:
  - build
  - test
  - deploy
  
build:
  before_script:
    - echo "before-script in job"
  stage: build
  tags:
    - build
  only:
    - master
  script:
    - ls
    - id
    - mvn clean package -DskipTests
    - ls target
    - echo "$DOMAIN"
    - false && true ; exit_code=$?
    - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
    - sleep 2;
  after_script:
    - echo "after script in job"


unittest:
  stage: test
  tags:
    - build
  only:
    - master
  script:
    - echo "run test"
    - echo 'test' >> target/a.txt
    - ls target
  retry:
    max: 2
    when:
      - script_failure
  
deploy:
  stage: deploy
  tags:
    - build
  only:
    - master
  script:
    - echo "run deploy"
    - ls target
  retry:
    max: 2
    when:
      - script_failure
      

after_script:
  - echo "after-script"

Pipeline日志分析

build作業運行時會對項目代碼打包,然后生成target目錄。作業結束創建緩存。

開始第二個作業test,此時會把當前目錄中的target目錄刪除掉(因為做了git 對比)。

獲取到第一個作業生成的緩存target目錄。

開始第三個作業,同樣先刪除了target目錄,然后獲取了第二個作業的緩存。最后生成了當前的緩存。


Runner緩存

在做本次實驗的時候我現在本地runner清除了項目的工作目錄和歷史緩存。

[root@zeyang-nuc-service ~]# cd /home/gitlab-runner/builds/1Cxihk7-/0/demo/demo-maven-service/
[root@zeyang-nuc-service demo-maven-service]# ls
Jenkinsfile  README.md  aaaaa  jenkins  pom.xml  src  target
[root@zeyang-nuc-service demo-maven-service]# cd ..
[root@zeyang-nuc-service demo]# ls
demo-maven-service  demo-maven-service.tmp
[root@zeyang-nuc-service demo]# rm -fr demo-maven-service
[root@zeyang-nuc-service demo]# rm -fr demo-maven-service.tmp/
[root@zeyang-nuc-service demo]# cd
[root@zeyang-nuc-service ~]# cd /home/gitlab-runner/cache/
[root@zeyang-nuc-service cache]# ls
demo
[root@zeyang-nuc-service cache]# rm -rf *

項目代碼默認不會刪除,可以發現是第二次作業的緩存。(因為上面的例子中第三次作業並沒有修改緩存內容)

[root@zeyang-nuc-service cache]# cd /home/gitlab-runner/builds/1Cxihk7-/0/demo/demo-maven-service/
[root@zeyang-nuc-service demo-maven-service]# ls
Jenkinsfile  README.md  aaaaa  jenkins  pom.xml  src  target
[root@zeyang-nuc-service demo-maven-service]# cd ..
[root@zeyang-nuc-service demo]# ls
demo-maven-service  demo-maven-service.tmp
[root@zeyang-nuc-service demo]# rm -fr *
[root@zeyang-nuc-service demo]# ls
[root@zeyang-nuc-service demo]# ls
demo-maven-service  demo-maven-service.tmp
[root@zeyang-nuc-service demo]# cd demo-maven-service
[root@zeyang-nuc-service demo-maven-service]# ls
Jenkinsfile  README.md  aaaaa  jenkins  pom.xml  src  target
[root@zeyang-nuc-service demo-maven-service]# cat target/a.txt
test

進入runner緩存目錄中查看緩存。

[root@zeyang-nuc-service ~]# cd /home/gitlab-runner/cache/demo/demo-maven-service/default/
[root@zeyang-nuc-service default]# ls
cache.zip
[root@zeyang-nuc-service default]# unzip cache.zip
Archive:  cache.zip
   creating: target/
  inflating: target/a.txt
   creating: target/classes/
   creating: target/classes/com/
   creating: target/classes/com/mycompany/
   creating: target/classes/com/mycompany/app/
  inflating: target/classes/com/mycompany/app/App.class
   creating: target/maven-archiver/
  inflating: target/maven-archiver/pom.properties
   creating: target/maven-status/
   creating: target/maven-status/maven-compiler-plugin/
   creating: target/maven-status/maven-compiler-plugin/compile/
   creating: target/maven-status/maven-compiler-plugin/compile/default-compile/
  inflating: target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  inflating: target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
   creating: target/maven-status/maven-compiler-plugin/testCompile/
   creating: target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/
  inflating: target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
  inflating: target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
  inflating: target/my-app-1.1-SNAPSHOT.jar
   creating: target/test-classes/
   creating: target/test-classes/com/
   creating: target/test-classes/com/mycompany/
   creating: target/test-classes/com/mycompany/app/
  inflating: target/test-classes/com/mycompany/app/AppTest.class
[root@zeyang-nuc-service default]# ls
cache.zip  target
[root@zeyang-nuc-service default]# cd target/
[root@zeyang-nuc-service target]# ls
a.txt  classes  maven-archiver  maven-status  my-app-1.1-SNAPSHOT.jar  test-classes
[root@zeyang-nuc-service target]# cat a.txt
test

此時此刻再次運行流水線作業,第一個作業用的是上個作業最后生成的緩存。

進入runner緩存目錄查看,cache.zip時間已經發生的變化。

[root@zeyang-nuc-service default]# ll
total 12
-rw------- 1 gitlab-runner gitlab-runner 9172 Apr 29 10:27 cache.zip
drwxrwxr-x 6 root          root           127 Apr 29 10:05 target

結論: 全局緩存生效於未在作業中定義緩存的所有作業,這種情況如果每個作業都對緩存目錄做了更改,會出現緩存被覆蓋的場景。


綜合實例(二)

控制緩存策略

例如build階段我們需要生成新的target目錄內容,可以優化設置job運行時不下載緩存。

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com

cache: 
  paths:
   - target/

stages:
  - build
  - test
  - deploy
  
build:
  before_script:
    - echo "before-script in job"
  stage: build
  tags:
    - build
  only:
    - master
  script:
    - ls
    - id
    - cat target/a.txt
    - mvn clean package -DskipTests
    - ls target
    - echo "$DOMAIN"
    - false && true ; exit_code=$?
    - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
    - sleep 2;
  after_script:
    - echo "after script in job"
  cache:
    policy: pull   #不下載緩存


unittest:
  stage: test
  tags:
    - build
  only:
    - master
  script:
    - echo "run test"
    - echo 'test' >> target/a.txt
    - ls target
    - cat target/a.txt
  retry:
    max: 2
    when:
      - script_failure
  
deploy:
  stage: deploy
  tags:
    - build
  only:
    - master
  script:
    - cat target/a.txt
    - echo "run deploy"
    - ls target
    - echo "deploy" >> target/a.txt
  retry:
    max: 2
    when:
      - script_failure
      

after_script:
  - echo "after-script"
  
  

artifacts/dependencies

artifacts

用於指定在作業成功或者失敗時應附加到作業的文件或目錄的列表。作業完成后,工件將被發送到GitLab,並可在GitLab UI中下載。

artifacts:paths

路徑是相對於項目目錄的,不能直接鏈接到項目目錄之外。

將制品設置為target目錄

artifacts:
  paths:
    - target/

禁用工件傳遞

job:
  stage: build
  script: make build
  dependencies: []

您可能只想為標記的發行版創建構件,以避免用臨時構建構件填充構建服務器存儲。僅為標簽創建工件( default-job不會創建工件):

default-job:
  script:
    - mvn test -U
  except:
    - tags

release-job:
  script:
    - mvn package -U
  artifacts:
    paths:
      - target/*.war
  only:
    - tags

artifacts:expose_as

關鍵字expose_as可用於在合並請求 UI中公開作業工件。

例如,要匹配單個文件:

test:
  script: 
    - echo 1
  artifacts:
    expose_as: 'artifact 1'
    paths: 
      - path/to/file.txt

使用此配置,GitLab將在指向的相關合並請求中添加鏈接file1.txt

制品瀏覽

請注意以下幾點:

  • 每個合並請求最多可以公開10個作業工件。
  • 如果指定了目錄,那么如果目錄中有多個文件,則該鏈接將指向指向作業工件瀏覽器。
  • 如果開啟GitlabPages可以對.html .htm .txt .json .log擴展名單個文件工件渲染工件。

artifacts:name

通過name指令定義所創建的工件存檔的名稱。可以為每個檔案使用唯一的名稱。 artifacts:name變量可以使用任何預定義變量。默認名稱是artifacts,下載artifacts改為artifacts.zip

使用當前作業的名稱創建檔案

job:
  artifacts:
    name: "$CI_JOB_NAME"
    paths:
      - binaries/

使用內部分支或標記的名稱(僅包括binaries目錄)創建檔案,

job:
  artifacts:
    name: "$CI_COMMIT_REF_NAME"
    paths:
      - binaries/

使用當前作業的名稱和當前分支或標記(僅包括二進制文件目錄)創建檔案

job:
  artifacts:
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
    paths:
      - binaries/

要創建一個具有當前階段名稱和分支名稱的檔案

job:
  artifacts:
    name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME"
    paths:
      - binaries/

artifacts:when

用於在作業失敗時或盡管失敗而上傳工件。on_success僅在作業成功時上載工件。這是默認值。on_failure僅在作業失敗時上載工件。always 上載工件,無論作業狀態如何。

要僅在作業失敗時上傳工件:

job:
  artifacts:
    when: on_failure

artifacts:expire_in

制品的有效期,從上傳和存儲到GitLab的時間開始算起。如果未定義過期時間,則默認為30天。

expire_in的值以秒為單位的經過時間,除非提供了單位。可解析值的示例:

‘42’
‘3 mins 4 sec’
‘2 hrs 20 min’
‘2h20min’
‘6 mos 1 day’
‘47 yrs 6 mos and 4d’
‘3 weeks and 2 days’

一周后過期

job:
  artifacts:
    expire_in: 1 week

artifacts:reports

用於從作業中收集測試報告,代碼質量報告和安全報告. 在GitLab的UI中顯示這些報告。

注意:無論作業結果(成功或失敗),都將收集測試報告。

artifacts:reports:junit

收集junit單元測試報告,收集的JUnit報告將作為工件上傳到GitLab,並將自動顯示在合並請求中。

build:
  stage: build
  tags:
    - build
  only:
    - master
  script:
    - mvn test
    - mvn cobertura:cobertura
    - ls target
  artifacts:
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
    when: on_success
    expose_as: 'artifact 1'
    paths:
      - target/*.jar
    reports:
      junit: target/surefire-reports/TEST-*.xml

注意:如果您使用的JUnit工具導出到多個XML文件,則可以在一個作業中指定多個測試報告路徑,它們將被自動串聯到一個文件中. 使用文件名模式( junit: rspec-*.xml ),文件名數組( junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml] )或其組合( junit: [rspec.xml, test-results/TEST-*.xml] )。

如果無法顯示此頁面,需要更改系統設置。此選項可能會加大資源占用,默認禁用了需要啟用。

登錄gitlab
su -  git
$ gitlab-rails console
--------------------------------------------------------------------------------
 GitLab:       12.9.0 (9a382ff2c82) FOSS
 GitLab Shell: 12.0.0
 PostgreSQL:   10.12
--------------------------------------------------------------------------------
Feature.enable(:junit_pipeline_view)Loading production environment (Rails 6.0.2)
irb(main):001:0>
irb(main):002:0>
irb(main):003:0> Feature.enable(:junit_pipeline_view)
=> true
irb(main):004:0>

參考鏈接:https://docs.gitlab.com/ee/ci/junit_test_reports.html


artifacts:reports:cobertura

收集的Cobertura覆蓋率報告將作為工件上傳到GitLab,並在合並請求中自動顯示。

build:
  stage: build
  tags:
    - build
  only:
    - master
  script:
    - mvn test
    - mvn cobertura:cobertura
    - ls target
  artifacts:
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
    when: on_success
    expose_as: 'artifact 1'
    paths:
      - target/*.jar
    reports:
      junit: target/surefire-reports/TEST-*.xml
      cobertura: target/site/cobertura/coverage.xml
$ gitlab-rails console
--------------------------------------------------------------------------------
 GitLab:       12.9.0 (9a382ff2c82) FOSS
 GitLab Shell: 12.0.0
 PostgreSQL:   10.12
--------------------------------------------------------------------------------


Loading production environment (Rails 6.0.2)
irb(main):001:0>
irb(main):002:0>
irb(main):003:0> Feature.enable(:coverage_report_view)
=> true

maven集成cobertura插件

<plugins>       
  <!--  cobertura plugin start -->
  <plugin>
    <groupId>org.codehaus.mojo</groupId>  
    <artifactId>cobertura-maven-plugin</artifactId>  
    <version>2.7</version>  
    <configuration>  
      <formats>  
          <format>html</format>  
          <format>xml</format>  
      </formats>  
  	</configuration>  
  </plugin>       
  <!--  cobertura plugin end -->

</plugins>

執行 mvn cobertura:cobertura 運行測試並產生 Cobertura 覆蓋率報告。

參考鏈接:https://docs.gitlab.com/12.9/ee/user/project/merge_requests/test_coverage_visualization.html

備注實驗未做出效果,具體問題待排查。


dependencies

定義要獲取工件的作業列表,只能從當前階段之前執行的階段定義作業。定義一個空數組將跳過下載該作業的任何工件不會考慮先前作業的狀態,因此,如果它失敗或是未運行的手動作業,則不會發生錯誤。

如果設置為依賴項的作業的工件已過期或刪除,那么依賴項作業將失敗。


綜合實例

before_script:
  - echo "before-script!!"

variables:
  DOMAIN: example.com


cache: 
  paths:
   - target/

stages:
  - build
  - test
  - deploy
  
build:
  before_script:
    - echo "before-script in job"
  stage: build
  tags:
    - build
  only:
    - master
  script:
    - ls
    - id
    - mvn test
    - mvn cobertura:cobertura
    - ls target
    - echo "$DOMAIN"
    - false && true ; exit_code=$?
    - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
    - sleep 2;
  after_script:
    - echo "after script in job"
  artifacts:
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
    when: on_success
    #expose_as: 'artifact 1'
    paths:
      - target/*.jar
      #- target/surefire-reports/TEST*.xml
    reports:
      junit: target/surefire-reports/TEST-*.xml
      cobertura: target/site/cobertura/coverage.xml
  coverage: '/Code coverage: \d+\.\d+/'


unittest:
  dependencies:
    - build
  stage: test
  tags:
    - build
  only:
    - master
  script:
    - echo "run test"
    - echo 'test' >> target/a.txt
    - ls target
  retry:
    max: 2
    when:
      - script_failure
  
deploy:
  stage: deploy
  tags:
    - build
  only:
    - master
  script:
    - echo "run deploy"
    - ls target
  retry:
    max: 2
    when:
      - script_failure
      
      

after_script:
  - echo "after-script"
  

needs/include/extends/trigger

needs 並行階段

可無序執行作業,無需按照階段順序運行某些作業,可以讓多個階段同時運行。

stages:
  - build
  - test
  - deploy

module-a-build:
  stage: build
  script: 
    - echo "hello3a"
    - sleep 10
    
module-b-build:
  stage: build
  script: 
    - echo "hello3b"
    - sleep 10

module-a-test:
  stage: test
  script: 
    - echo "hello3a"
    - sleep 10
  needs: ["module-a-build"]
    
module-b-test:
  stage: test
  script: 
    - echo "hello3b"
    - sleep 10
  needs: ["module-b-build"]
    

如果needs:設置為指向因only/except規則而未實例化的作業,或者不存在,則創建管道時會出現YAML錯誤。

暫時限制了作業在needs:可能需要的最大作業數分配,ci_dag_limit_needs功能標志已啟用(默認)分配10個,如果功能被禁用為50。

Feature::disable(:ci_dag_limit_needs)   # 50
Feature::enable(:ci_dag_limit_needs)  #10

制品下載

在使用needs,可通過artifacts: trueartifacts: false來控制工件下載。 默認不指定為true。

module-a-test:
  stage: test
  script: 
    - echo "hello3a"
    - sleep 10
  needs: 
    - job: "module-a-build"
      artifacts: true

相同項目中的管道制品下載,通過將project關鍵字設置為當前項目的名稱,並指定引用,可以使用needs從當前項目的不同管道中下載工件。在下面的示例中,build_job將使用other-refref下載最新成功的build-1作業的工件:

build_job:
  stage: build
  script:
    - ls -lhR
  needs:
    - project: group/same-project-name
      job: build-1
      ref: other-ref
      artifacts: true

不支持從parallel:運行的作業中下載工件。


include

https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates

可以允許引入外部YAML文件,文件具有擴展名.yml.yaml 。使用合並功能可以自定義和覆蓋包含本地定義的CI / CD配置。相同的job會合並,參數值以源文件為准。

local

引入同一存儲庫中的文件,使用相對於根目錄的完整路徑進行引用,與配置文件在同一分支上使用。

ci/localci.yml: 定義一個作業用於發布。

stages:
  - deploy
  
deployjob:
  stage: deploy
  script:
    - echo 'deploy'

.gitlab-ci.yml 引入本地的CI文件’ci/localci.yml’。

include:
  local: 'ci/localci.yml'
  

stages:
  - build
  - test
  - deploy
  

buildjob:
  stage: build
  script: ls
  
 
testjob:
  stage: test
  script: ls

效果


file

包含來自另一個項目的文件

include:
  - project: demo/demo-java-service
    ref: master
    file: '.gitlab-ci.yml'

實際使用效果演示:

在同一個用戶目錄下的不同倉庫,項目是一個私有倉庫,yml文件所在是一個公開倉庫
注意引用的yml文件的路徑寫法 前面的是用戶名,后面的是倉庫名




template

只能使用官方提供的模板 https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates

include:
  - template: Auto-DevOps.gitlab-ci.yml

remote

用於通過HTTP / HTTPS包含來自其他位置的文件,並使用完整URL進行引用. 遠程文件必須可以通過簡單的GET請求公開訪問,因為不支持遠程URL中的身份驗證架構。

include:
  - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml'

extends

繼承模板作業

stages:
  - test
variables:
  RSPEC: 'test'

.tests:
  script: echo "mvn test"
  stage: test
  only:
    refs:
      - branches

testjob:
  extends: .tests
  script: echo "mvn clean test"
  only:
    variables:
      - $RSPEC

合並后

testjob:
  stage: test
  script: mvn clean test
  only:
    variables:
      - $RSPEC
    refs:
      - branches

extends & include

aa.yml

#stages:
#  - deploy
  
deployjob:
  stage: deploy
  script:
    - echo 'deploy'
  only:
    - dev

.template:
  stage: build
  script: 
    - echo "build"
  only:
    - master
include:
  local: 'ci/localci.yml'

stages:
  - test
  - build 
  - deploy
  
variables:
  RSPEC: 'test'

.tests:
  script: echo "mvn test"
  stage: test
  only:
    refs:
      - branches

testjob:
  extends: .tests
  script: echo "mvn clean test"
  only:
    variables:
      - $RSPEC
      

newbuildjob:
  script:
    - echo "123"
  extends: .template

這將運行名為useTemplate的作業,該作業運行echo Hello!.template作業中所定義,並使用本地作業中所定義的alpine Docker映像.


trigger 管道觸發

當GitLab從trigger定義創建的作業啟動時,將創建一個下游管道。允許創建多項目管道和子管道。將triggerwhen:manual一起使用會導致錯誤。

多項目管道: 跨多個項目設置流水線,以便一個項目中的管道可以觸發另一個項目中的管道。[微服務架構]

父子管道: 在同一項目中管道可以觸發一組同時運行的子管道,子管道仍然按照階段順序執行其每個作業,但是可以自由地繼續執行各個階段,而不必等待父管道中無關的作業完成。

多項目管道

當前面階段運行完成后,觸發demo/demo-java-service項目master流水線。創建上游管道的用戶需要具有對下游項目的訪問權限。如果發現下游項目用戶沒有訪問權限以在其中創建管道,則staging作業將被標記為失敗

staging:
  variables:
    ENVIRONMENT: staging
  stage: deploy
  trigger: 
    project: demo/demo-java-service
    branch: master
    strategy: depend

project關鍵字,用於指定下游項目的完整路徑。該branch關鍵字指定由指定的項目分支的名稱。使用variables關鍵字將變量傳遞到下游管道。 全局變量也會傳遞給下游項目。上游管道優先於下游管道。如果在上游和下游項目中定義了兩個具有相同名稱的變量,則在上游項目中定義的變量將優先。默認情況下,一旦創建下游管道,trigger作業就會以success狀態完成。strategy: depend將自身狀態從觸發的管道合並到源作業。

在下游項目中查看管道信息

在此示例中,一旦創建了下游管道,該staging將被標記為成功。

父子管道

創建子管道ci/child01.yml

stages:
  - build

child-a-build:
  stage: build
  script: 
    - echo "hello3a"
    - sleep 10

在父管道觸發子管道

staging2:
  variables:
    ENVIRONMENT: staging
  stage: deploy
  trigger: 
    include: ci/child01.yml  
    strategy: depend

image/services/environment/inherit

准備工作注冊docker類型的runner

gitlab-runner register \
  --non-interactive \
  --executor "docker" \
  --docker-image alpine:latest \
  --url "http://192.168.1.200:30088/" \
  --registration-token "JRzzw2j1Ji6aBjwvkxAv" \
  --description "docker-runner" \
  --tag-list "newdocker" \
  --run-untagged="true" \
  --locked="false" \
  --docker-privileged \ 
  --access-level="not_protected"
[[runners]]
  name = "docker-runner"
  url = "http://192.168.1.200:30088/"
  token = "xuaLZD7xUVviTsyeJAWh"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
  [runners.docker]
    pull_policy = "if-not-present"
    tls_verify = false
    image = "alpine:latest"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0

image

默認在注冊runner的時候需要填寫一個基礎的鏡像,請記住一點只要使用執行器為docker類型的runner所有的操作運行都會在容器中運行。 如果全局指定了images則所有作業使用此image創建容器並在其中運行。 全局未指定image,再次查看job中是否有指定,如果有此job按照指定鏡像創建容器並運行,沒有則使用注冊runner時指定的默認鏡像。

#image: maven:3.6.3-jdk-8

before_script:
  - ls
  
  
build:
  image: maven:3.6.3-jdk-8
  stage: build
  tags:
    - newdocker
  script:
    - ls
    - sleep 2
    - echo "mvn clean "
    - sleep 10

deploy:
  stage: deploy
  tags:
    - newdocker
  script:
    - echo "deploy"

services

工作期間運行的另一個Docker映像,並link到image關鍵字定義的Docker映像。這樣,您就可以在構建期間訪問服務映像.

服務映像可以運行任何應用程序,但是最常見的用例是運行數據庫容器,例如mysql 。與每次安裝項目時都安裝mysql相比,使用現有映像並將其作為附加容器運行更容易,更快捷。

services:
  - name: mysql:latest
    alias: mysql-1

environment

deploy to production:
  stage: deploy
  script: git push production HEAD:master
  environment:
    name: production
    url: https://prod.example.com

inherit

使用或禁用全局定義的環境變量(variables)或默認值(default)。

使用true、false決定是否使用,默認為true

inherit:
  default: false
  variables: false

繼承其中的一部分變量或默認值使用list

inherit:
  default:
    - parameter1
    - parameter2
  variables:
    - VARIABLE1
    - VARIABLE2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM