Сборка в конвейере

Сборка в конвейере#

Все инструменты AFT рассчитаны на запуск без участия человека: параметры задаются манифестом, результат возвращается кодом выхода, отчёты пишутся в файлы. Поэтому полный цикл собирается в конвейер: проверить описание, собрать, проверить результат, найти уязвимости и опубликовать.

Порядок шагов#

Проверка манифеста идёт первой и не требует ни прав администратора, ни сборки:

aft-app validate app.yaml

Код возврата 0 означает, что ошибок нет, 1 - что манифест не принят. Проверка разбирает манифест теми же правилами, что и сборка, поэтому ловит опечатку в имени поля, значение неподходящего типа, одиночное значение там, где ожидается список, и секцию источника, не совпадающую с заявленным типом. В сообщении указывается путь до поля и номер строки, а при опечатке предлагается близкое по написанию имя. Шаг дешёвый и снимает большую часть ошибок до того, как будет занята сборочная машина.

Сборка меняет систему и требует прав администратора:

sudo aft-app build app.yaml

Результат ложится в каталог, заданный секцией export. Ненулевой код выхода означает, что сборка не удалась.

Проверка результата выполняется анализатором. Он работает с уже установленным приложением, поэтому сборку сначала нужно установить из полученного репозитория:

sudo flatpak remote-add --if-not-exists --no-gpg-verify ci-repo ./repo
sudo flatpak install -y ci-repo ru.example.MyApp
aft-analyzer ru.example.MyApp --format=json --report=./report

Анализатор возвращает 0 при успехе, 1 при предупреждениях и 2 при ошибках. Флаг --no-exit-code заставляет его всегда возвращать 0, если конвейер не должен падать на предупреждениях. Набор проверок сужается флагом --checkers со списком через запятую: Manifest, Desktop, Icon, AppStream, Export, Permission, Binary, Xattr, Library, Environment, Signature, Bsign, DBus.

Поиск уязвимостей запускается отдельным инструментом или прямо из сборки:

aft-scanner scan ru.example.MyApp --fail-on=high --format=json,html \
    --output-dir=./report

Встроенный в сборку вариант описывается секцией build.scan манифеста и отрабатывает последним, уже после экспорта:

build:
  scan:
    enabled: true
    failOn: high
    strict: true
    severities: [critical, high]
    ignoreCves: [CVE-2023-0001]

Поле strict делает найденные уязвимости причиной неуспеха сборки. Без него находки попадают в отчёт, но сборка считается успешной.

Состав ПО формируется сборкой автоматически, если включено поле build.sbom. Получить состав уже установленного приложения отдельно можно так:

aft-flatpak-sbom ru.example.MyApp -o myapp.cdx.json

Подпись#

Подписей две, и они независимы.

Подпись репозитория ключом GPG задаётся полями export.gpgSign и export.gpgHomedir. Без неё пользователю придётся подключать репозиторий с отключённой проверкой.

Подпись исполняемых файлов средствами bsign нужна для замкнутой программной среды Astra Linux и настраивается секцией build.bsign. Пароль ключа в конвейере передаётся файлом, чтобы подпись не требовала ввода:

build:
  bsign:
    enabled: true
    key: 0123456789ABCDEF0123456789ABCDEF01234567
    passphraseFile: /run/secrets/bsign-pass
    elfOnly: true

Файл с паролем не хранится в репозитории с исходниками, а подставляется механизмом секретов конвейера.

Воспроизводимость#

Плавающие версии делают сборку невоспроизводимой. Версия пакета закрепляется полем source.repository.version, версия среды выполнения указывается точным номером ветки, а не значением вроде stable.

Кэш скачанных пакетов лежит в каталоге build.cacheDir. На сборочной машине его имеет смысл сохранять между запусками, чтобы не скачивать одно и то же, но при закреплении версий кэш не подменяет запрошенную версию тем, что в нём уже лежит.

Один манифест может описывать несколько сборок: документы разделяются строкой --- и собираются по очереди. Это удобно, когда одно и то же приложение собирается под несколько линий или архитектур, и позволяет держать все варианты в одном файле.