CI: сборка прошивок на Gitea Actions (workflow, скрипт, раннер)
This commit is contained in:
@@ -0,0 +1,146 @@
|
|||||||
|
name: Firmware build
|
||||||
|
|
||||||
|
# Сборка прошивок на своём Gitea-раннере (метка ubuntu-latest, см. ci/README.md).
|
||||||
|
#
|
||||||
|
# push в main — собрать набор прошивок и выгрузить артефакты
|
||||||
|
# push тега — то же плюс черновик релиза с прикреплёнными файлами
|
||||||
|
# вручную — можно задать targets / match / version
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
- '*-v*'
|
||||||
|
paths-ignore:
|
||||||
|
- '**/*.md'
|
||||||
|
- '.preview/**'
|
||||||
|
- 'ci/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
targets:
|
||||||
|
description: 'env через запятую (пусто — набор по умолчанию)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
match:
|
||||||
|
description: 'подстрока имени env, например heltec_t096'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
version:
|
||||||
|
description: 'FIRMWARE_VERSION (по умолчанию ci)'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 300
|
||||||
|
steps:
|
||||||
|
- name: Клонирование
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Кэш PlatformIO
|
||||||
|
uses: actions/cache@v4
|
||||||
|
continue-on-error: true # сервер кэша может быть недоступен — сборку это ломать не должно
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/pip
|
||||||
|
~/.platformio
|
||||||
|
~/.platformio-venv
|
||||||
|
key: pio-${{ runner.os }}-v1
|
||||||
|
restore-keys: |
|
||||||
|
pio-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: PlatformIO
|
||||||
|
run: |
|
||||||
|
# отдельное venv: на свежих Debian/Ubuntu pip в систему запрещён (PEP 668)
|
||||||
|
python3 -m venv "$HOME/.platformio-venv"
|
||||||
|
"$HOME/.platformio-venv/bin/pip" install --upgrade pip platformio
|
||||||
|
echo "$HOME/.platformio-venv/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- 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
|
||||||
|
echo "FIRMWARE_VERSION=$VERSION" >> "$GITHUB_ENV"
|
||||||
|
echo "версия: $VERSION"
|
||||||
|
|
||||||
|
- name: Сборка прошивок
|
||||||
|
env:
|
||||||
|
TARGETS: ${{ github.event.inputs.targets }}
|
||||||
|
MATCH: ${{ github.event.inputs.match }}
|
||||||
|
run: bash ci/build-firmwares.sh
|
||||||
|
|
||||||
|
- name: Выгрузка артефактов
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
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"
|
||||||
+165
@@ -0,0 +1,165 @@
|
|||||||
|
# CI: автоматическая сборка прошивок на своём Gitea
|
||||||
|
|
||||||
|
Схема: **Gitea (systemd) → act_runner на том же сервере → PlatformIO → артефакты `out/`**.
|
||||||
|
Сборка идёт через `build.sh` из репозитория, то есть тем же путём, что и локально
|
||||||
|
(версия прошивки, `merge-bin` для ESP32, `.uf2` для nRF52), — логика не дублируется.
|
||||||
|
|
||||||
|
## Что где лежит
|
||||||
|
|
||||||
|
| Файл | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `.gitea/workflows/firmware.yml` | workflow: клон, кэш PlatformIO, сборка, артефакты, черновик релиза по тегу |
|
||||||
|
| `ci/build-firmwares.sh` | сборка выбранного набора env (годится и для запуска руками) |
|
||||||
|
| `ci/act_runner/act-runner.service` | systemd-юнит раннера |
|
||||||
|
| `ci/act_runner/config.yaml` | конфиг раннера: ёмкость, таймаут, кэш |
|
||||||
|
| `ci/act_runner/docker-compose.yml` | альтернатива: раннер в Docker |
|
||||||
|
|
||||||
|
## 1. Что должно быть на VPS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y git python3 python3-venv python3-pip build-essential curl ca-certificates
|
||||||
|
```
|
||||||
|
|
||||||
|
- `python3-venv` обязателен: workflow ставит PlatformIO в отдельное окружение
|
||||||
|
(`~/.platformio-venv`), потому что на свежих Debian/Ubuntu pip в систему запрещён.
|
||||||
|
- Свободного места нужно **5 ГБ**: `~/.platformio` с тулчейнами (~2–3 ГБ),
|
||||||
|
venv и промежуточные файлы сборки.
|
||||||
|
- RAM: 2 ГБ достаточно, при 1 ГБ возможны падения линковки ESP32.
|
||||||
|
|
||||||
|
## 2. Установка раннера (systemd)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# отдельный пользователь, от его имени пойдут сборки
|
||||||
|
useradd --create-home --home-dir /var/lib/act-runner --shell /bin/bash act-runner
|
||||||
|
|
||||||
|
# бинарник: актуальную версию и имя файла сверьте на
|
||||||
|
# https://gitea.com/gitea/act_runner/releases
|
||||||
|
# (в свежих релизах проект называется Gitea Runner, см. https://docs.gitea.com/runner/)
|
||||||
|
curl -fsSL -o /usr/local/bin/act_runner \
|
||||||
|
https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
|
||||||
|
chmod +x /usr/local/bin/act_runner
|
||||||
|
|
||||||
|
# каталоги
|
||||||
|
install -d -o act-runner -g act-runner /var/lib/act-runner
|
||||||
|
install -d /etc/act_runner
|
||||||
|
cp ci/act_runner/config.yaml /etc/act_runner/config.yaml
|
||||||
|
|
||||||
|
# токен: Gitea → репозиторий → Settings → Actions → Runners → Create new Runner
|
||||||
|
su - act-runner -c 'act_runner register --no-interactive \
|
||||||
|
--instance https://git.meshinfo.ru \
|
||||||
|
--token ВСТАВИТЬ_ТОКЕН \
|
||||||
|
--name meshcore-builder \
|
||||||
|
--labels ubuntu-latest:host'
|
||||||
|
|
||||||
|
# сервис
|
||||||
|
cp ci/act_runner/act-runner.service /etc/systemd/system/
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now act-runner
|
||||||
|
systemctl status act-runner
|
||||||
|
journalctl -u act-runner -f # в логах: "runner registered" / "polling tasks"
|
||||||
|
```
|
||||||
|
|
||||||
|
Метка `ubuntu-latest:host` означает, что шаги выполняются **прямо на сервере** — быстро
|
||||||
|
и без Docker, но зависимости ставятся в систему. Метка должна совпадать с `runs-on`
|
||||||
|
в `.gitea/workflows/firmware.yml`.
|
||||||
|
|
||||||
|
Раннер виден в Gitea: репозиторий → Settings → Actions → Runners (должен быть зелёным).
|
||||||
|
|
||||||
|
### Альтернатива: раннер в Docker
|
||||||
|
|
||||||
|
Если на VPS есть Docker, из `ci/act_runner`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ci/act_runner
|
||||||
|
cat > .env <<'EOF'
|
||||||
|
GITEA_INSTANCE_URL=https://git.meshinfo.ru
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN=ВСТАВИТЬ_ТОКЕН
|
||||||
|
GITEA_RUNNER_NAME=meshcore-builder
|
||||||
|
EOF
|
||||||
|
docker compose up -d && docker compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
В этом варианте job'ы идут в контейнере `catthehacker/ubuntu:act-22.04`, а docker.sock
|
||||||
|
смонтирован внутрь раннера. В свежих версиях образ может называться `gitea/runner`.
|
||||||
|
|
||||||
|
## 3. Отключить лишние workflow
|
||||||
|
|
||||||
|
Gitea читает workflow и из `.gitea/workflows`, и из `.github/workflows`, а там лежат
|
||||||
|
upstream-файлы с триггером `push`: `build-companion-firmwares.yml`,
|
||||||
|
`build-repeater-firmwares.yml`, `build-room-server-firmwares.yml`, `github-pages.yml`,
|
||||||
|
`run-unit-tests.yml`. На первом же пуше они попытаются собрать сотни env (в проекте их
|
||||||
|
около 600) или задеплоить Pages.
|
||||||
|
|
||||||
|
Отключите их в настройках репозитория (раздел Actions) либо через API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
https://git.meshinfo.ru/api/v1/repos/shade/MeshCore/actions/workflows/run-unit-tests.yml/disable
|
||||||
|
```
|
||||||
|
|
||||||
|
Оставьте включённым только `firmware.yml`. Если ваша версия Gitea поддерживает
|
||||||
|
настройку `actions.WORKFLOW_DIRS`, можно ограничить список каталогов одним
|
||||||
|
`.gitea/workflows` — тогда upstream-файлы не подхватятся вовсе.
|
||||||
|
|
||||||
|
## 4. Запуск сборки
|
||||||
|
|
||||||
|
- **Автоматически** — push в `main` (кроме изменений в `*.md`, `ci/**`, `.preview/**`).
|
||||||
|
- **Вручную** — Actions → Firmware build → Run workflow, поля:
|
||||||
|
- `targets` — env через запятую, например `Heltec_t096_companion_radio_ble,ProMicro_companion_radio_ble`;
|
||||||
|
- `match` — подстрока имени env, например `heltec_t096`;
|
||||||
|
- `version` — значение `FIRMWARE_VERSION` (по умолчанию `ci`).
|
||||||
|
- **Локально** — тот же скрипт, что запускает 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
|
||||||
|
bash build.sh list | grep -i t096 # доступные env
|
||||||
|
```
|
||||||
|
|
||||||
|
Готовые файлы попадают в `out/` (каталог в `.gitignore`) и прикрепляются к запуску
|
||||||
|
workflow как артефакт `firmware`.
|
||||||
|
|
||||||
|
## 5. Релизы по тегу
|
||||||
|
|
||||||
|
Пуш тега вида `v1.0.0` или `companion-v1.0.0` запускает сборку и **создаёт черновик
|
||||||
|
релиза** с прикреплёнными `.bin` / `.uf2` / `.zip`. Версия прошивки берётся из тега:
|
||||||
|
`companion-v1.2.3` → `v1.2.3`, и попадает в имена файлов
|
||||||
|
(`<env>-v1.2.3-<sha>.uf2`).
|
||||||
|
|
||||||
|
Черновик — чтобы можно было посмотреть состав и нажать Publish руками:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag companion-v1.0.0
|
||||||
|
git push origin companion-v1.0.0
|
||||||
|
# затем: репозиторий → Releases → черновик → Publish
|
||||||
|
```
|
||||||
|
|
||||||
|
Для публикации используется `secrets.GITHUB_TOKEN`, который Gitea выдаёт workflow
|
||||||
|
автоматически (в workflow стоит `permissions: contents: write`). Если по вашему
|
||||||
|
токену релизы не создаются, заведите секрет репозитория `RELEASE_TOKEN` с правом
|
||||||
|
`write:repository` и подставьте его в шаге «Черновик релиза».
|
||||||
|
|
||||||
|
## Набор прошивок по умолчанию
|
||||||
|
|
||||||
|
`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.
|
||||||
|
|
||||||
|
## Время и кэш
|
||||||
|
|
||||||
|
- Первая (холодная) сборка набора — примерно 30–60 минут: скачиваются тулчейны.
|
||||||
|
- Последующие запуски заметно быстрее: `~/.platformio` и venv кэшируются между
|
||||||
|
запусками через `actions/cache`.
|
||||||
|
- `capacity: 1` в `config.yaml` — одна сборка за раз; поднимайте, если CPU позволяет.
|
||||||
|
|
||||||
|
## Ограничения
|
||||||
|
|
||||||
|
- Шаги используют `actions/checkout`, `actions/cache`, `actions/upload-artifact`,
|
||||||
|
`actions/download-artifact`. Раннер скачивает их с GitHub (`DEFAULT_ACTIONS_URL`),
|
||||||
|
поэтому серверу нужен доступ в интернет; в закрытом контуре укажите свой миррор
|
||||||
|
экшенов в `config.yaml`.
|
||||||
|
- Кэш `~/.platformio` растёт со временем: если диск кончается, почистите
|
||||||
|
`~/.platformio/.cache` у пользователя `act-runner`.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Gitea Actions runner (MeshCore firmware builder)
|
||||||
|
Documentation=https://docs.gitea.com/usage/actions/act-runner
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
# отдельный пользователь: от его имени выполняются шаги workflow,
|
||||||
|
# здесь же живёт кэш PlatformIO
|
||||||
|
User=act-runner
|
||||||
|
Group=act-runner
|
||||||
|
WorkingDirectory=/var/lib/act-runner
|
||||||
|
Environment=HOME=/var/lib/act-runner
|
||||||
|
ExecStart=/usr/local/bin/act_runner daemon --config /etc/act_runner/config.yaml
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
# сборка прошивок — процесс долгий и прожорливый, но не привилегированный
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Конфигурация act_runner (Gitea Actions).
|
||||||
|
# Подключается в docker-compose.yml как /config.yaml.
|
||||||
|
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
|
|
||||||
|
runner:
|
||||||
|
file: /data/.runner
|
||||||
|
capacity: 1 # одновременно одна сборка; поднимайте, если на VPS много CPU
|
||||||
|
timeout: 5h # холодная сборка набора прошивок может идти долго
|
||||||
|
fetch_timeout: 30s
|
||||||
|
fetch_interval: 5s
|
||||||
|
# Метки не задаём здесь: они фиксируются при регистрации раннера
|
||||||
|
# (systemd: act_runner register --labels ubuntu-latest:host,
|
||||||
|
# docker: переменная GITEA_RUNNER_LABELS в docker-compose.yml)
|
||||||
|
|
||||||
|
cache:
|
||||||
|
enabled: true
|
||||||
|
dir: /data/cache
|
||||||
|
host: ""
|
||||||
|
port: 0
|
||||||
|
|
||||||
|
container:
|
||||||
|
# job'ы запускаются как sibling-контейнеры через смонтированный docker.sock
|
||||||
|
network: ""
|
||||||
|
privileged: false
|
||||||
|
options: "--add-host=host.docker.internal:host-gateway"
|
||||||
|
workdir_parent: ""
|
||||||
|
valid_volumes: []
|
||||||
|
force_pull: false
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# act_runner для Gitea: выполняет Gitea Actions на этом сервере.
|
||||||
|
#
|
||||||
|
# Запуск (из каталога ci/act_runner):
|
||||||
|
# 1) получить токен: Gitea → репозиторий → Settings → Actions → Runners → Create new Runner
|
||||||
|
# 2) создать .env рядом с этим файлом:
|
||||||
|
# GITEA_INSTANCE_URL=https://git.meshinfo.ru
|
||||||
|
# GITEA_RUNNER_REGISTRATION_TOKEN=<токен из шага 1>
|
||||||
|
# GITEA_RUNNER_NAME=meshcore-builder
|
||||||
|
# 3) docker compose up -d
|
||||||
|
# 4) проверить: docker compose logs -f
|
||||||
|
#
|
||||||
|
# Метка ubuntu-latest должна совпадать с runs-on в .gitea/workflows/firmware.yml.
|
||||||
|
# Образ job'а — catthehacker/ubuntu:act-22.04: в нём уже есть git, curl, python3,
|
||||||
|
# build-essential; PlatformIO ставится шагом workflow и живёт в кэше.
|
||||||
|
|
||||||
|
services:
|
||||||
|
act-runner:
|
||||||
|
image: gitea/act_runner:latest
|
||||||
|
container_name: meshcore-act-runner
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
GITEA_INSTANCE_URL: ${GITEA_INSTANCE_URL:?укажите адрес Gitea в .env}
|
||||||
|
GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN:?нужен токен раннера}
|
||||||
|
GITEA_RUNNER_NAME: ${GITEA_RUNNER_NAME:-meshcore-builder}
|
||||||
|
GITEA_RUNNER_LABELS: ${GITEA_RUNNER_LABELS:-ubuntu-latest:docker://catthehacker/ubuntu:act-22.04}
|
||||||
|
CONFIG_FILE: /config.yaml
|
||||||
|
volumes:
|
||||||
|
# состояние раннера (.runner) и локальный кэш Gitea Actions
|
||||||
|
- ./data:/data
|
||||||
|
- ./config.yaml:/config.yaml:ro
|
||||||
|
# job'ы запускаются как соседние контейнеры, поэтому нужен доступ к демону
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Сборка выбранных прошивок через build.sh — тот же путь, что и при локальной сборке,
|
||||||
|
# поэтому CI не дублирует логику (версия, merge-bin, uf2, каталог out/).
|
||||||
|
# Скрипт годится и для запуска руками на VPS или локально.
|
||||||
|
#
|
||||||
|
# Переменные окружения:
|
||||||
|
# TARGETS список env через запятую (перебивает набор по умолчанию)
|
||||||
|
# MATCH подстрока имени env — собрать все подходящие (регистронезависимо)
|
||||||
|
# FIRMWARE_VERSION версия прошивки (по умолчанию ci)
|
||||||
|
# OUT_DIR каталог артефактов (по умолчанию out, его использует build.sh)
|
||||||
|
#
|
||||||
|
# Примеры:
|
||||||
|
# bash ci/build-firmwares.sh
|
||||||
|
# TARGETS="Heltec_t096_companion_radio_ble,ProMicro_companion_radio_ble" bash ci/build-firmwares.sh
|
||||||
|
# MATCH=heltec_t096 FIRMWARE_VERSION=v1.2.3 bash ci/build-firmwares.sh
|
||||||
|
#
|
||||||
|
# Один упавший env не отменяет остальные: в конце печатается список несобравшихся,
|
||||||
|
# и скрипт возвращает ненулевой код, чтобы CI пометил сборку красной.
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
||||||
|
|
||||||
|
# Набор по умолчанию — устройства этого форка.
|
||||||
|
DEFAULT_TARGETS=(
|
||||||
|
# companion
|
||||||
|
Heltec_t096_companion_radio_ble
|
||||||
|
ProMicro_companion_radio_ble
|
||||||
|
ProMicro_SH1106_companion_radio_ble
|
||||||
|
Heltec_v3_companion_radio_ble
|
||||||
|
heltec_v4_tft_companion_radio_ble
|
||||||
|
heltec_tracker_v2_companion_radio_ble
|
||||||
|
LilyGo_TDeck_companion_radio_ble
|
||||||
|
LilyGo_T-Echo_Card_companion_radio_ble
|
||||||
|
Heltec_t114_companion_radio_ble
|
||||||
|
Heltec_T190_companion_radio_ble_
|
||||||
|
ThinkNode_M9_companion_radio_ble_
|
||||||
|
Meshadventurer_sx1262_companion_radio_ble
|
||||||
|
Meshadventurer_sx1262_e22p_868m30s_companion_radio_ble
|
||||||
|
Meshadventurer_e22p_433m30s_companion_radio_ble
|
||||||
|
# repeater / room server / sensor
|
||||||
|
Heltec_t096_repeater
|
||||||
|
Heltec_t096_room_server
|
||||||
|
Heltec_t096_sensor
|
||||||
|
ProMicro_repeater
|
||||||
|
ProMicro_room_server
|
||||||
|
)
|
||||||
|
|
||||||
|
export FIRMWARE_VERSION="${FIRMWARE_VERSION:-ci}"
|
||||||
|
OUT_DIR="${OUT_DIR:-out}"
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
|
||||||
|
targets=()
|
||||||
|
if [[ -n "${MATCH:-}" ]]; then
|
||||||
|
# список env берём тем же способом, что и build.sh list
|
||||||
|
while IFS= read -r env; do
|
||||||
|
[[ -n "$env" ]] && targets+=("$env")
|
||||||
|
done < <(bash build.sh list | grep -i -- "$MATCH" || true)
|
||||||
|
elif [[ -n "${TARGETS:-}" ]]; then
|
||||||
|
IFS=',' read -r -a parts <<< "$TARGETS"
|
||||||
|
for part in "${parts[@]}"; do
|
||||||
|
part="$(printf '%s' "$part" | xargs)"
|
||||||
|
[[ -n "$part" ]] && targets+=("$part")
|
||||||
|
done
|
||||||
|
else
|
||||||
|
targets=("${DEFAULT_TARGETS[@]}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#targets[@]} -eq 0 ]]; then
|
||||||
|
echo "Нечего собирать: проверьте TARGETS/MATCH" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Версия прошивки: $FIRMWARE_VERSION"
|
||||||
|
echo "К сборке: ${#targets[@]}"
|
||||||
|
printf ' %s\n' "${targets[@]}"
|
||||||
|
|
||||||
|
failed=()
|
||||||
|
for env in "${targets[@]}"; do
|
||||||
|
echo
|
||||||
|
echo "===== $env ====="
|
||||||
|
if bash build.sh build-firmware "$env"; then
|
||||||
|
echo "----- $env: OK"
|
||||||
|
else
|
||||||
|
echo "----- $env: ОШИБКА"
|
||||||
|
failed+=("$env")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "===== итог ====="
|
||||||
|
echo "собрано ${#targets[@]} - ${#failed[@]} ошибок"
|
||||||
|
if [[ ${#failed[@]} -gt 0 ]]; then
|
||||||
|
printf 'не собрались: %s\n' "${failed[@]}"
|
||||||
|
fi
|
||||||
|
echo "артефакты в $OUT_DIR:"
|
||||||
|
ls -1 "$OUT_DIR" 2>/dev/null || echo " (пусто)"
|
||||||
|
|
||||||
|
[[ ${#failed[@]} -eq 0 ]]
|
||||||
Reference in New Issue
Block a user