CI: сборка прошивок только по ручному запуску

This commit is contained in:
2026-10-11 15:18:50 +03:00
parent 819b140a90
commit d55129160f
3 changed files with 37 additions and 107 deletions
+5 -78
View File
@@ -2,21 +2,11 @@ name: Firmware build
# Сборка прошивок на своём Gitea-раннере (метка ubuntu-latest, см. ci/README.md).
#
# push в main — собрать набор прошивок и выгрузить артефакты
# push тега — то же плюс черновик релиза с прикреплёнными файлами
# вручную — можно задать targets / match / version
# Запуск ТОЛЬКО вручную: Actions → Firmware build → Run workflow, либо через API
# (пример запроса — в ci/README.md). Автоматических сборок по push и тегам нет:
# прошивки собираются локально (ci/build-local.ps1) и публикуются релизом в Gitea.
on:
push:
branches:
- main
tags:
- 'v*'
- '*-v*'
paths-ignore:
- '**/*.md'
- '.preview/**'
- 'ci/**'
workflow_dispatch:
inputs:
targets:
@@ -32,9 +22,6 @@ on:
required: false
default: ''
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
@@ -72,14 +59,8 @@ jobs:
- name: Версия прошивки
run: |
# тег вида companion-v1.2.3 даёт версию v1.2.3; иначе — значение из запуска
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
TAG="${GITHUB_REF#refs/tags/}"
VERSION="${TAG##*-}"
else
VERSION="${{ github.event.inputs.version }}"
[[ -z "$VERSION" ]] && VERSION="ci"
fi
VERSION="${{ github.event.inputs.version }}"
[[ -z "$VERSION" ]] && VERSION="ci"
echo "FIRMWARE_VERSION=$VERSION" >> "$GITHUB_ENV"
echo "версия: $VERSION"
@@ -96,57 +77,3 @@ jobs:
name: firmware
path: out/
if-no-files-found: warn
release:
needs: build
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Скачивание артефактов
uses: actions/download-artifact@v4
with:
name: firmware
path: out
- name: Черновик релиза
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG="${GITHUB_REF#refs/tags/}"
API="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
if [[ -z "${TOKEN:-}" ]]; then
echo "Нет токена для Gitea API (secrets.GITHUB_TOKEN пуст)" >&2
exit 1
fi
echo "файлы к релизу:"
ls -1 out
# черновик: релиз создаётся, но не публикуется — проверить и нажать Publish
RESPONSE=$(curl -fsS -X POST "$API/releases" \
-H "Authorization: token $TOKEN" \
-H 'Content-Type: application/json' \
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\",\"draft\":true,\"prerelease\":false,\"target_commitish\":\"$GITHUB_SHA\"}")
# id разбираем питоном: в ответе есть и другие поля id (автор, вложения)
RELEASE_ID=$(printf '%s' "$RESPONSE" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
if [[ -z "$RELEASE_ID" ]]; then
echo "Не удалось создать релиз для тега $TAG" >&2
exit 1
fi
echo "релиз #$RELEASE_ID создан (черновик)"
for f in out/*; do
[[ -f "$f" ]] || continue
name="$(basename "$f")"
echo " прикрепляю $name"
curl -fsS -X POST "$API/releases/$RELEASE_ID/assets?name=$name" \
-H "Authorization: token $TOKEN" \
-F "attachment=@$f" > /dev/null
done
echo "готово: ${{ github.server_url }}/${{ github.repository }}/releases"
+6 -6
View File
@@ -67,14 +67,14 @@ git merge upstream/main # правки для upstream отправляю
### Сборка и CI
- **Сборка прошивок на своём Gitea** ([`.gitea/workflows/firmware.yml`](./.gitea/workflows/firmware.yml),
[`ci/build-firmwares.sh`](./ci/build-firmwares.sh)): workflow собирает набор устройств через
`build.sh`, поэтому версия, `merge-bin` для ESP32 и `.uf2` для nRF52 получаются такими же,
как при локальной сборке. Готовые файлы выгружаются артефактами, пуш тега создаёт черновик
релиза. Как поднять раннер — [`ci/README.md`](./ci/README.md).
- **Локальная сборка с публикацией результата** ([`ci/build-local.ps1`](./ci/build-local.ps1)):
[`ci/build-firmwares.sh`](./ci/build-firmwares.sh)): workflow собирает выбранный набор устройств
через `build.sh`, поэтому версия, `merge-bin` для ESP32 и `.uf2` для nRF52 получаются такими же,
как при локальной сборке. Запускается **только вручную** (Actions → Firmware build → Run workflow);
автоматических сборок по push и тегам нет. Как поднять раннер — [`ci/README.md`](./ci/README.md).
- **Локальная сборка с публикацией релиза** ([`ci/build-local.ps1`](./ci/build-local.ps1)):
набор прошивок собирается на своей машине (тот же `build.sh` через Git Bash), а готовые
файлы прикрепляются к релизу Gitea — сервер только принимает их и не тратит CPU на сборку.
Это основной способ собрать полный набор: на VPS всего одно ядро.
Это основной способ выпустить прошивки: на VPS всего одно ядро.
### Варианты плат
+26 -23
View File
@@ -8,8 +8,9 @@
| Файл | Назначение |
|---|---|
| `.gitea/workflows/firmware.yml` | workflow: клон, кэш, сборка, артефакты, черновик релиза по тегу |
| `.gitea/workflows/firmware.yml` | workflow: клон, кэш, сборка, артефакты (запуск только вручную) |
| `ci/build-firmwares.sh` | сборка выбранного набора env (годится и для запуска руками) |
| `ci/build-local.ps1` | сборка на своей машине под Windows и публикация релиза в Gitea |
| `ci/act_runner/gitea-runner.service` | systemd-юнит раннера |
| `ci/act_runner/config.yaml` | конфиг раннера: ёмкость, таймаут, кэш |
| `ci/act_runner/docker-compose.yml` | альтернатива: раннер в Docker |
@@ -108,8 +109,10 @@ cd ci/act_runner && cp .env.example .env && nano .env && docker compose up -d
## 4. Запуск сборки
- **Автоматически** — push в `main` (кроме изменений в `*.md`, `ci/**`, `.preview/**`).
- **Вручную** — Actions → Firmware build → Run workflow (`targets`, `match`, `version`),
Workflow запускается **только вручную** — автоматических сборок по push и тегам нет
(прошивки собираются локально и публикуются релизом, см. следующий раздел).
- **Вручную в Gitea** — Actions → Firmware build → Run workflow (`targets`, `match`, `version`),
либо через API:
```bash
curl -X POST -H "Authorization: token $GITEA_TOKEN" -H 'Content-Type: application/json' \
@@ -123,8 +126,8 @@ cd ci/act_runner && cp .env.example .env && nano .env && docker compose up -d
TARGETS="Heltec_t096_companion_radio_ble" bash ci/build-firmwares.sh
```
Готовые файлы попадают в `out/` (каталог в `.gitignore`) и прикрепляются к запуску
workflow как артефакт `firmware`.
Готовые файлы попадают в `out/` (каталог в `.gitignore`); при запуске в Gitea они
выгружаются артефактом `firmware`.
### Локально на Windows, без нагрузки на сервер
@@ -138,32 +141,31 @@ workflow как артефакт `firmware`.
# полный набор из 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
.\ci\build-local.ps1 -Version v1.0.0 -Publish -Public -Tag v1.0.0
# опубликовать уже собранное, без пересборки
.\ci\build-local.ps1 -Version v1.0.0 -SkipBuild -Publish -Public -Tag v1.0.0
```
Скрипт находит Git Bash и PlatformIO, подставляет рабочий `python3` (в Git Bash это
заглушка Microsoft Store — из-за неё `build.sh` не может определить платформу env),
чистит `out/` перед сборкой, а с `-Publish` создаёт тег, черновик релиза и прикрепляет
к нему файлы. Токен нужен только для публикации: сама сборка работает без него.
чистит `out/` перед сборкой, а с `-Publish` создаёт тег и релиз, прикрепляя к нему файлы
(`-Public` публикует сразу, без флага создаётся черновик). Токен нужен только для
публикации: сама сборка работает без него.
На Linux/macOS то же самое делается напрямую: `FIRMWARE_VERSION=v1.0.0 bash ci/build-firmwares.sh`.
## 5. Релизы по тегу
## 5. Релизы
Пуш тега `v1.0.0` или `companion-v1.0.0` собирает набор и создаёт **черновик релиза**
с прикреплёнными `.bin` / `.uf2` / `.zip`. Версия берётся из тега
(`companion-v1.2.3` → `v1.2.3`) и попадает в имена файлов (`<env>-v1.2.3-<sha>.uf2`).
Релиз собирается и публикуется **локально**: `ci/build-local.ps1 -Publish -Public -Tag <тег>`
(см. выше). Скрипт создаёт тег на текущем коммите, релиз в Gitea и прикрепляет к нему
`.bin` / `.uf2` / `.zip`; версия `-Version` попадает в имена файлов
(`<env>-v1.0.0-<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` и подставьте его в шаге «Черновик релиза».
В CI шага публикации нет: сервер только собирает прошивки по ручному запуску и отдаёт их
артефактом.
## 6. Набор прошивок по умолчанию
@@ -174,8 +176,9 @@ tracker_v2, T-Deck, T-Echo Card, T114, T190, M9 и три варианта Mesha
## 7. Время и ресурсы
- Сервер с **1 CPU / 2 ГБ RAM** полный набор собирает долго (первый прогон — часы),
и на время сборки Gitea с Postgres на той же машине заметно тормозят.
Разумно запускать полный набор вручную, а на push держать 2–3 env.
и на время сборки Gitea с Postgres на той же машине заметно тормозят. Поэтому рабочий
вариант — собирать полный набор локально (`ci/build-local.ps1`), а в Gitea запускать
вручную только те env, которые нужно проверить.
- Первая сборка качает тулчейны (nRF52: framework + CMSIS + gcc-arm ≈ 660 МБ;
ESP32 — ещё столько же), дальше работает кэш `~/.platformio`.
- `capacity: 1` в `config.yaml` — одна сборка за раз.