Кукбук · 2 из 3
Сборка и релиз
Превратить работающий пакет в подписанные артефакты, которые любой может проверить. Ключей тут два, и работу они делают разную — это стоит прочитать до того, как копировать workflow.
Сделать два ключа, один раз
owfeed keygen -o author.pem # EC prime256v1 — подписывает пакеты owfeed keygen --usign -o release.key # usign/ed25519 — подписывает манифест релиза gh secret set OWFEED_AUTHOR_KEY < author.pem gh secret set OWFEED_RELEASE_KEY < release.key git add author.pub.pem release.pub && git commit -m "publish the public halves"
owfeed keygen откажется писать внутрь
него без --force. Запишите id ключей, которые он печатает: фид их спросит.Почему два
| Ключ | Подписывает | Кто проверяет |
|---|---|---|
EC (author.pem) | внутри каждого .apk | кто угодно и когда угодно, по вашей публичной половине |
usign (release.key) | манифест релиза | фид, один раз, когда забирает релиз |
Подпись usign проверяется при приёмке — и на этом всё, за пределы CI фида она не выходит. Подпись EC едет внутри пакета до самого роутера, поэтому тот, кто фиду не доверяет, всё равно может убедиться: собрали это вы. Это единственное утверждение о пакете, которое переживает раздачу через фид, — потому фиды её и требуют.
Собрать обе линии релизов
owlab build --release 25.12.5 # apk, для 25.12 и новее owlab build --release 24.10.8 # ipk, для 24.10 и старее
Обе попадают в dist/<arch>/. Пакет, не зависящий от архитектуры, даёт два
каталога — и это правильно, а не баг: apk требует noarch и отвергает all,
opkg про noarch никогда не слышал.
dist/ ├── noarch/my-app-1.0.0-r1.apk └── all/my-app_1.0.0-r1_all.ipk
Выпуская только под 25.12, вы бросаете всех, кто не обновился, — а на релизе роутеры сидят годами.
luci.mk минифицирует JS и CSS, owlab sync — нет. Код, который работает
неминифицированным и ломается после минификации, не виден, пока кто-нибудь не соберёт пакет.Сначала подпись, потом манифест — именно в таком порядке
owfeed sign --key env:OWFEED_AUTHOR_KEY owfeed release --repo "$GITHUB_REPOSITORY" --tag "$GITHUB_REF_NAME"
Порядок здесь не вкусовщина. owfeed release записывает размер и
sha256 каждого пакета, а подпись дописывает байты в файл. Поменяете местами — манифест будет
описывать файлы, которых больше нет.
owfeed release пишет manifest.txt: что входит в этот релиз, размер и
хеш каждого файла, из какого репозитория и тега он приехал — и подписывает всё это вашим ключом
usign. Репозиторий там не для красоты: подпись доказывает, кто это написал, но никогда — о
чём это. Без той строки манифест, взятый из другого вашего релиза, прекрасно прошёл бы
проверку как этот.
GitHub Actions
.github/workflows/release.yml
name: release
on:
push: { tags: ["v*"] }
permissions: { contents: read }
jobs:
release:
runs-on: ubuntu-latest
permissions: { contents: write }
steps:
- uses: actions/checkout@v5
- uses: owfeed/owlab/setup@v0.5.1
- uses: owfeed/owfeed/setup@v0.5.0
- run: owlab build --release 25.12.5
- run: owlab build --release 24.10.8
- name: Sign the packages, then write the manifest
env:
OWFEED_AUTHOR_KEY: ${{ secrets.OWFEED_AUTHOR_KEY }}
OWFEED_RELEASE_KEY: ${{ secrets.OWFEED_RELEASE_KEY }}
run: |
owfeed sign --key env:OWFEED_AUTHOR_KEY
owfeed release
- run: gh release create "${{ github.ref_name }}" --generate-notes
dist/*/*.apk dist/*/*.ipk dist/manifest.txt*
env: { GH_TOKEN: ${{ github.token }} }
owfeed release сам читает репозиторий и тег из GITHUB_REPOSITORY и
GITHUB_REF_NAME на GitHub и из CI_PROJECT_PATH и
CI_COMMIT_TAG на GitLab, так что флаги нужны только чтобы их перебить.
environment:.GitLab CI
release:
rules:
- if: $CI_COMMIT_TAG
script:
- wget -qO- https://github.com/owfeed/owlab/releases/download/v0.5.1/owlab_0.5.1_linux_amd64.tar.gz | tar xz
- wget -qO owfeed https://github.com/owfeed/owfeed/releases/latest/download/owfeed-linux-amd64
- chmod +x owfeed && export PATH="$PWD:$PATH"
- owlab build --release 25.12.5
- owlab build --release 24.10.8
- owfeed sign --key env:OWFEED_AUTHOR_KEY
- owfeed release
Проверить раньше, чем это сделают другие
owfeed doctor --require-origin
Нумерованные находки, каждая говорит, чем это грозит и что делать. Те, что ловят большинство первых попыток:
| Находка | Что это значит |
|---|---|
arch: all | apk считает такой пакет неустанавливаемым. Пишите LUCI_PKGARCH:=all и дайте сборке перевести это самой — так делает и собственная упаковка OpenWrt. |
| OWF207 | Файл /etc/config/* кладётся, но не объявлен в conffiles:, поэтому sysupgrade молча заменит настройки пользователя вашими дефолтами при каждом обновлении прошивки. |
| Версия отклонена | После ~ apk ждёт хеш коммита, то есть только hex. Пишите 1.0_beta1, а не 1.0~beta. |
| Переводы не видны | LuCI читает скомпилированные .lmo и игнорирует .po. Укажите каталоги в i18n.from:. |