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}}