Files
MeshCore/ci/README.md
T
shade e4b8e4e820
Firmware build / release (push) Canceled after 0s
Firmware build / build (push) Canceled after 36m29s
CI: локальная сборка прошивок с публикацией релиза в Gitea
2026-10-11 14:15:38 +03:00

195 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CI: автоматическая сборка прошивок на своём Gitea
Схема: **Gitea (systemd) → Gitea Runner на том же сервере → PlatformIO → артефакты `out/`**.
Сборка идёт через `build.sh` из репозитория, то есть тем же путём, что и локально
(версия прошивки, `merge-bin` для ESP32, `.uf2` для nRF52), — логика не дублируется.
## Что где лежит
| Файл | Назначение |
|---|---|
| `.gitea/workflows/firmware.yml` | workflow: клон, кэш, сборка, артефакты, черновик релиза по тегу |
| `ci/build-firmwares.sh` | сборка выбранного набора env (годится и для запуска руками) |
| `ci/act_runner/gitea-runner.service` | systemd-юнит раннера |
| `ci/act_runner/config.yaml` | конфиг раннера: ёмкость, таймаут, кэш |
| `ci/act_runner/docker-compose.yml` | альтернатива: раннер в Docker |
## 1. Что должно быть на сервере
```bash
apt-get update
apt-get install -y git python3 python3-venv python3-pip curl ca-certificates build-essential
```
- **`python3-pip` обязателен.** Без него `python3 -m venv` создаёт окружение **без pip**
(в `bin/` только симлинки python), и шаг установки PlatformIO падает с
`No such file or directory`. Если venv уже создан без pip, workflow пересоздаст его сам.
- Свободного места нужно **5 ГБ**: тулчейны PlatformIO занимают ~800 МБ на одну платформу,
а при сборке и ESP32, и nRF52 — заметно больше.
- **Swap желателен.** На VPS с 2 ГБ RAM линковка ESP32 упирается в память:
```bash
fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
```
## 2. Включение Actions в Gitea
В `/etc/gitea/app.ini` (владелец `git:git`, права 600):
```ini
[actions]
ENABLED = true
# Gitea 1.27 принимает значение github или gitea, но НЕ ссылку:
# "https://github.com" даёт ошибку DEFAULT_ACTIONS_URL does not support ...
DEFAULT_ACTIONS_URL = github
# Искать workflow только в .gitea/workflows: иначе Gitea подхватит upstream-файлы
# из .github/workflows, а у них триггер push — на каждый push запустится сборка
# сотен env и деплой Pages.
WORKFLOW_DIRS = .gitea/workflows
```
После правки: `systemctl restart gitea`. Перед изменением делайте копию конфига —
`cp -a /etc/gitea/app.ini /etc/gitea/app.ini.bak`.
## 3. Установка раннера (systemd)
```bash
useradd --create-home --home-dir /var/lib/act-runner --shell /bin/bash act-runner
# актуальный релиз: https://gitea.com/gitea/runner/releases
# (проект переименован: раньше act_runner, теперь Gitea Runner; на момент настройки — v5.0.0)
curl -fsSL -o /usr/local/bin/gitea-runner \
https://gitea.com/gitea/runner/releases/download/v5.0.0/gitea-runner-5.0.0-linux-amd64
chmod +x /usr/local/bin/gitea-runner
gitea-runner --version
install -d -o act-runner -g act-runner /var/lib/act-runner
cp ci/act_runner/config.yaml /var/lib/act-runner/config.yaml
chown act-runner:act-runner /var/lib/act-runner/config.yaml
```
**Токен — обязательно со scope репозитория.** Без `--scope` раннер становится глобальным
и начинает брать задачи **всех** репозиториев инстанса (в том числе чужие stale-bot):
```bash
# от имени пользователя Gitea (CLI не работает под root)
su - git -c "gitea actions generate-runner-token -c /etc/gitea/app.ini --scope shade/MeshCore" \
> /var/lib/act-runner/reg-token
chown act-runner:act-runner /var/lib/act-runner/reg-token && chmod 600 /var/lib/act-runner/reg-token
su - act-runner -c "/usr/local/bin/gitea-runner register --no-interactive \
--instance https://git.meshinfo.ru \
--token-file /var/lib/act-runner/reg-token \
--name meshcore-builder \
--labels ubuntu-latest:host \
-c /var/lib/act-runner/config.yaml"
rm -f /var/lib/act-runner/reg-token # токен больше не нужен
```
Метка `ubuntu-latest:host` означает, что шаги выполняются **прямо на сервере** — без Docker,
но зависимости ставятся в систему. Метка должна совпадать с `runs-on` в workflow.
```bash
cp ci/act_runner/gitea-runner.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now gitea-runner
systemctl status gitea-runner
journalctl -u gitea-runner -f # ждём "declare successfully"
```
### Альтернатива: раннер в Docker
```bash
cd ci/act_runner && cp .env.example .env && nano .env && docker compose up -d
```
В свежих версиях образ называется `gitea/runner` (раньше `gitea/act_runner`).
## 4. Запуск сборки
- **Автоматически** — push в `main` (кроме изменений в `*.md`, `ci/**`, `.preview/**`).
- **Вручную** — Actions → Firmware build → Run workflow (`targets`, `match`, `version`),
либо через API:
```bash
curl -X POST -H "Authorization: token $GITEA_TOKEN" -H 'Content-Type: application/json' \
-d '{"ref":"main","inputs":{"targets":"Heltec_t096_companion_radio_ble","version":"ci"}}' \
https://git.meshinfo.ru/api/v1/repos/shade/MeshCore/actions/workflows/firmware.yml/dispatches
```
- **Локально** — тем же скриптом, что запускает CI:
```bash
FIRMWARE_VERSION=v1.0.0 bash ci/build-firmwares.sh
MATCH=promicro bash ci/build-firmwares.sh
TARGETS="Heltec_t096_companion_radio_ble" bash ci/build-firmwares.sh
```
Готовые файлы попадают в `out/` (каталог в `.gitignore`) и прикрепляются к запуску
workflow как артефакт `firmware`.
### Локально на Windows, без нагрузки на сервер
На этом VPS всего 1 CPU, поэтому полный набор прошивок собирается там часами. Разумнее
собрать у себя, а на сервер отправить только готовые файлы — релизом Gitea:
```powershell
# быстрый набор: все env, в имени которых есть подстрока
.\ci\build-local.ps1 -Match promicro -Version v1.0.0
# полный набор из DEFAULT_TARGETS
.\ci\build-local.ps1 -Version v1.0.0
# собрать и прикрепить к релизу (черновик; -Public опубликует сразу)
$env:GITEA_TOKEN = '<токен с правом write:repository>'
.\ci\build-local.ps1 -Version v1.0.0 -Publish -Tag companion-v1.0.0
```
Скрипт находит Git Bash и PlatformIO, подставляет рабочий `python3` (в Git Bash это
заглушка Microsoft Store — из-за неё `build.sh` не может определить платформу env),
чистит `out/` перед сборкой, а с `-Publish` создаёт тег, черновик релиза и прикрепляет
к нему файлы. Токен нужен только для публикации: сама сборка работает без него.
На Linux/macOS то же самое делается напрямую: `FIRMWARE_VERSION=v1.0.0 bash ci/build-firmwares.sh`.
## 5. Релизы по тегу
Пуш тега `v1.0.0` или `companion-v1.0.0` собирает набор и создаёт **черновик релиза**
с прикреплёнными `.bin` / `.uf2` / `.zip`. Версия берётся из тега
(`companion-v1.2.3` → `v1.2.3`) и попадает в имена файлов (`<env>-v1.2.3-<sha>.uf2`).
```bash
git tag companion-v1.0.0 && git push origin companion-v1.0.0
# затем: репозиторий → Releases → черновик → Publish
```
Публикация идёт автоматическим `secrets.GITHUB_TOKEN` (в workflow стоит
`permissions: contents: write`). Если релизы не создаются — заведите секрет
`RELEASE_TOKEN` с правом `write:repository` и подставьте его в шаге «Черновик релиза».
## 6. Набор прошивок по умолчанию
`ci/build-firmwares.sh`, массив `DEFAULT_TARGETS`: T096 (companion, repeater, room server,
sensor), ProMicro (SSD1306, SH1106, repeater, room server), Heltec v3, heltec_v4 TFT,
tracker_v2, T-Deck, T-Echo Card, T114, T190, M9 и три варианта Meshadventurer.
## 7. Время и ресурсы
- Сервер с **1 CPU / 2 ГБ RAM** полный набор собирает долго (первый прогон — часы),
и на время сборки Gitea с Postgres на той же машине заметно тормозят.
Разумно запускать полный набор вручную, а на push держать 2–3 env.
- Первая сборка качает тулчейны (nRF52: framework + CMSIS + gcc-arm ≈ 660 МБ;
ESP32 — ещё столько же), дальше работает кэш `~/.platformio`.
- `capacity: 1` в `config.yaml` — одна сборка за раз.
## 8. Грабли, на которые уже наступали
| Симптом | Причина и решение |
|---|---|
| `.../bin/pip: No such file or directory` | venv создан без pip — нет `python3-pip`; поставить пакет, venv пересоздать |
| `DEFAULT_ACTIONS_URL does not support "https://github.com"` | в Gitea 1.27 значение — `github`, не ссылка |
| раннер берёт задачи чужих репозиториев | токен выдан без `--scope owner/repo` |
| `registration file not found` в цикле рестартов | раннер запущен до регистрации: сначала `register`, потом сервис |
| `E: Could not get lock /var/lib/dpkg/lock-frontend` | работает unattended-upgrades; подождать либо остановить `apt-daily.timer` |
| на push запускается сборка сотен env | не выставлен `WORKFLOW_DIRS = .gitea/workflows` |
| `405 Method Not Allowed` при создании тега | в Gitea тег создаётся через `POST /repos/{owner}/{repo}/tags`, у `/git/refs` метода POST нет |
| `python3: command not found` или пустой вывод в Git Bash | это заглушка Microsoft Store; задайте `PYTHON3=/c/.../python.exe` (это делает `ci/build-local.ps1`) |