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"
一起學習呀: