Ну че типа разберемся с кэшом…
В качестве основы возьмем статью GitLab CI speeding up your pipeline with caching
Чуток модифицируем это дело вообщем поехали…
Пару слов о конфигурации
Нам понадобится Gitlab Runner + minio это нужно для использования fallback_keys в конфигурации кэша (ниже будет подробнее).
В доке к сожалению подробностей нет но можно почитать тут Fallback cache key only works for distributed cache.
Тут писать что-то о настройке gitlab-runer + minio мы не будем просто приведу конфиг
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
listen_address = "runner.local:9252"
concurrent = 20
check_interval = 2
[session_server]
session_timeout = 1800
[[runners]]
name = "runner"
url = "https://gitlab.local/"
limit = 20
request_concurrency = 10
id = 521
token = "xdfsFGcvdfsvffdsF"
token_obtained_at = 2023-09-19T14:51:02Z
token_expires_at = 0001-01-01T00:00:00Z
tls-ca-file = "/media/data/gitlab-runner/config/certs/gitlab.pem"
executor = "shell"
environment = ["GIT_SSL_NO_VERIFY=1"]
[runners.cache]
MaxUploadedArchiveSize = 0
Type = "s3"
Shared = true
[runners.cache.s3]
AccessKey = "xzgxgdfgdfg"
SecretKey = "dxdgdxgGfxzdhf"
BucketName = "runner"
Insecure = true
ServerAddress = "runner.local:80"
Тестовый конфиг для GitLab CI
Тут стоит у помянуть что у нас будут “псевдошаги” те по факту будем просто писать и выводить файл. В краце опишем что мы хотим
Скажем у нас есть 2 ветки:
- master
- dev
Stage + Variables
Фиг знает че тут сказать вообще то нечего… ну разве что по переменным.
DEFAULT_CACHE_KEY_PREFIX - эт типа для fallback кэша т.е. если мы не будем собирать кэш то от куда его брать.
CACHE_KEY_PREFIX - тут просто префикс для кэша.
DEPS_FOLDER - директория которую будем кэшировать.
1
2
3
4
5
6
7
8
9
stages:
- prepare
- build
- test
variables:
DEFAULT_CACHE_KEY_PREFIX: ${CI_DEFAULT_BRANCH}
CACHE_KEY_PREFIX: ${CI_COMMIT_REF_SLUG}
DEPS_FOLDER: ${CI_PROJECT_DIR}/.deps
Когда собирать кэш?
Собирать кэш будем в 2х случаях.
- В случае билда из ветки мастер
- Если мы билдим любую другую ветку при этом у нас файл my-referent-file.lock изменился в сравнии с файлом из ветки master doc.
За это дело у нас будут отвечать следующий кусок конфига
1
2
3
4
5
6
7
8
9
10
11
.deps_update_rules:
rules:
- if: $CI_COMMIT_BRANCH != "master"
changes:
paths:
- my-referent-file.lock
compare_to: refs/heads/master
- if: $CI_COMMIT_BRANCH == "master"
when: always
- if: $CI_COMMIT_TAG != null
when: always
Anchor для сборки кэша
Тут у нас пару кэшей будет формироваться.
- ${CACHE_KEY_PREFIX}-deps-dev
- ${CACHE_KEY_PREFIX}-deps-run
(Их 2 не потому что тут что-то хитрожопое просто в изначальной статье их зачем то сделали 2, ну и для наглядности пойдет)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.deps_dev_cache:
cache: &deps_dev_cache
key: ${CACHE_KEY_PREFIX}-deps-dev
fallback_keys:
- ${DEFAULT_CACHE_KEY_PREFIX}-deps-dev
paths:
- ${DEPS_FOLDER}
policy: pull
.deps_run_cache:
cache: &deps_run_cache
key: ${CACHE_KEY_PREFIX}-deps-run
fallback_keys:
- ${DEFAULT_CACHE_KEY_PREFIX}-deps-run
paths:
- ${DEPS_FOLDER}
policy: pull
Собственно че тут написанно про сами anchors (&deps_dev_cache/&deps_run_cache) писать не буду можно почитать тут. Тут просто нужно знать что anchors пишутся для того чтобы можно бы ло переиспользовать данный контент где то ниже.
Соответственно тут у нас “контент” для формирования кэша:
- key: ${CACHE_KEY_PREFIX}-deps-dev - название кэша
- fallback_keys: - ${DEFAULT_CACHE_KEY_PREFIX}-deps-dev - если не найден кэш ${CACHE_KEY_PREFIX}-deps-dev то попробовать взять кэш из fallback_keys
- paths: ${DEPS_FOLDER} - путь который будем кэшировать
- policy - забирать пулять вообщем типа че делать с кэшом, данное свойство будем переопредлять по ходу написания конфига.
Сбор кэша
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
dev_dependencies:
stage: prepare
script:
- echo "I am a dependency" > ./.deps/deps.txt
- echo "I am a dev dependency" >> ./.deps/deps.txt
cache:
<<: *deps_dev_cache
policy: pull-push
rules: !reference [.deps_update_rules, rules]
run_dependencies:
stage: prepare
script:
- echo "I am a dependency" > ./.deps/deps.txt
cache:
<<: *deps_run_cache
policy: pull-push
rules: !reference [.deps_update_rules, rules]
Тут мы формируем 2 кэша путем использования упомянутых выше anchors. В зависимости от rules
- script - ну типа скрипт че тут еще сказать
- cache - тут берем контент из anchor deps_dev_cache
- policy - тут подменяем policy взятое из anchors на ту которая позваляет так же засывывать кэш
Вывод файла из кэша
1
2
3
4
5
6
7
8
9
10
11
12
13
test-app:
stage: test
script:
- cat ./.deps/deps.txt
cache:
<<: *deps_dev_cache
package-app:
stage: build
script:
- cat ./.deps/deps.txt
cache:
<<: *deps_run_cache
тут хз че сказать просто скрипт который выводит содержимое файла при этом опять использует кэши из anchors deps_dev_cache и deps_run_cache.
Full config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
stages:
- prepare
- build
- test
variables:
DEFAULT_CACHE_KEY_PREFIX: ${CI_DEFAULT_BRANCH}
CACHE_KEY_PREFIX: ${CI_COMMIT_REF_SLUG}
DEPS_FOLDER: ${CI_PROJECT_DIR}/.deps
.deps_update_rules:
rules:
- if: $CI_COMMIT_BRANCH != "master"
changes:
paths:
- my-referent-file.lock
compare_to: refs/heads/master
- if: $CI_COMMIT_BRANCH == "master"
when: always
- if: $CI_COMMIT_TAG != null
when: always
.deps_dev_cache:
cache: &deps_dev_cache
key: ${CACHE_KEY_PREFIX}-deps-dev
fallback_keys:
- ${DEFAULT_CACHE_KEY_PREFIX}-deps-dev
paths:
- ${DEPS_FOLDER}
policy: pull
.deps_run_cache:
cache: &deps_run_cache
key: ${CACHE_KEY_PREFIX}-deps-run
fallback_keys:
- ${DEFAULT_CACHE_KEY_PREFIX}-deps-run
paths:
- ${DEPS_FOLDER}
policy: pull
dev_dependencies:
stage: prepare
script:
- echo "I am a dependency" > ./.deps/deps.txt
- echo "I am a dev dependency" >> ./.deps/deps.txt
cache:
<<: *deps_dev_cache
policy: pull-push
rules: !reference [.deps_update_rules, rules]
run_dependencies:
stage: prepare
script:
- echo "I am a dependency" > ./.deps/deps.txt
cache:
<<: *deps_run_cache
policy: pull-push
rules: !reference [.deps_update_rules, rules]
test-app:
stage: test
script:
- cat ./.deps/deps.txt
cache:
<<: *deps_dev_cache
package-app:
stage: build
script:
- cat ./.deps/deps.txt
cache:
<<: *deps_run_cache
Test Runs
Попробуем позапускать это дело.
Запуск master ветки
Предположим что на старте у нас есть две абсолютно одинаковые ветки
- master
- dev
Нам полюбому надо сначала запустить pipeline по ветке master как минимум для того что бы у нас сформировался кэш. Запускаем видимо что все хорошо
Запуск dev ветки
Далее запускаем по ветке dev видим что кэши не собирались при этом все шаги отработали хорошо потому что исползован был fallback cache т.е в нашем случае кэш из ветки мастер:
1
2
fallback_keys:
- ${DEFAULT_CACHE_KEY_PREFIX}-deps-dev
В логе джоба можно увидеть что кэш для dev ветки не найден, и соответствено был звят кэш из ветки master (напомню что для этого надо s3 хранилище)
Run dev branch after update file my-referent-file.lock
Попробуем поправить файл my-referent-file.lock в dev ветке собственнааа для того что бы собрался отдельный кэш для этой ветки (я просто добавил туда пару строк)… пушим… смотрим результат:
P.S.
Всем спасибо!)