From c33d2d0f739ea65c079439b2bf70f0d9487d36c9 Mon Sep 17 00:00:00 2001 From: Dmitry Ilyin <6576495+widgetii@users.noreply.github.com> Date: Sat, 23 May 2026 23:00:08 +0300 Subject: [PATCH] ci/nightly: SHA-gate cron, publish dated nightly-* releases, BUILD_ID env MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirror the OpenIPC/firmware nightly redesign (PRs #2111-#2129) to builder. This commit is PR-Bld-A: the build.yml-side changes only. Subsequent PRs add the manifest aggregator + retention sweep (PR-Bld-B) and the build-one.yml commit input (PR-Bld-C). Changes: 1. **Preflight SHA gate**. New `preflight` job reads `sha=` from the rolling `nightly` release body. On schedule events it short- circuits the matrix when HEAD matches the previously-published SHA; PRs and workflow_dispatch always build. Mirrors firmware's #2111. 2. **Three release tags per build**: - `nightly-YYYYMMDD-` (prerelease, content-addressable, the unit of history — 90-day retention via PR-Bld-B's cleanup.yml). - `nightly` (rolling channel pointer; body carries sha/short/ built_at). - `latest` (legacy alias, kept one cycle so existing sysupgrade clients hitting the old hardcoded URL don't break). 3. **`BUILD_ID` / `BUILD_SHA` / `BUILD_PLATFORM` env** exported at the job level from preflight outputs. firmware's rootfs_script.sh (which builder.sh reuses via its clone of firmware) picks BUILD_ID + BUILD_SHA into /etc/os-release automatically. BUILD_PLATFORM is set to the matrix entry (e.g. `gk7205v200_fpv_caddx-fly`) and is forward-compatible with Phase 3 of the mirror plan (the firmware- side rootfs_script.sh update that emits BUILD_PLATFORM as an os-release field). 4. **Retry budget** around `bash builder.sh`. Matches firmware's `30 60 120 300 600 1200` ladder, covering toolchain/CDN flakes (#2115 + #2129 in firmware). 5. **Telegram caption** leads with `Build: `; obsolete `Tag: ${TAG_NAME}` line gone; workflow-level `env: TAG_NAME= latest` removed. No on-device firmware changes; builder cameras keep their existing sysupgrade legacy URL until Phase 2 of the mirror (sysupgrade variant routing) lands in OpenIPC/firmware. See ~/.claude/plans/mirror-nightly-redesign-to-builder.md. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/master.yml | 88 +++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 8b1a28939..e554737df 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -8,13 +8,49 @@ on: description: Platform required: false -env: - TAG_NAME: latest - jobs: + preflight: + name: Preflight + runs-on: ubuntu-latest + outputs: + should_build: ${{ steps.gate.outputs.should_build }} + head_sha: ${{ steps.gate.outputs.head_sha }} + short_sha: ${{ steps.gate.outputs.short_sha }} + build_id: ${{ steps.gate.outputs.build_id }} + built_at: ${{ steps.gate.outputs.built_at }} + steps: + - uses: actions/checkout@v4 + - id: gate + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + HEAD=$(git rev-parse HEAD) + SHORT=$(git rev-parse --short HEAD) + BUILD_ID="nightly-$(date -u +%Y%m%d)-${SHORT}" + BUILT_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ) + PREV=$(gh release view nightly --json body -q .body 2>/dev/null \ + | sed -n 's/^sha=//p' | head -1 || true) + if [ "${{ github.event_name }}" = "schedule" ] && [ "$PREV" = "$HEAD" ]; then + echo "Skip: HEAD ($HEAD) already published as the latest nightly." + echo "should_build=false" >> "$GITHUB_OUTPUT" + else + echo "Build: $BUILD_ID (event=${{ github.event_name }}, prev=$PREV)" + echo "should_build=true" >> "$GITHUB_OUTPUT" + fi + echo "head_sha=$HEAD" >> "$GITHUB_OUTPUT" + echo "short_sha=$SHORT" >> "$GITHUB_OUTPUT" + echo "build_id=$BUILD_ID" >> "$GITHUB_OUTPUT" + echo "built_at=$BUILT_AT" >> "$GITHUB_OUTPUT" + buildroot: name: Firmware + needs: preflight + if: needs.preflight.outputs.should_build == 'true' runs-on: ubuntu-latest + env: + BUILD_ID: ${{ needs.preflight.outputs.build_id }} + BUILD_SHA: ${{ needs.preflight.outputs.head_sha }} + BUILD_PLATFORM: ${{ matrix.platform }} strategy: fail-fast: false @@ -171,7 +207,20 @@ jobs: ln -s /tmp/ccache ${HOME}/.ccache NAME=${{matrix.platform}} - bash builder.sh ${NAME} + # Retry budget for transient upstream toolchain/CDN flakes + # (matches OpenIPC/firmware/.github/workflows/build.yml). + backoffs="30 60 120 300 600 1200" + attempt=1 + for sleep_for in $backoffs ""; do + bash builder.sh ${NAME} && break + if [ -z "$sleep_for" ]; then + echo "::error::build failed after ${attempt} attempts" + exit 1 + fi + echo "::warning::attempt ${attempt} failed, retrying after ${sleep_for}s" + sleep "$sleep_for" + attempt=$((attempt + 1)) + done cd openipc TIME=$(date -d @${SECONDS} +%M:%S) @@ -202,7 +251,34 @@ jobs: exit 1 fi - - name: Upload firmware + - name: Upload firmware (dated) + if: env.NORFW || env.NANDFW + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.preflight.outputs.build_id }} + prerelease: true + body: | + sha=${{ needs.preflight.outputs.head_sha }} + short=${{ needs.preflight.outputs.short_sha }} + built_at=${{ needs.preflight.outputs.built_at }} + files: | + ${{env.NORFW}} + ${{env.NANDFW}} + + - name: Upload firmware (rolling nightly) + if: env.NORFW || env.NANDFW + uses: softprops/action-gh-release@v2 + with: + tag_name: nightly + body: | + sha=${{ needs.preflight.outputs.head_sha }} + short=${{ needs.preflight.outputs.short_sha }} + built_at=${{ needs.preflight.outputs.built_at }} + files: | + ${{env.NORFW}} + ${{env.NANDFW}} + + - name: Upload firmware (latest — legacy alias) if: env.NORFW || env.NANDFW uses: softprops/action-gh-release@v2 with: @@ -214,7 +290,7 @@ jobs: - name: Send binary if: env.NORFW run: | - TG_MSG="Commit: ${GIT_HASH}\nBranch: ${GIT_BRANCH}\nTag: ${TAG_NAME}\nTime: ${TIME}\n\n" + TG_MSG="Build: ${BUILD_ID}\nCommit: ${GIT_HASH}\nBranch: ${GIT_BRANCH}\nTime: ${TIME}\n\n" TG_ICON="\xE2\x9C\x85 GitHub Actions" TG_HEADER=$(echo -e ${TG_MSG}${TG_ICON}) TG_TOKEN=${{secrets.TELEGRAM_TOKEN_BOT_OPENIPC}}