Відтворювані збірки .deb — це основа надійного CI. Щоб ваші пакети не ламалися від різниці версій та залежностей, найкраще будувати їх у ізольованих chroot. Сьогодні покажу, як швидко налаштувати pbuilder і sbuild для Debian/Ubuntu і підключити їх до CI. Обійдемося лише перевіреними підходами, з мінімумом магії, але з максимумом користі 🧪

Що і навіщо: коротко про chroot, pbuilder і sbuild

chroot створює окреме середовище системи з власними пакетами та залежностями. Інструменти pbuilder і sbuild автоматизують таку збірку .deb-пакетів у чітко контрольованих умовах. Це гарантує, що один і той самий вихідний код отримає однаковий результат як локально в термінал Linux, так і на CI.

Основний How-to: готуємо оточення та збираємо

1) Встановлення інструментів

Почнемо з базових linux команди в терміналі. Знадобляться devscripts, debootstrap та самі збирачі.

sudo apt update
sudo apt install -y devscripts debhelper build-essential \
  debootstrap equivs fakeroot lintian \
  pbuilder cowbuilder ubuntu-dev-tools \
  sbuild schroot eatmydata ccache

Рекомендовано налаштувати кеш APT (apt-cacher-ng) для швидших збірок у CI, але це опційно.

2) pbuilder: створюємо базовий chroot і збираємо

pbuilder працює з архівом базової системи (base.tgz) або з copy-on-write (cowbuilder). Дамо мінімальну конфігурацію у файлі користувача:

mkdir -p ~/.pbuilder/hooks
cat > ~/.pbuilderrc <<'EOF'
# Дзеркало та дистрибутив за замовчуванням
MIRRORSITE=http://deb.debian.org/debian
DISTRIBUTION=bookworm
COMPONENTS="main contrib non-free"
DEBOOTSTRAPOPTS=("--variant=buildd")
# Прискорюємо apt у chroot
OTHERMIRROR="deb http://security.debian.org/debian-security bookworm-security main"
# Менше питань під час встановлення
export DEBIAN_FRONTEND=noninteractive
EOF

Створюємо базову систему та оновлюємо її:

sudo pbuilder create --distribution bookworm --debootstrapopts --variant=buildd
sudo pbuilder update

Тепер підготуйте вихідний пакет (зазвичай це репозиторій з debian/). Зберіть сорс-пакет:

debuild -S -us -uc

І зберіть бінарний .deb у chroot через pbuilder:

sudo pbuilder build ../ім'я_пакета_версія.dsc

Якщо любите автоматизацію, використовуйте pdebuild — він сам викличе pbuilder прямо з каталогу проєкту:

pdebuild --pbuilder pbuilder

Порада: для швидких збірок перейдіть на cowbuilder:

sudo cowbuilder --create --distribution bookworm --basepath /var/cache/pbuilder/base.cow
pdebuild --pbuilder cowbuilder

3) sbuild: налаштування schroot та збірка

sbuild — улюбленець CI й офіційних збірок Debian. Готуємо користувача та chroot:

sudo sbuild-adduser "$USER"
newgrp sbuild
sudo sbuild-createchroot --include=eatmydata,ccache \
  bookworm /srv/chroot/bookworm-amd64-sbuild \
  http://deb.debian.org/debian

Створіть простий ~/.sbuildrc для зручності:

cat > ~/.sbuildrc <<'EOF'
# Менше зайвого в логу, швидше apt
$eatmydata = 1;
$build_arch_all = 1;
$build_source = 1;
$verbose = 0;
$purge_build_deps = 1;
$maintainer_name='CI Bot';
$maintainer_email='ci@example.com';
EOF

Збірка з .dsc виглядає так:

sbuild -d bookworm ../ім'я_пакета_версія.dsc

Або напряму з каталогу з debian/: (спочатку сформуйте сорс)

debuild -S -us -uc
sbuild -d bookworm --no-clean-source ../ім'я_пакета_версія.dsc

Плюс sbuild у тому, що він чітко керує залежностями, чистить середовище після збірки й ідеально підходить для автоматизація задач у CI.

4) Підключення до CI (GitHub Actions і GitLab CI)

Приклад GitHub Actions, який збирає пакет у sbuild на Debian:

# .github/workflows/deb.yml
name: Build .deb with sbuild
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install build tools
        run: |
          sudo apt update
          sudo apt install -y devscripts debhelper sbuild schroot debootstrap eatmydata ccache
          sudo sbuild-adduser $USER
          sudo sbuild-createchroot --include=eatmydata,ccache \
            bookworm /srv/chroot/bookworm-amd64-sbuild http://deb.debian.org/debian
      - name: Build source
        run: |
          debuild -S -us -uc
      - name: sbuild
        run: |
          DSC=$(ls ../*.dsc | tail -n1)
          sbuild -d bookworm "$DSC"
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: debs
          path: |
            ../*.deb
            ../*.changes
            ../*.buildinfo

Приклад GitLab CI (образ Debian, збірка через pbuilder):

# .gitlab-ci.yml
image: debian:bookworm
build:deb:
  stage: build
  script:
    - apt-get update
    - apt-get install -y devscripts debhelper pbuilder debootstrap fakeroot
    - pbuilder create --distribution bookworm --debootstrapopts --variant=buildd
    - debuild -S -us -uc
    - pbuilder build ../*.dsc
  artifacts:
    paths:
      - ../*.deb
      - ../*.changes
      - ../*.buildinfo
    expire_in: 1 week

Обидва варіанти повторювані: CI від нуля створює чисте оточення, що позбавляє від "працює тільки на моїй машині" 🚀 Це і є доросла розробка на Linux.

Альтернативні способи

  • cowbuilder (COW-режим pbuilder): значно швидше оновлює chroot; ідеально для локальних і CI-збірок.
  • git-buildpackage (gbp) + sbuild/pbuilder: зручно інтегрує git-історію, теги та pristine-tar.
  • Контейнеризація (Docker на Linux): запуск sbuild/pbuilder всередині контейнерів для повної ізоляції runner-ів; добре масштабується.
  • reprotest: додаткова перевірка відтворюваності збірок.

GUI-спосіб: Open Build Service або Launchpad

Якщо вам зручніше кліком у вебі, спробуйте Open Build Service (OBS) або Launchpad PPA:

  • OBS: створюєте проєкт у веб-інтерфейсі, додаєте вихідні (dsc+orig.tar), обираєте ціль (Debian/Ubuntu) — система сама збере пакет. Зручно для команд і швидкого поширення.
  • Launchpad PPA: публічні або приватні PPA, керування через веб, збирання на інфраструктурі Canonical. Потрібен підписаний GPG сорс-пакет (dput), але далі все видно у GUI.

GUI-підхід підходить, коли CI ще не готовий або потрібен легкий шлях розповсюдження тестових збірок.

FAQ

Чим відрізняються pbuilder і sbuild?

pbuilder простіший і відмінно підходить для локальних збірок та базового CI. sbuild має точніший контроль залежностей, кращі логи, типовий для офіційних билд-ферм Debian і надійніший у масштабі.

Проблеми з залежностями (E: Unable to find ...)?

Перевірте Build-Depends у debian/control, відповідність дистрибутива (-d bookworm/jammy), наявність секцій (main/contrib/non-free) у chroot та джерела security/updates.

Як чистити або оновлювати chroot?

pbuilder: sudo pbuilder update. Для cowbuilder: sudo cowbuilder --update --basepath /var/cache/pbuilder/base.cow. sbuild: перевідтворити через sbuild-createchroot або оновити sources.list всередині schroot і запустити apt-get update/upgrade.

Помилка прав доступу у sbuild (permission denied)?

Додайте користувача до групи sbuild (sudo sbuild-adduser $USER) і перелогіньтесь (newgrp sbuild або перезапустіть сесію).

Як збирати для інших архітектур (armhf, arm64)?

Використовуйте qemu-user-static у chroot або builder-и з крос-збіркою. Для sbuild додайте --arch=arm64 і підготуйте відповідний chroot.

Як прискорити збірки?

Увімкніть eatmydata, ccache, використовуйте локальний apt-кеш (apt-cacher-ng), обирайте cowbuilder, кешуйте артефакти CI.

Як зробити збірки більш відтворюваними?

Фіксуйте версії залежностей, очищайте середовище, використовуйте SOURCE_DATE_EPOCH, перевіряйте reprotest, не тягніть мережеві артефакти під час build.

Порада від Kernelka

Для CI я б обрала sbuild як основний інструмент, а cowbuilder — для швидких локальних перевірок. Тримайте окремі chroot-и під різні релізи (bookworm, jammy), додавайте lintian у пайплайн, а ще — заведіть прості bash скрипти, щоб однаковими linux команди будити збірку локально і на CI. Так ви уникнете дрібних розсинхронів між середовищами.

Підсумок

  • Будуйте .deb у chroot через pbuilder або sbuild — це стабільність і відтворюваність.
  • sbuild краще масштабується для CI; pbuilder простіший для старту.
  • Автоматизуйте збірку в CI: створюйте chroot з нуля у пайплайні.
  • Прискорюйте збірки eatmydata, ccache, apt-кешем і cowbuilder.
  • GUI-альтернатива: OBS або Launchpad PPA для швидкого поширення.
  • Тестуйте відтворюваність і фіксуйте залежності — так ваші релізи будуть передбачуваними.