From 2fa097e3d65f2f7ef637af864181b7eb8d9abcf6 Mon Sep 17 00:00:00 2001 From: sl-jetson Date: Fri, 17 Apr 2026 22:11:33 -0400 Subject: [PATCH] =?UTF-8?q?ci:=20OTA=20release=20pipeline=20=E2=80=94=20bu?= =?UTF-8?q?ild=20+=20attach=20firmware=20binaries=20(bd-9kod)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds .gitea/workflows/ota-release.yml: triggered on esp32-balance/vX.Y.Z or esp32-io/vX.Y.Z tags, builds the corresponding ESP32-S3 project with espressif/idf:v5.2.2, and attaches _.bin + .sha256 to the Gitea release for OTA download. Co-Authored-By: Claude Sonnet 4.6 --- .gitea/workflows/ota-release.yml | 162 +++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 .gitea/workflows/ota-release.yml diff --git a/.gitea/workflows/ota-release.yml b/.gitea/workflows/ota-release.yml new file mode 100644 index 0000000..80ac07d --- /dev/null +++ b/.gitea/workflows/ota-release.yml @@ -0,0 +1,162 @@ +# .gitea/workflows/ota-release.yml +# Gitea Actions — ESP32 OTA firmware build & release (bd-9kod) +# +# Triggers on signed release tags: +# esp32-balance/vX.Y.Z → builds esp32s3/balance/ (ESP32-S3 Balance board) +# esp32-io/vX.Y.Z → builds esp32s3-io/ (ESP32-S3 IO board) +# +# Uses the official espressif/idf Docker image for reproducible builds. +# Attaches _.bin + _.sha256 to the Gitea release. +# The ESP32 Balance OTA system fetches the .bin from the release asset URL. + +name: OTA release — build & attach firmware + +on: + push: + tags: + - "esp32-balance/v*" + - "esp32-io/v*" + +permissions: + contents: write + +jobs: + build-and-release: + name: Build ${{ github.ref_name }} + runs-on: ubuntu-latest + container: + image: espressif/idf:v5.2.2 + options: --user root + + steps: + # ── 1. Checkout ─────────────────────────────────────────────────────────── + - name: Checkout + uses: actions/checkout@v4 + + # ── 2. Resolve build target from tag ───────────────────────────────────── + # Tag format: esp32-balance/v1.2.3 or esp32-io/v1.2.3 + - name: Resolve project from tag + id: proj + shell: bash + run: | + TAG="${GITHUB_REF_NAME}" + case "$TAG" in + esp32-balance/*) + DIR="esp32s3/balance" + APP="esp32s3_balance" + ;; + esp32-io/*) + DIR="esp32s3-io" + APP="esp32s3_io" + ;; + *) + echo "::error::Unrecognised tag prefix: ${TAG}" + exit 1 + ;; + esac + VERSION="${TAG#*/}" + echo "dir=${DIR}" >> "$GITHUB_OUTPUT" + echo "app=${APP}" >> "$GITHUB_OUTPUT" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "Build: ${APP} ${VERSION} from ${DIR}" + + # ── 3. Build with ESP-IDF ───────────────────────────────────────────────── + - name: Build firmware (idf.py build) + shell: bash + run: | + . "${IDF_PATH}/export.sh" + cd "${{ steps.proj.outputs.dir }}" + idf.py build + + # ── 4. Collect binary & generate checksum ──────────────────────────────── + - name: Collect artifacts + id: art + shell: bash + run: | + APP="${{ steps.proj.outputs.app }}" + VER="${{ steps.proj.outputs.version }}" + BIN_SRC="${{ steps.proj.outputs.dir }}/build/${APP}.bin" + BIN_OUT="${APP}_${VER}.bin" + SHA_OUT="${APP}_${VER}.sha256" + + cp "$BIN_SRC" "$BIN_OUT" + sha256sum "$BIN_OUT" > "$SHA_OUT" + + echo "bin=${BIN_OUT}" >> "$GITHUB_OUTPUT" + echo "sha=${SHA_OUT}" >> "$GITHUB_OUTPUT" + + echo "Binary: ${BIN_OUT} ($(wc -c < "$BIN_OUT") bytes)" + echo "Checksum: $(cat "$SHA_OUT")" + + # ── 5. Archive artifacts in CI workspace ───────────────────────────────── + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: firmware-${{ steps.proj.outputs.app }}-${{ steps.proj.outputs.version }} + path: | + ${{ steps.art.outputs.bin }} + ${{ steps.art.outputs.sha }} + + # ── 6. Create Gitea release (if needed) & upload assets ────────────────── + # Uses GITHUB_TOKEN (auto-provided, contents:write from permissions block). + # URL-encodes the tag to handle the slash in esp32-balance/vX.Y.Z. + - name: Publish assets to Gitea release + shell: bash + env: + GITEA_URL: https://gitea.vayrette.com + TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + TAG: ${{ steps.proj.outputs.tag }} + BIN: ${{ steps.art.outputs.bin }} + SHA: ${{ steps.art.outputs.sha }} + run: | + API="${GITEA_URL}/api/v1/repos/${REPO}" + + # URL-encode the tag (slash in esp32-balance/vX.Y.Z must be escaped) + TAG_ENC=$(python3 -c " + import urllib.parse, sys + print(urllib.parse.quote(sys.argv[1], safe='')) + " "$TAG") + + # Try to fetch an existing release for this tag + RELEASE=$(curl -sf \ + -H "Authorization: token ${TOKEN}" \ + "${API}/releases/tags/${TAG_ENC}") || true + + # If no release yet, create it + if [ -z "$RELEASE" ]; then + echo "Creating release for tag: ${TAG}" + RELEASE=$(curl -sf \ + -X POST \ + -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$(python3 -c " + import json, sys + print(json.dumps({ + 'tag_name': sys.argv[1], + 'name': sys.argv[1], + 'draft': False, + 'prerelease': False, + })) + " "$TAG")" \ + "${API}/releases") + fi + + RELEASE_ID=$(echo "$RELEASE" | python3 -c " + import sys, json; print(json.load(sys.stdin)['id']) + ") + echo "Release ID: ${RELEASE_ID}" + + # Upload binary and checksum + for FILE in "$BIN" "$SHA"; do + FNAME=$(basename "$FILE") + echo "Uploading: ${FNAME}" + curl -sf \ + -X POST \ + -H "Authorization: token ${TOKEN}" \ + -F "attachment=@${FILE}" \ + "${API}/releases/${RELEASE_ID}/assets?name=${FNAME}" + done + + echo "Published: ${BIN} + ${SHA} → release ${TAG}" -- 2.47.2