# Подготовка GitLab Runner и Jenkins Agent

Эта глава нужна для сборки в CI. Выберите GitLab или Jenkins и подготовьте агент на выделенном Linux-хосте. Команды ниже
рассчитаны на Debian-подобную систему. Для локальной сборки сразу переходите к [Linux](036_linux_setup.md) или [Windows](037_windows_setup.md).

Агент выполняет команды от своего пользователя. Позже этому же пользователю понадобятся рабочий каталог GSF CLI,
мастер-ключ и учётные данные. Не настраивайте их от `root`, если job работает от другой учётной записи.

## GitLab Runner

В этом варианте используется `shell` executor. Он имеет доступ к постоянному workspace и сохранённым credentials. Такой
runner подходит для доверенного проекта и защищённых веток.

### Создание runner в GitLab

1. Откройте проект и перейдите в `Settings` → `CI/CD` → `Runners`.
2. Нажмите **New project runner**. Задайте описание и tag, например `gsf-build`.
3. Отключите **Run untagged jobs**.
4. После создания включите **Protected** и **Lock to current projects**. Runner будет обслуживать защищённые ветки и
   теги только назначенного проекта.

Сохраните предложенную GitLab команду регистрации с токеном вида `glrt-...`. Этот токен подключает runner к GitLab; для
доступа GSF CLI к исходникам позднее используются отдельные учётные данные.

### Установка на хосте

Уточните версию GitLab у администратора. Выберите GitLab Runner с теми же `major.minor` и задайте полный тег версии
вместо `v<gitlab-major.minor.patch>`, например `v18.0.3` для соответствующей установки GitLab.

Выполните от пользователя с правом `sudo`:

```bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl git

RUNNER_VERSION="v<gitlab-major.minor.patch>"
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

sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
gitlab-runner --version
sudo gitlab-runner status
```

Бинарный файл в примере предназначен для `amd64`. В закрытой сети заранее доставьте эту же версию через разрешённый
внутренний репозиторий. Системные пакеты тоже должны быть доступны внутри контура.

Порядок ручной установки описан в [документации GitLab](https://docs.gitlab.com/runner/install/linux-manually/).

### Корпоративный сертификат GitLab

Если GitLab использует сертификат внутреннего центра сертификации, настройте доверие до регистрации runner. Если
внутренний сертификат нужен уже для загрузки установочных файлов, выполните этот шаг до загрузки.

Получите корневой и промежуточные CA-сертификаты в формате PEM. Добавьте каждый сертификат отдельным файлом с
расширением `.crt`:

```bash
sudo install -m 0644 /path/to/company-root-ca.crt \
  /usr/local/share/ca-certificates/company-root-ca.crt
sudo update-ca-certificates
```

Повторите команду `install` для промежуточных CA, если они нужны, и снова выполните `update-ca-certificates`.

При ошибке `x509: certificate signed by unknown authority` дополнительно передайте цепочку CA самому runner:

```bash
sudo install -d -m 0755 /etc/gitlab-runner/certs
sudo install -m 0644 /path/to/gitlab-ca-chain.pem \
  /etc/gitlab-runner/certs/gitlab.example.org.crt
sudo systemctl restart gitlab-runner.service
```

Имя файла должно совпадать с hostname GitLab, без номера порта. Замените `gitlab.example.org` своим именем сервера. Не
используйте `GIT_SSL_NO_VERIFY` вместо установки сертификата.

Подробнее — [сертификаты GitLab Runner](https://docs.gitlab.com/runner/configuration/tls-self-signed/).

### Регистрация и ограничение параллельных заданий

Выполните команду, полученную при создании runner. Пример:

```bash
sudo gitlab-runner register \
  --config /etc/gitlab-runner/config.toml \
  --url "https://gitlab.example.org" \
  --token "<runner-authentication-token>"
```

Укажите имя runner и выберите executor `shell`. Метки задайте в настройках runner в GitLab; если диалог регистрации
запросит tag, используйте ту же метку.

Путь `--config` в этой инструкции указывается явно: сервис должен читать тот же `/etc/gitlab-runner/config.toml`, в
который записана регистрация. Не смешивайте системную конфигурацию и конфигурацию в домашнем каталоге пользователя.

Откройте файл:

```bash
sudoedit /etc/gitlab-runner/config.toml
```

Установите следующие значения в существующей конфигурации:

```toml
concurrent = 1

[[runners]]
limit = 1
executor = "shell"
```

Не заменяйте этим фрагментом весь файл и не добавляйте второй блок `[[runners]]` для уже зарегистрированного runner.
Сохраните сгенерированные `url`, `token` и остальные параметры.

```bash
sudo gitlab-runner verify
sudo systemctl restart gitlab-runner.service
sudo systemctl --no-pager --full status gitlab-runner.service
```

Ограничение нужно для общего workspace `/opt/global/gsf-cli/workspace`: две сборки не должны одновременно менять его
содержимое и файлы credentials одного пользователя.

Справка GitLab: [регистрация](https://docs.gitlab.com/runner/register/)
и [настройки runner](https://docs.gitlab.com/runner/configuration/advanced-configuration/).

### Проверка runner

Защитите тестовую ветку в GitLab. Создайте в ней `.gitlab-ci.yml`, указав свой tag:

```yaml
test-job:
  tags:
    - gsf-build
  script:
    - test "$(whoami)" = "gitlab-runner"
    - test "$HOME" = "/home/gitlab-runner"
    - git --version
```

Runner должен быть `online`, а job — завершиться успешно. Если job остаётся в ожидании, проверьте tag и защиту ветки:
защищённый runner не берёт задания из обычной незащищённой ветки.

При ошибке подготовки окружения:

```text
Preparing the "shell" executor
Using Shell (bash) executor...
Preparing environment
ERROR: Job failed: prepare environment: exit status 1
```

проверьте `/home/gitlab-runner/.bash_logout`. Если там есть блок очистки консоли, закомментируйте его:

```bash
if [ "$SHLVL" = 1 ]; then
    [ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
fi
```

Перезапустите сервис:

```bash
sudo systemctl restart gitlab-runner.service
```

Причина описана в разделе GitLab о [загрузке профиля shell](https://docs.gitlab.com/runner/shells/#shell-profile-loading).

После проверки переходите к [установке GSF CLI на Linux](036_linux_setup.md). Используйте там пользователя
`gitlab-runner`; конфигурация сборочного pipeline находится в конце этой же главы Linux.

## Jenkins Agent

Здесь агент подключается к Jenkins по SSH. На хосте уже должен быть пользователь, под которым Jenkins сможет открыть
SSH-соединение. Его имя заменяет `<agent_user>` в командах ниже.

### Рабочий каталог и Java

Создайте каталог и передайте его пользователю агента:

```bash
GSF_AGENT_USER="<agent_user>"
GSF_AGENT_GROUP="$(id -gn "$GSF_AGENT_USER")"
sudo mkdir -p /opt/JenkinsSlave
sudo chown -R "$GSF_AGENT_USER:$GSF_AGENT_GROUP" /opt/JenkinsSlave
```

Для агента и прикладной сборки используйте **JDK 21**. Если в репозитории вашей ОС доступен OpenJDK 21:

```bash
sudo apt-get update
sudo apt-get install -y openjdk-21-jdk git
/usr/lib/jvm/java-21-openjdk-amd64/bin/java -version
```

Если такого пакета нет, установите JDK 21 из принятого в вашей организации дистрибутива и используйте его фактический
путь. В закрытой сети установочные файлы должны быть доставлены заранее.

Версия Jenkins должна поддерживать запуск на Java 21; требования распространяются и на агент. Таблица совместимости
приведена в [политике Java для Jenkins](https://www.jenkins.io/doc/book/platform-information/support-policy-java/).

### Подключение узла

В интерфейсе Jenkins создайте новый узел и выберите тип **Постоянный агент**. Заполните параметры:

| Параметр                      | Значение                                                     |
|-------------------------------|--------------------------------------------------------------|
| Удалённая корневая директория | `/opt/JenkinsSlave`                                          |
| Метки                         | Например, `gsf-build`                                        |
| Использование                 | Собирать только проекты с метками, совпадающими с этим узлом |
| Способ запуска                | `Launch agents via SSH`                                      |
| Host                          | Адрес подготовленного хоста                                  |
| Credentials                   | SSH-учётные данные пользователя `<agent_user>`               |
| Число исполнителей            | `1` для общего workspace GSF CLI                             |

В **Advanced…** укажите нестандартный SSH-порт, если используется не `22`. В поле **JavaPath** задайте путь к Java 21,
особенно если на хосте установлены несколько JDK:

```text
/usr/lib/jvm/java-21-openjdk-amd64/bin/java
```

Сохраните узел, откройте его и нажмите **Launch agent**. После успешного подключения проверьте журнал агента и его
статус в Jenkins.

Переходите к [установке GSF CLI на Linux](036_linux_setup.md), сохранив пользователя агента. В конце главы приведён
пример сборочного задания Jenkins с сохранением `applib` и `appsrc`.
