🦊 Предварительный просмотр GitLab Pages: бескомпромиссный хак для обслуживания страниц каждой ветки
С помощью GitLab Pages вы можете публиковать статические веб-сайты непосредственно из репозитория в GitLab. По умолчанию у нас не может быть страниц предварительного просмотра: если задание развертывает страницы, это перезаписывает предыдущее содержимое, что запрещает режим предварительного просмотра. Мы покажем как сделать настройку GitLab на примере предварительного просмотра страниц, что облегчит вам работу в будущем.
В некоторых статьях в Интернете показано, как обойти это с помощью артефактов, зная, что GitLab может отображать артефакты. Но у этого трюка есть минусы, в основном узкотехнические ссылки, которыми приходится снова делиться после изменений на ветке.
Некоторая суть Github указывает на правильное направление, но сложным образом и со слишком небольшим количеством побочных функций.
В этой статье мы обойдем ограничение, воспользовавшись механизмом кэширования, и сможем отображать контент для каждой ветки с побочным преимуществом запутывания пути к содержимому эфемерных ветвей, если это необходимо.
Решение можно разбить на следующие шаги:
- Генерация файлов для текущей ветки
- Получение предыдущей генерации веток из кэша GitLab
- Слияние и обновление кэша
- Автоматическое удаление устаревшего кэша при удалении ветки с использованием среды GitLab
Предпосылки
Мы предполагаем, что у вас уже есть способ создания статического HTML-контента, и вы просто хотите обслуживать файлы с помощью GitLab Pages.
Чтобы код работал, ваш кеш должен быть централизованным, либо с помощью gitlab.com runner, либо с помощью одного исполнителя, либо путем совместного использования кешей несколькими частными исполнителями.
Вам необходимо принять глобальный кэш, отключив опцию GiLab Использовать отдельные кэши для защищенных веток в Settings->CICD->General Pipelnes.
Код конвейера GitLab
workflow:
rules: # disable tag pipelines and duplicate MR pipelines
- if: $CI_COMMIT_BRANCH
variables:
EPHEMERAL_BRANCHES_PATH: preview # subpath to ephemeral branches content for preview, anything will work
pages:
stage: build
image: alpine:3.18
cache:
key: gitlab-pages
paths: [public]
before_script:
# default available 'tree' app in alpine image does not work as intended
- apk add tree
# CURRENT_CONTENT_PATH is defined in rules, different between main branch and ephemeral branches
- mkdir -p public/$CURRENT_CONTENT_PATH && ls public/$CURRENT_CONTENT_PATH/..
- | # avoid deleting main branch content when cache has been erased
if [ "$CI_COMMIT_BRANCH" != "$CI_DEFAULT_BRANCH" ] && [ ! -d public/$CI_DEFAULT_BRANCH ]; then
echo -e "💥\e[91;1m Unable to retrieve $CI_DEFAULT_BRANCH generated files from cache ; please regenerate $CI_DEFAULT_BRANCH files first\e[0m"
exit 1
fi
- rm -rf public/$CURRENT_CONTENT_PATH || true # remove last version of current branch
script:
- ./generate-my-html.sh --output build-docs || true # insert here your code that generates documentation
- mv --verbose build-docs public/$CURRENT_CONTENT_PATH
- cd public/$EPHEMERAL_BRANCHES_PATH
- tree -d -H '.' -L 1 --noreport --charset utf-8 -T "Versions" -o index.html # generate a root HTML listing all previews for easier access
environment:
name: pages/$CI_COMMIT_BRANCH
action: start
url: $CI_PAGES_URL/$CURRENT_CONTENT_PATH
on_stop: pages:clean-preview
rules:
# 'main branch' is exposed at GitLab Pages root
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
variables:
CURRENT_CONTENT_PATH: "."
# other (short-lived) branches generation are exposed in 'EPHEMERAL_BRANCHES_PATH/branch-name-sanitized' sub path
- variables:
CURRENT_CONTENT_PATH: $EPHEMERAL_BRANCHES_PATH/$CI_COMMIT_REF_SLUG
artifacts:
paths: [public]
expire_in: 1h
pages:clean-preview:
stage: build
image: alpine:3.18
cache:
key: gitlab-pages
paths: [public]
variables:
GIT_STRATEGY: none # git files not available after branch deletion
FOLDER_TO_DELETE: preview/$CI_COMMIT_BRANCH # an indirection to allow arbirtraty deletion when launching this job
script:
- rm -rf public/$FOLDER_TO_DELETE
environment:
name: pages/$CI_COMMIT_BRANCH
action: stop
rules:
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
when: manual
allow_failure: true
Интегрированные функции
Приведённый выше код имеет следующие функции:
main
контент отображается на$CI_PAGES_URL
, а путь настраивается с помощью$CURRENT_CONTENT_PATH
.- Контент предварительного просмотра для каждой ветки отображается на
$CI_PAGES_URL/preview
, а домашняя страница позволяет легко переходить к веткам. - Путь к корневой папке предварительного просмотра настраивается с помощью переменной
$EPHEMERAL_BRANCHES_PATH
, чтобы скрыть содержимое предварительного просмотра путем обфускации. - Сгенерированные страницы связаны со средами, чтобы воспользоваться автоматической очисткой при удалении ветки.
- Чтобы не нарушать уже существующие среды, среда страниц помещается в папку
pages
. - Если
main
контент не был сгенерирован в текущем кэше или если кэш был удален, срабатывает ошибка, чтобы избежать случайного удаления - Задание на удаление может быть запущено вручную с любым путем кэширования в качестве входных данных для очистки устаревших данных.
- Его можно безопасно добавить в существующий конвейер проекта, не вызывая проблем с уже существующими заданиями.
Workflow:rules
можно удалить, если у вас уже есть свои, или обновить, чтобы они соответствовали вашему потоку.- Задание должно называться
pages
, а артефакт должен быть общедоступной папкой для развертывания на страницах GitLab (или вы можете использовать ключевое слово pages:publish).
Заключение
Учитывая предоставленный кусок yaml, используя его в своем пайплайне, вы должны иметь возможность делиться своими страницами GitLab для каждой ветки по нужному вам пути, при этом предоставляя стабильный контент из корневого контекста.
Для любого вопроса или замечания, пожалуйста, используйте раздел комментариев ниже 🤓.