Настройка GitLab CI для сборки проектов gsf-cli#
Инструкция по настройке CI процесса для автоматической сборки applib и appsrc.
1. Настройка gitlab-runner#
Инструкция применима к выделенному хосту сборки с Debian-based системой и shell executor.
1.1 Настройка раннера в GitLab проекте#
Перейдите в нужный проект.
Откройте меню:
Settings→CI/CD.Разверните секцию
Runners.Нажмите «New project runner».
Укажите:
Tag — метка, по которой будет запускаться раннер.
Runner description — описание раннера.
Отключите опцию
Run untagged jobs.После создания откройте настройки раннера и включите:
Protected— раннер выполняет job-ы только для защищенных веток и тегов.Lock to current projects— раннер нельзя подключить к другому проекту.
После нажатия вы перейдёте на страницу справки по регистрации gitlab-runner.
Выберите нужную операционную систему и сохраните предложенную команду регистрации с токеном вида glrt-....
shell executor выполняет команды с правами gitlab-runner и имеет доступ к постоянному workspace и сохраненным
credentials. Используйте его только для доверенного проекта и защищенных веток.
1.2. Установка GitLab Runner#
Версия GitLab Runner должна совпадать с версией GitLab по major.minor. Уточните версию GitLab у администратора и
задайте соответствующий тег runner, например v18.0.3.
На хосте сборки выполните следующие команды для архитектуры amd64:
sudo apt-get update
sudo apt-get install -y ca-certificates curl
RUNNER_VERSION="v<gitlab-major.minor.patch>"
# Скачивание бинарного файла GitLab Runner
sudo curl -fL \
--output /usr/local/bin/gitlab-runner \
"https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/${RUNNER_VERSION}/binaries/gitlab-runner-linux-amd64"
# Выдача прав на исполнение
sudo chmod 0755 /usr/local/bin/gitlab-runner
# Создание системного пользователя
id gitlab-runner >/dev/null 2>&1 || \
sudo useradd --comment "GitLab Runner" --create-home gitlab-runner --shell /bin/bash
# Установка раннера как systemd-сервиса
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
# Запуск сервиса
sudo gitlab-runner start
# Проверка установленной версии и сервиса
gitlab-runner --version
sudo gitlab-runner status
В закрытой сети загрузите бинарный файл той же версии через разрешенный внутренний репозиторий. Если GitLab использует
корпоративный сертификат, перед регистрацией выполните шаг 1.4.
Официальная инструкция: Install GitLab Runner manually on GNU/Linux.
1.3. Регистрация раннера#
Выполните команду регистрации, полученную на этапе Настройка раннера в GitLab проекте:
Пример:
sudo gitlab-runner register \
--config /etc/gitlab-runner/config.toml \
--url "https://gitlab.example.org" \
--token "<runner-authentication-token>"
Параметр --config обязателен: systemd-сервис использует /etc/gitlab-runner/config.toml. Без него конфигурация может
быть сохранена в домашнем каталоге текущего пользователя и не будет загружена сервисом.
Данная команда выдаст диалоговое окно, в котором:
Укажите имя раннера (можно оставить по умолчанию).
Выберите тип исполнителя:
shell.Если команда запросит tag, укажите tag из раздела
1.1.
После регистрации ограничьте runner одним одновременно выполняемым job. Откройте /etc/gitlab-runner/config.toml:
sudoedit /etc/gitlab-runner/config.toml
Проверьте следующие параметры:
concurrent = 1
[[runners]]
limit = 1
executor = "shell"
Остальные сгенерированные параметры, включая url и token, не изменяйте. После сохранения выполните:
sudo gitlab-runner verify
sudo systemctl restart gitlab-runner.service
sudo systemctl --no-pager --full status gitlab-runner.service
Ограничение необходимо, потому что GSF CLI использует общий workspace /opt/global/gsf-cli/workspace.
Официальные инструкции: Registering runners, Advanced configuration.
1.4. Корпоративный сертификат GitLab#
Если сертификат GitLab выпущен внутренним центром сертификации, добавьте корневой и промежуточные сертификаты в системное хранилище. Файл должен быть в формате PEM:
sudo install -m 0644 <path-to-ca-file> \
/usr/local/share/ca-certificates/gitlab-internal-ca.crt
sudo update-ca-certificates
sudo systemctl restart gitlab-runner.service
При ошибке регистрации x509: certificate signed by unknown authority дополнительно укажите CA для runner:
sudo install -d -m 0755 /etc/gitlab-runner/certs
sudo install -m 0644 <path-to-ca-file> \
/etc/gitlab-runner/certs/gitlab.example.org.crt
sudo systemctl restart gitlab-runner.service
Имя файла должно совпадать с hostname GitLab без номера порта. Не используйте GIT_SSL_NO_VERIFY.
Официальная инструкция: Self-signed certificates or custom Certification Authorities.
1.5. Проверка#
Защитите ветку, из которой будет запускаться проверка. Создайте минимальный .gitlab-ci.yml и укажите tag раннера:
test-job:
tags:
- <your-runner-tag>
script:
- test "$(whoami)" = "gitlab-runner"
- test "$HOME" = "/home/gitlab-runner"
- git --version
Возможные проблемы#
Если при запуске пайплайна возникает ошибка:
Running with gitlab-runner 18.0.3 (4e717029)
on gsf-cli-runner t3_bF2zm, system ID: s_3f8d99cb7822
Preparing the "shell" executor
00:00
Using Shell (bash) executor...
Preparing environment
00:00
Running on gsf-cli-ci...
ERROR: Job failed: prepare environment: exit status 1. Check https://docs.gitlab.com/runner/shells/#shell-profile-loading for more information
Проверьте /home/gitlab-runner/.bash_logout. Если в нем присутствует следующий блок, закомментируйте его:
if [ "$SHLVL" = 1 ]; then
[ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
fi
Перезапустите сервис:
sudo systemctl restart gitlab-runner.service
2. Установка и настройка GSF-CLI на хосте сборки#
Программное обеспечение, которое потребуется для сборки#
Java 21 - установка выполняется пользователем самостоятельно до начала настройки GSF-CLI
2.1. Установка требуемых пакетов#
sudo apt-get update
sudo apt-get install -y ca-certificates curl git wget zip unzip
2.2. Подготовка директорий#
Создайте рабочие каталоги:
sudo mkdir -p /opt/global/{tmp,builds}
2.3. Загрузка необходимых компонентов#
# GSF CLI
sudo wget -P /opt/global/tmp https://repo.global-system.ru/artifactory/common/ru/bitec/gsf-cli-linux/SNAPSHOT/gsf-cli-linux-SNAPSHOT.zip
# sbt
sudo wget -P /opt/global/tmp https://github.com/sbt/sbt/releases/download/v1.10.7/sbt-1.10.7.zip
# JDK 21
# установка выполняется пользователем самостоятельно
2.4. Установка и распаковка компонентов#
# Установка JDK
# установка выполняется пользователем самостоятельно
# Распаковка SBT
sudo unzip /opt/global/tmp/sbt-1.10.7.zip -d /opt/global
# Распаковка GSF CLI
sudo unzip /opt/global/tmp/gsf-cli-linux-SNAPSHOT.zip -d /opt/global/gsf-cli
2.5. Установка GSF CLI#
sudo /opt/global/gsf-cli/bin/installpkg.sh
sudo /opt/global/gsf-cli/bin/initvenv.sh
initvenv.sh использует каталог wheels из дистрибутива GSF CLI. Если каталога нет, хосту потребуется доступ к
настроенному Python package index. Linux-дистрибутив содержит wheels для CPython версий 3.9.2–3.13 на архитектуре
x86_64, включая Python 3.13 из Debian 13.
2.6. Настройка владельца директории#
Сборка выполняется пользователем gitlab-runner. Перед настройкой передайте ему рабочую директорию:
sudo chown -R gitlab-runner:gitlab-runner /opt/global
Не выполняйте настройку проекта и учетных данных от root: его домашний каталог и файлы credentials не используются
job-ами gitlab-runner.
Проверьте установку и права от имени пользователя runner:
sudo -u gitlab-runner -H test -x /opt/global/gsf-cli/manage.sh
sudo -u gitlab-runner -H test -x /opt/global/sbt/bin/sbt
sudo -u gitlab-runner -H test -f /opt/global/sbt/bin/sbt-launch.jar
sudo -u gitlab-runner -H test -x /usr/lib/jvm/bellsoft-java21-amd64/bin/java
sudo -u gitlab-runner -H test -x /usr/lib/jvm/bellsoft-java21-amd64/bin/javac
sudo -u gitlab-runner -H \
/usr/lib/jvm/bellsoft-java21-amd64/bin/java -version
sudo -u gitlab-runner -H \
/usr/lib/jvm/bellsoft-java21-amd64/bin/javac -version
sudo -u gitlab-runner -H mkdir -p /opt/global/gsf-cli/workspace
sudo -u gitlab-runner -H touch /opt/global/gsf-cli/workspace/.write-test
sudo -u gitlab-runner -H rm /opt/global/gsf-cli/workspace/.write-test
Замените путь JDK в командах и config.json, если JDK установлена в другой каталог.
2.7. Настройка сборочного проекта#
Конфигурационный файл#
Создайте конфигурационный файл:
sudo -u gitlab-runner -H nano /opt/global/builds/config.json
со следующим содержимым:
project_source— URL конфигурационного проекта, оканчивающийся на.git.project_branch— существующая ветка конфигурационного проекта.jdk_home— каталог JDK 21, содержащийbin/javaиbin/javac.name— имя проекта внутри GSF CLI.
{
"sbt_home": "/opt/global/sbt",
"projects": [
{
"project_branch": "test",
"jdk_home": "/usr/lib/jvm/bellsoft-java21-amd64/",
"name": "main",
"project_source": "https://git.example.org/group/configuration-project.git",
"build_system": "sbt",
"publish_type": "SNAPSHOT"
}
]
}
Детальное описание файла можно посмотреть тут
Проверьте синтаксис JSON:
sudo -u gitlab-runner -H \
python3 -m json.tool /opt/global/builds/config.json >/dev/null
Регистрация приватного ключа#
sudo -u gitlab-runner -H \
/opt/global/gsf-cli/config.sh register_private_key -c /opt/global
Настройка учетных данных GSF CLI#
Учетные данные Git и менеджера репозиториев сохраняются в зашифрованном виде в
/opt/global/gsf-cli/workspace/store.json. Для постоянного shell runner-а настройте их один раз.
Откройте shell от имени пользователя runner:
sudo -u gitlab-runner -H bash
Добавьте учетные данные Git. В качестве URL укажите базовый адрес Git-сервера без пути к репозиторию:
read -rp "Git URL: " GSF_GIT_URL
read -rp "Git login: " GSF_GIT_LOGIN
read -rsp "Git token: " GSF_GIT_TOKEN
printf '\n'
printf '%s' "$GSF_GIT_TOKEN" | \
/opt/global/gsf-cli/credential_manager.sh set \
--url "$GSF_GIT_URL" \
--login "$GSF_GIT_LOGIN" \
--password-stdin
unset GSF_GIT_URL GSF_GIT_LOGIN GSF_GIT_TOKEN
Добавьте учетные данные для репозитория из которого будет выкачиваться дистрибутив GlobalServer. В качестве URL укажите базовый адрес хоста без пути к конкретному репозиторию:
read -rp "Repository URL: " GSF_REPO_URL
read -rp "Repository login: " GSF_REPO_LOGIN
read -rsp "Repository token: " GSF_REPO_TOKEN
printf '\n'
printf '%s' "$GSF_REPO_TOKEN" | \
/opt/global/gsf-cli/credential_manager.sh set \
--url "$GSF_REPO_URL" \
--login "$GSF_REPO_LOGIN" \
--password-stdin
unset GSF_REPO_URL GSF_REPO_LOGIN GSF_REPO_TOKEN
Проверьте сохраненные записи без вывода паролей и закройте shell:
/opt/global/gsf-cli/credential_manager.sh show
exit
Одна запись используется для всех вложенных URL на том же хосте. Если модули или зависимости расположены на разных
хостах, повторите команду set для каждого базового URL. Повторная настройка требуется после смены токена, переноса
runner-а или удаления workspace/store.json либо приватного ключа.
2.8. Активация headless-режима#
Включите headless режим для отключения диалогов в процессе сборки:
sudo -u gitlab-runner -H \
/opt/global/gsf-cli/config.sh enable_headless
2.9. Загрузка конфигурации#
Выполните первичную загрузку конфигурации из config.json:
sudo -u gitlab-runner -H \
/opt/global/gsf-cli/config.sh load_config -f /opt/global/builds/config.json
Команда регистрирует проекты в GSF CLI, но не скачивает их исходный код. Первое клонирование выполняется командой
refresh внутри pipeline. Pipeline повторно загружает config.json перед каждой сборкой, поэтому изменения файла
применяются автоматически.
Проверьте владельца и права файлов с конфигурацией:
sudo -u gitlab-runner -H stat -c '%a %U:%G %n' \
/opt/global/.gsf-cli.priv \
/opt/global/gsf-cli/workspace/store.json
Для обоих файлов ожидаются права 600 и владелец gitlab-runner.
Проверьте загруженную конфигурацию:
sudo -u gitlab-runner -H \
/opt/global/gsf-cli/manage.sh --all clean
3. Конфигурация пайплайна#
3.1. Настройка переменных#
Откройте Settings → CI/CD → Variables и добавьте переменные:
Переменная |
Значение |
Настройка |
|---|---|---|
|
содержимое файла |
|
|
содержимое файла |
|
Содержимое GSF_SBT_REPOSITORIES_FILE:
[repositories]
local
repository-1: https://repository.example.org/path/to/repository-1/
repository-2: https://repository.example.org/path/to/repository-2/
Добавьте или удалите строки в соответствии с фактическим количеством репозиториев. Их имена и полные URL определяются конфигурацией используемого менеджера репозиториев.
Содержимое GSF_SBT_CREDENTIALS_FILE:
realm=repository-realm
host=repository.example.org
user=build-user
password=very-secret-password
Пример предполагает, что все SBT-репозитории используют один hostname, realm и одну учетную запись.
Protected-переменные доступны только job-ам из защищенных веток и тегов. Защитите целевую ветку перед запуском
пайплайна.
Не сохраняйте логины и токены в .gitlab-ci.yml. Не запускайте env, printenv и CI_DEBUG_TRACE в job-е с
секретами.
Подробнее о переменных: GitLab CI/CD variables.
3.2. Конфигурация .gitlab-ci.yml#
Создайте файл .gitlab-ci.yml в корне проекта.
Минимальная конфигурация .gitlab-ci.yml для сборки проекта:
stages:
- build
variables:
GSF_CONFIG_FILE: "/opt/global/builds/config.json"
GSF_PROJECT_NAME: "<project_name>"
gsf_build:
stage: build
tags:
- <runner_tag>
timeout: 4h
before_script:
- |
: "${GSF_PROJECT_NAME:?Не задано имя проекта GSF_PROJECT_NAME}"
: "${GSF_SBT_REPOSITORIES_FILE:?Не задана CI/CD variable GSF_SBT_REPOSITORIES_FILE}"
: "${GSF_SBT_CREDENTIALS_FILE:?Не задана CI/CD variable GSF_SBT_CREDENTIALS_FILE}"
test -s "$GSF_SBT_REPOSITORIES_FILE"
test -s "$GSF_SBT_CREDENTIALS_FILE"
test -r "$GSF_CONFIG_FILE"
test -x /opt/global/gsf-cli/config.sh
test -x /opt/global/gsf-cli/manage.sh
umask 077
- install -d -m 700 "$HOME/.sbt" "$HOME/.ivy2"
- install -m 600 "$GSF_SBT_REPOSITORIES_FILE" "$HOME/.sbt/repositories"
- install -m 600 "$GSF_SBT_CREDENTIALS_FILE" "$HOME/.sbt/.credentials"
- install -m 600 "$HOME/.sbt/.credentials" "$HOME/.ivy2/.credentials"
- chmod 600 "$HOME/.sbt/repositories" "$HOME/.sbt/.credentials"
- export SBT_CREDENTIALS="$HOME/.sbt/.credentials"
- export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:+$JAVA_TOOL_OPTIONS }-Dsbt.boot.credentials=$SBT_CREDENTIALS -Dsbt.repository.config=$HOME/.sbt/repositories -Dsbt.override.build.repos=true"
script:
- /opt/global/gsf-cli/config.sh load_config -f "$GSF_CONFIG_FILE"
- /opt/global/gsf-cli/manage.sh -p "$GSF_PROJECT_NAME" refresh || /opt/global/gsf-cli/manage.sh -p "$GSF_PROJECT_NAME" refresh
- /opt/global/gsf-cli/manage.sh -p "$GSF_PROJECT_NAME" build --build-appsrc --skip-publication --publish-path "$CI_PROJECT_DIR/publish"
after_script:
- rm -f "$HOME/.sbt/repositories" "$HOME/.sbt/.credentials" "$HOME/.ivy2/.credentials"
artifacts:
paths:
- publish/applib/
- publish/appsrc/
Если CA-сертификаты менеджера репозиториев или других HTTPS-сервисов хранятся в нестандартном
месте и отсутствуют в наборе CA, доступном requests, укажите читаемый пользователем gitlab-runner PEM-bundle
в переменной REQUESTS_CA_BUNDLE. Переменная должна быть доступна в каждом job-е, который запускает GSF CLI:
variables:
REQUESTS_CA_BUNDLE: "/path/to/company-ca-bundle.pem"
Если сертификаты передаются через GitLab CI/CD variable типа File, сохраните ее, например, как
GSF_CA_BUNDLE_FILE и добавьте в before_script:
- export REQUESTS_CA_BUNDLE="$GSF_CA_BUNDLE_FILE"
- test -r "$REQUESTS_CA_BUNDLE"
Указанный bundle заменяет стандартный набор доверенных CA для requests, поэтому должен содержать все CA,
необходимые для используемых HTTPS-сервисов. Каталог с сертификатами можно указать вместо bundle-файла
только после обработки командой openssl rehash <path-to-ca-directory>. Java truststore cacerts не заменяет эту настройку,
так как GSF CLI выполняет HTTPS-запросы через Python-библиотеку requests.
Если корректную TLS-цепочку нельзя восстановить до запуска pipeline, для временного аварийного режима можно задать:
variables:
GSF_CLI_INSECURE_TLS: "true"
Переменную необходимо удалить сразу после восстановления TLS. Значение true отключает проверку
подлинности HTTPS-сервера для загрузки и публикации артефактов и делает соединение уязвимым для MITM-атак.
Строки с SBT_CREDENTIALS и JAVA_TOOL_OPTIONS обязательны в каждом job-е, который запускает GSF CLI или sbt.
Выполните их в before_script до первой команды сборки. Одного создания файлов .credentials и repositories
недостаточно: JVM должна получить sbt.boot.credentials, sbt.repository.config и sbt.override.build.repos.
В headless-режиме Git не запрашивает данные через терминал, поэтому учетные данные всех используемых Git-хостов должны быть добавлены при настройке runner-а.
Файлы ~/.sbt/repositories, ~/.sbt/.credentials и ~/.ivy2/.credentials существуют только во время job-а. Пример
рассчитан на выделенный runner без параллельных GSF-сборок от одного пользователя.
Флаг --build-appsrc добавляет выполнение publishSrcFolder после publishLibFolder. Оба каталога используют общий
корень, заданный через --publish-path: в примере это $CI_PROJECT_DIR/publish/applib и
$CI_PROJECT_DIR/publish/appsrc. GitLab сохраняет их как job artifacts для последующих шагов pipeline.
В project.yaml параметр isPublishSrcFolder не должен иметь значение false; по умолчанию публикация исходных
артефактов включена.
Один общий --publish-path нельзя использовать с --all: проекты могут перезаписать артефакты друг друга,
поэтому пример собирает один проект через -p.
Команда с --skip-publication не загружает артефакты в удаленный репозиторий, но не мешает формированию
локальных applib и appsrc. Если pipeline должен выполнять Maven-публикацию и другие шаги метода publish,
удалите --skip-publication. В этом случае sbt publish также публикует отдельные *-sources.jar, если
isPublishSrcFolder включен. Параметр --publish-path на адрес Maven-репозитория не влияет.
GSF CLI создает каталоги с JAR-файлами, а не отдельные applib.zip и appsrc.zip. Если следующему этапу нужны
именно ZIP-архивы, упакуйте содержимое обоих каталогов на отдельном шаге CI/CD или передайте их nscli.
GSF_SBT_CREDENTIALS_FILE имеет тип File: GitLab сохраняет содержимое переменной во временный файл, а в переменную
окружения передает путь к нему. Pipeline копирует файл в ~/.sbt/.credentials и ~/.ivy2/.credentials, затем задает
SBT_CREDENTIALS и JAVA_TOOL_OPTIONS.
После полной очистки кешей первый refresh может завершиться ошибкой, частично загрузив зависимости. В примере разрешен
один повторный запуск. Если повторный refresh также завершился ошибкой, job останавливается. На runner-е с прогретым
кешем первый запуск завершается успешно.
3.3. Проверка перед первым запуском#
Перед запуском полного pipeline проверьте:
runner имеет статус
online, настроен какProtected, заблокирован за текущим проектом и содержит tag из.gitlab-ci.yml;ветка или Git tag защищены, иначе job не будет создан, а
Protected-переменные не будут доступны;config.jsonпрошелpython3 -m json.tool, загружен командойload_config, а GSF CLI работает в headless-режиме;credential_manager.sh showсодержит записи всех используемых Git- и репозиторных хостов;сохраненная учетная запись Git имеет права чтения конфигурационного проекта, sbt-плагина и всех Git-модулей;
сохраненная учетная запись менеджера репозиториев имеет права чтения SBT-репозиториев и источника сервера приложения;
GSF_SBT_REPOSITORIES_FILEсодержит все репозитории, необходимые для загрузки sbt, плагинов и зависимостей проекта;GSF_SBT_CREDENTIALS_FILEсодержит актуальные realm, host, логин и пароль;GSF_PROJECT_NAMEточно совпадает с именем проекта в конфигурации GSF CLI;application/project/repositories/default.yamlсодержит актуальные URL и realm для используемой версии sbt-плагина;для сборки
appsrcпараметрisPublishSrcFolderвproject.yamlне равенfalse;системное хранилище и truststore JDK доверяют сертификатам GitLab и менеджера репозиториев;
если CA-сертификаты хранятся в нестандартном месте,
REQUESTS_CA_BUNDLEуказывает на читаемый PEM-bundle или подготовленный каталог с CA-сертификатами;на хосте достаточно свободного места и оперативной памяти для сборки.
Проверьте .gitlab-ci.yml через CI/CD → Editor → Validate. На хосте проверьте ресурсы:
df -h /opt/global
free -h
В закрытой среде проверьте, что applicationServer.source и репозитории в конфигурационном проекте также указывают на
внутренний репозиторий. Дополнительная настройка описана
в главе о сборке в закрытой среде.
После выполнения данного pipeline каталоги publish/applib и publish/appsrc будут загружены в GitLab
как job artifacts.