Создание и публикация приложения в Launchpad

Последнюю неделю я активно стал разрабатывать небольшое приложение epever-tracer-influxdb. Оно позволяет читать параметры солнечного контроллера и отправлять данные в InfluxDB. Само приложение написано на C и предполагается, что оно будет работать на Raspberry PI. После того как я написал это приложение передо мной в очередной раз встала задача дистрибуции. Самый простой способ - попытаться добавить его в основной репозиторий Debian. Но тут есть несколько проблем:

  • непонятно в какой момент пакет окажется в основном репозитории. Если мне, скажем, необходимо завтра начать использовать его, то мне точно не хочется ждать пока open source бюрократия пережуёт моё приложение
  • что-то мне подсказывает, что нужно сделать очень много неявных приседаний прежде, чем моё приложение будет “каноничным” debian приложением. Это, конечно, полезно, но я не готов тратить сразу много времени на это.

Все эти проблемы решает Launchpad. Специальный сервис для хостинга своих персональных apt репозиториев. Это не первое моё приложение, которое я решил разместить там. До этого я размещал там apt-transport-swift.

Подготовка

Прежде, чем начать подготавливать приложение, необходимо знать одну важную деталь. На ней в документации нет сильного акцента и для новичка это может стать откровением. В debian/ubuntu мире есть очень чёткое различие между “оригинальным” приложением и “дебинизированным”. Оригинальное приложение - это фактически исходники приложения и то, что предоставляет разработчик приложения. “дебинизированное” приложение - это исходники (или .tar.gz) и метаинформация о самом приложении, необходимые скрипты для сборки и разворачивания его в операционной системе. Эту особенность необходимо постоянно держать в голове. Это особенно важно, если ты являешься одновременно разработчиком приложения и мейнтейнером.

Общая схема работы

PPA - это personal package archives. По сути репозиторий, где можно хранить свои собственные сборки разных пакетов или собственные приложения. Работает это следующим образом:

source code
.tar.gz
source code...
dev
dev
build agent
build agent
i386
i386
amd64
amd64
i386
i386
Launchpad
Launchpad
Text is not SVG - cannot display
  1. Разработчик подготавливает пакет и исходные коды.
  2. Эти исходные коды заливаются в launchpad
  3. Launchpad начинает их собирать для разных архитектур и
  4. Выкладывает в персональный apt репозиторий

В самом Launchpad есть гигантская билд ферма, которая постоянно собирает новые пакеты под разные архитектуры. Очень круто и удобно. Понятное дело, что они поддерживают только open source проекты.

Погнали

Во-первых, необходимо создать аккаунт.

Во-вторых, в своём профиле на launchpad необходимо создать новый PPA. Тут опять всё очевидно.

В-третьих, необходимо привязать к своему аккаунту PGP ключ. Тут всё не так очевидно, но есть хороший мануал о том, как это сделать. В последствии этот ключ будет использоваться для того, чтобы подписать пакет и залить его launchpad.

Подготовка пакета

Для того чтобы собрать пакет, необходимо описать некоторую мета-информацию. Для этого необходимо создать папку debian в корне проекта. Я подробно не буду описывать каждый из необходимых файлов. Достаточно посмотреть пример того, как это сделано для epever-tracer-influxdb. Для разных приложений набор необходимых файлов может быть разный.

Локальная сборка пакета

Тут всё немножко сложнее. Поскольку я разрабатываю на маке, у меня нет всех необходимых инструментов, чтобы собирать .deb пакеты. В моём случае необходимо делать дополнительные шаги:

  • создать виртуалку в облаке
  • скопировать свои pgp ключи на виртуалку

После всего этого необходимо установить пакеты:

sudo apt-get install devscripts build-essential lintian

Создать архив с оригинальными исходными кодами:

tar czf epever-tracer-influxdb_1.0.0.orig.tar.gz epever-tracer-influxdb

Тут очень важно то, как называется этот архив. В нём обязательно должна быть версия и .orig.tar.gz. Скрипты сборки будут искать архив именно с таким именем.

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

debuild -i -us -uc -b

Также эта команда запускает lintian - линтер для .deb пакетов. Он очень продвинутый и может находить достаточно странные ошибки:

W: epever-tracer-influxdb: debian-changelog-has-wrong-day-of-week 2020-03-23 is a Monday
W: epever-tracer-influxdb: new-package-should-close-itp-bug
E: epever-tracer-influxdb: bad-permissions-for-etc-cron.d-script etc/cron.d/epeverTracerCron 0755 != 0644

По коду ошибки можно найти достаточно полное описание с вариантами исправления. Например, debian-changelog-has-wrong-day-of-week говорит о том, что в changelog файле у меня неправильный день недели. И это правда, потому что changelog был скопирован из другого проекта.

После того как сборка прошла успешно, можно собирать .changes файл. Для этого необходимо выполнить команду:

debuild -S -sa

Эта команда создаст несколько файлов директорией выше и подпишет их pgp ключом.

Публикация

Теперь всё готово, чтобы публиковать файлы в launchpad. Для этого нужно перейти на директорию выше и вызывать команду:

dput ppa:rodionovamp/epever-tracer-influxdb epever-tracer-influxdb_1.0.0-3_source.changes

Название PPA и файла .changes, конечно же, необходимо изменить на свои. Если всё прошло успешно, то launchpad пришлёт письмо:

[~rodionovamp/ubuntu/epever-tracer-influxdb/disco] epever-tracer-influxdb 1.0.2-5 (Accepted)

Это значит, что исходники получены и готовы к сборке. Статус сборки можно посмотреть в PPA. После того как собраны все пакеты для всех архитектур, они могут быть доступны для установки:

sudo add-apt-repository ppa:rodionovamp/epever-tracer-influxdb
sudo apt-get update
sudo apt-get install epever-tracer-influxdb

Что может пойти не так

Почти всё может пойти не так. Из-за того, что почти вся сборка основана на различных скриптах и негласных конвенциях, сломаться может любой из шагов выше. Я собрал очень много ошибок и потратил на их решение пару дней.

dpkg-source: info: building epever-tracer-influxdb using existing ./epever-tracer-influxdb_1.0.0.orig.tar.gz
dpkg-source: error: cannot represent change to docs/screen1.png: binary file contents changed

Почти всегда необходимо пересоздавать .orig.tar.gz после получения новых исходников из гита.

Rejected:
File epever-tracer-influxdb_1.0.0.orig.tar.gz already exists in epever-tracer-influxdb, but uploaded version has different contents. See more information about this error in https://help.launchpad.net/Packaging/UploadErrors.

Нельзя залить один и тот же архив с исходниками два раза. Даже если первый не собрался или в нём ошибка. При небольшом изменении исходников необходимо менять минорную версию и заново создавать архив.

Files specified in DSC are broken or missing, skipping package unpack verification.

debuild почему-то при ошибке подписывания исходников не падает, а продолжает работу. Если такие исходники попытаться залить в launchpad, то возникают странные ошибки.

* State: Failed to build
* Duration: 2 minutes
* Build Log: ....

Для старых дистрибутивов уже нельзя собрать проект.

Rejected:
disco is obsolete and will not accept new uploads.

epever-tracer-influxdb (1.0.3-2) disco; urgency=medium

То, что собралось на Mac OS необязательно соберётся на Ubuntu. Необходимо локально собирать проект и прогонять все тесты.

Выводы

  • Очень много негласных конвенций и скриптов для сборки deb пакетов. Возможно, это связано с большим наследием самой системы. Возможно, это связано со сложностью поддержки такого большого количества пакетов в консистентном состоянии.
  • Как следствие, нужно много читать или много тратить времени, чтобы исправить все ошибки деплоя
  • Из плюсов, бесплатный хостинг вашего маленького приложения в публичном месте. Хотя я, конечно же, предпочёл что-нибудь посовременнее и проще.