CI: сборка прошивок только по ручному запуску
This commit is contained in:
@@ -2,21 +2,11 @@ name: Firmware build
|
|||||||
|
|
||||||
# Сборка прошивок на своём Gitea-раннере (метка ubuntu-latest, см. ci/README.md).
|
# Сборка прошивок на своём Gitea-раннере (метка ubuntu-latest, см. ci/README.md).
|
||||||
#
|
#
|
||||||
# push в main — собрать набор прошивок и выгрузить артефакты
|
# Запуск ТОЛЬКО вручную: Actions → Firmware build → Run workflow, либо через API
|
||||||
# push тега — то же плюс черновик релиза с прикреплёнными файлами
|
# (пример запроса — в ci/README.md). Автоматических сборок по push и тегам нет:
|
||||||
# вручную — можно задать targets / match / version
|
# прошивки собираются локально (ci/build-local.ps1) и публикуются релизом в Gitea.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
- '*-v*'
|
|
||||||
paths-ignore:
|
|
||||||
- '**/*.md'
|
|
||||||
- '.preview/**'
|
|
||||||
- 'ci/**'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
targets:
|
targets:
|
||||||
@@ -32,9 +22,6 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ''
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -72,14 +59,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Версия прошивки
|
- name: Версия прошивки
|
||||||
run: |
|
run: |
|
||||||
# тег вида companion-v1.2.3 даёт версию v1.2.3; иначе — значение из запуска
|
VERSION="${{ github.event.inputs.version }}"
|
||||||
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
[[ -z "$VERSION" ]] && VERSION="ci"
|
||||||
TAG="${GITHUB_REF#refs/tags/}"
|
|
||||||
VERSION="${TAG##*-}"
|
|
||||||
else
|
|
||||||
VERSION="${{ github.event.inputs.version }}"
|
|
||||||
[[ -z "$VERSION" ]] && VERSION="ci"
|
|
||||||
fi
|
|
||||||
echo "FIRMWARE_VERSION=$VERSION" >> "$GITHUB_ENV"
|
echo "FIRMWARE_VERSION=$VERSION" >> "$GITHUB_ENV"
|
||||||
echo "версия: $VERSION"
|
echo "версия: $VERSION"
|
||||||
|
|
||||||
@@ -96,57 +77,3 @@ jobs:
|
|||||||
name: firmware
|
name: firmware
|
||||||
path: out/
|
path: out/
|
||||||
if-no-files-found: warn
|
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"
|
|
||||||
|
|||||||
@@ -67,14 +67,14 @@ git merge upstream/main # правки для upstream отправляю
|
|||||||
### Сборка и CI
|
### Сборка и CI
|
||||||
|
|
||||||
- **Сборка прошивок на своём Gitea** ([`.gitea/workflows/firmware.yml`](./.gitea/workflows/firmware.yml),
|
- **Сборка прошивок на своём Gitea** ([`.gitea/workflows/firmware.yml`](./.gitea/workflows/firmware.yml),
|
||||||
[`ci/build-firmwares.sh`](./ci/build-firmwares.sh)): workflow собирает набор устройств через
|
[`ci/build-firmwares.sh`](./ci/build-firmwares.sh)): workflow собирает выбранный набор устройств
|
||||||
`build.sh`, поэтому версия, `merge-bin` для ESP32 и `.uf2` для nRF52 получаются такими же,
|
через `build.sh`, поэтому версия, `merge-bin` для ESP32 и `.uf2` для nRF52 получаются такими же,
|
||||||
как при локальной сборке. Готовые файлы выгружаются артефактами, пуш тега создаёт черновик
|
как при локальной сборке. Запускается **только вручную** (Actions → Firmware build → Run workflow);
|
||||||
релиза. Как поднять раннер — [`ci/README.md`](./ci/README.md).
|
автоматических сборок по push и тегам нет. Как поднять раннер — [`ci/README.md`](./ci/README.md).
|
||||||
- **Локальная сборка с публикацией результата** ([`ci/build-local.ps1`](./ci/build-local.ps1)):
|
- **Локальная сборка с публикацией релиза** ([`ci/build-local.ps1`](./ci/build-local.ps1)):
|
||||||
набор прошивок собирается на своей машине (тот же `build.sh` через Git Bash), а готовые
|
набор прошивок собирается на своей машине (тот же `build.sh` через Git Bash), а готовые
|
||||||
файлы прикрепляются к релизу Gitea — сервер только принимает их и не тратит CPU на сборку.
|
файлы прикрепляются к релизу Gitea — сервер только принимает их и не тратит CPU на сборку.
|
||||||
Это основной способ собрать полный набор: на VPS всего одно ядро.
|
Это основной способ выпустить прошивки: на VPS всего одно ядро.
|
||||||
|
|
||||||
### Варианты плат
|
### Варианты плат
|
||||||
|
|
||||||
|
|||||||
+26
-23
@@ -8,8 +8,9 @@
|
|||||||
|
|
||||||
| Файл | Назначение |
|
| Файл | Назначение |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `.gitea/workflows/firmware.yml` | workflow: клон, кэш, сборка, артефакты, черновик релиза по тегу |
|
| `.gitea/workflows/firmware.yml` | workflow: клон, кэш, сборка, артефакты (запуск только вручную) |
|
||||||
| `ci/build-firmwares.sh` | сборка выбранного набора env (годится и для запуска руками) |
|
| `ci/build-firmwares.sh` | сборка выбранного набора env (годится и для запуска руками) |
|
||||||
|
| `ci/build-local.ps1` | сборка на своей машине под Windows и публикация релиза в Gitea |
|
||||||
| `ci/act_runner/gitea-runner.service` | systemd-юнит раннера |
|
| `ci/act_runner/gitea-runner.service` | systemd-юнит раннера |
|
||||||
| `ci/act_runner/config.yaml` | конфиг раннера: ёмкость, таймаут, кэш |
|
| `ci/act_runner/config.yaml` | конфиг раннера: ёмкость, таймаут, кэш |
|
||||||
| `ci/act_runner/docker-compose.yml` | альтернатива: раннер в Docker |
|
| `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. Запуск сборки
|
## 4. Запуск сборки
|
||||||
|
|
||||||
- **Автоматически** — push в `main` (кроме изменений в `*.md`, `ci/**`, `.preview/**`).
|
Workflow запускается **только вручную** — автоматических сборок по push и тегам нет
|
||||||
- **Вручную** — Actions → Firmware build → Run workflow (`targets`, `match`, `version`),
|
(прошивки собираются локально и публикуются релизом, см. следующий раздел).
|
||||||
|
|
||||||
|
- **Вручную в Gitea** — Actions → Firmware build → Run workflow (`targets`, `match`, `version`),
|
||||||
либо через API:
|
либо через API:
|
||||||
```bash
|
```bash
|
||||||
curl -X POST -H "Authorization: token $GITEA_TOKEN" -H 'Content-Type: application/json' \
|
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
|
TARGETS="Heltec_t096_companion_radio_ble" bash ci/build-firmwares.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Готовые файлы попадают в `out/` (каталог в `.gitignore`) и прикрепляются к запуску
|
Готовые файлы попадают в `out/` (каталог в `.gitignore`); при запуске в Gitea они
|
||||||
workflow как артефакт `firmware`.
|
выгружаются артефактом `firmware`.
|
||||||
|
|
||||||
### Локально на Windows, без нагрузки на сервер
|
### Локально на Windows, без нагрузки на сервер
|
||||||
|
|
||||||
@@ -138,32 +141,31 @@ workflow как артефакт `firmware`.
|
|||||||
# полный набор из DEFAULT_TARGETS
|
# полный набор из DEFAULT_TARGETS
|
||||||
.\ci\build-local.ps1 -Version v1.0.0
|
.\ci\build-local.ps1 -Version v1.0.0
|
||||||
|
|
||||||
# собрать и прикрепить к релизу (черновик; -Public опубликует сразу)
|
# собрать и опубликовать релиз
|
||||||
$env:GITEA_TOKEN = '<токен с правом write:repository>'
|
$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 это
|
Скрипт находит Git Bash и PlatformIO, подставляет рабочий `python3` (в Git Bash это
|
||||||
заглушка Microsoft Store — из-за неё `build.sh` не может определить платформу env),
|
заглушка Microsoft Store — из-за неё `build.sh` не может определить платформу env),
|
||||||
чистит `out/` перед сборкой, а с `-Publish` создаёт тег, черновик релиза и прикрепляет
|
чистит `out/` перед сборкой, а с `-Publish` создаёт тег и релиз, прикрепляя к нему файлы
|
||||||
к нему файлы. Токен нужен только для публикации: сама сборка работает без него.
|
(`-Public` публикует сразу, без флага создаётся черновик). Токен нужен только для
|
||||||
|
публикации: сама сборка работает без него.
|
||||||
|
|
||||||
На Linux/macOS то же самое делается напрямую: `FIRMWARE_VERSION=v1.0.0 bash ci/build-firmwares.sh`.
|
На Linux/macOS то же самое делается напрямую: `FIRMWARE_VERSION=v1.0.0 bash ci/build-firmwares.sh`.
|
||||||
|
|
||||||
## 5. Релизы по тегу
|
## 5. Релизы
|
||||||
|
|
||||||
Пуш тега `v1.0.0` или `companion-v1.0.0` собирает набор и создаёт **черновик релиза**
|
Релиз собирается и публикуется **локально**: `ci/build-local.ps1 -Publish -Public -Tag <тег>`
|
||||||
с прикреплёнными `.bin` / `.uf2` / `.zip`. Версия берётся из тега
|
(см. выше). Скрипт создаёт тег на текущем коммите, релиз в Gitea и прикрепляет к нему
|
||||||
(`companion-v1.2.3` → `v1.2.3`) и попадает в имена файлов (`<env>-v1.2.3-<sha>.uf2`).
|
`.bin` / `.uf2` / `.zip`; версия `-Version` попадает в имена файлов
|
||||||
|
(`<env>-v1.0.0-<sha>.uf2`). Если тег уже существует, он переиспользуется.
|
||||||
|
|
||||||
```bash
|
В CI шага публикации нет: сервер только собирает прошивки по ручному запуску и отдаёт их
|
||||||
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. Набор прошивок по умолчанию
|
## 6. Набор прошивок по умолчанию
|
||||||
|
|
||||||
@@ -174,8 +176,9 @@ tracker_v2, T-Deck, T-Echo Card, T114, T190, M9 и три варианта Mesha
|
|||||||
## 7. Время и ресурсы
|
## 7. Время и ресурсы
|
||||||
|
|
||||||
- Сервер с **1 CPU / 2 ГБ RAM** полный набор собирает долго (первый прогон — часы),
|
- Сервер с **1 CPU / 2 ГБ RAM** полный набор собирает долго (первый прогон — часы),
|
||||||
и на время сборки Gitea с Postgres на той же машине заметно тормозят.
|
и на время сборки Gitea с Postgres на той же машине заметно тормозят. Поэтому рабочий
|
||||||
Разумно запускать полный набор вручную, а на push держать 2–3 env.
|
вариант — собирать полный набор локально (`ci/build-local.ps1`), а в Gitea запускать
|
||||||
|
вручную только те env, которые нужно проверить.
|
||||||
- Первая сборка качает тулчейны (nRF52: framework + CMSIS + gcc-arm ≈ 660 МБ;
|
- Первая сборка качает тулчейны (nRF52: framework + CMSIS + gcc-arm ≈ 660 МБ;
|
||||||
ESP32 — ещё столько же), дальше работает кэш `~/.platformio`.
|
ESP32 — ещё столько же), дальше работает кэш `~/.platformio`.
|
||||||
- `capacity: 1` в `config.yaml` — одна сборка за раз.
|
- `capacity: 1` в `config.yaml` — одна сборка за раз.
|
||||||
|
|||||||
Reference in New Issue
Block a user