Build #1333
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| on: | |
| schedule: | |
| - cron: '0 3 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| platform: | |
| description: Platform | |
| required: false | |
| 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) | |
| # Nightly rebuilds unconditionally on schedule. builder.sh re-clones | |
| # OpenIPC/firmware at HEAD on every run, so the relevant inputs are | |
| # mostly outside this repo (firmware HEAD, toolchain release, kernel | |
| # tarball, vendor osdrv, individual package upstreams). The previous | |
| # gate skipped when only this repo's HEAD matched the last published | |
| # nightly, which made upstream fixes (e.g. an openhisilicon mipi_rx | |
| # regression fix that lands in firmware) invisible to users until | |
| # something here happened to change. Always build on schedule. | |
| echo "Build: $BUILD_ID (event=${{ github.event_name }})" | |
| echo "should_build=true" >> "$GITHUB_OUTPUT" | |
| 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 | |
| matrix: | |
| platform: | |
| - gk7202v300_lite_cootli_camv0103 | |
| - gk7202v300_lite_ipg-g3-wr | |
| - gk7202v300_lite_xg521 | |
| - gk7205v200_lite_tiandy-tc-c321n | |
| - gk7205v200_lite_vixand-ipc-1 | |
| - gk7205v200_lite_vixand-iph-5-4g | |
| - gk7205v210_lite_tiandy-tc-c32qn | |
| - gk7205v210_lite_vixand-ivg-g3s | |
| - gk7205v210_lite_vixand-ivg-g4f-a | |
| - gk7205v210_lite_vixand-ivg-g4f-a-w | |
| - gk7205v210_lite_vixand-ivg-g4h | |
| - gk7205v300_lite_vixand-ivg-g6s | |
| - gk7205v300_lite_vixand-ivg-g6s-w | |
| - hi3516cv200_lite_trassir-tr-d4121ir1-v2 | |
| - hi3516ev300_ultimate_rostelecom-ipc8232swc-we | |
| - hi3516ev300_ultimate_rvi-1ncmw2028 | |
| - hi3518ev200_lite_smartwares-cip-37210 | |
| - hi3518ev200_lite_switcam-hs303 | |
| - hi3518ev200_lite_switcam-hs303-v2 | |
| - hi3518ev200_lite_vstarcam-c8892wip | |
| - hi3518ev200_lite_qtech-qvc-ipc-136w | |
| - hi3518ev300_lite_bathhouse | |
| - hi3518ev300_lite_xiaomi-mjsxj02hl | |
| - hi3518ev200_ultimate_lenovo-snowman-1080p | |
| - ssc30kd_lite_cmcc-ds-ytj5301 | |
| - ssc325_lite_imilab-ec3-cmsxj25a | |
| - ssc325_lite_imou-c22cp | |
| - ssc325_lite_tp-link-tapo-c310-v1 | |
| - ssc325_lite_trassir-tr-w2c1-v1 | |
| - ssc325de_lite_imou-c22ep-s2 | |
| - ssc333_lite_meari-speed-6s | |
| - ssc333_lite_tp-link-tapo-c110-v2 | |
| - ssc333_lite_tp-link-tapo-c110-v26 | |
| - ssc333_lite_babysense-see-hd-ip206 | |
| - ssc333_lite_vstarcam-c43s_b | |
| - ssc335_lite_tp-link-tapo-c110-v1 | |
| - ssc335_lite_tp-link-tapo-c310-v220 | |
| - ssc335_lite_trassir-tr-w2c1-v2 | |
| - ssc335de_lite_dahua-hfw1230sp-v2 | |
| - ssc335de_lite_imou-c22e-s2-v2 | |
| - ssc335de_lite_uniview-c1l-2wn-g | |
| - ssc337_lite_h3c-tc2101 | |
| - ssc337_lite_tiandy-tc-c321n-v2 | |
| - ssc337_lite_tp-link-tapo-c110-v1 | |
| - ssc337de_ultimate_foscam-x5 | |
| - ssc338q_fpv_caddx-fly | |
| - ssc338q_fpv_emax-wyvern-link | |
| - ssc338q_fpv_openipc-mario-aio | |
| - ssc338q_fpv_openipc-thinker-aio | |
| - ssc338q_fpv_openipc-urllc-aio | |
| - ssc338q_fpv_runcam-wifilink | |
| - ssc377qe_fpv_ccdcam-im50q01-tipoman | |
| - t10_lite_hb-wifi-z6 | |
| - t10_lite_jvs-ingt10-gqs60ep | |
| - t20_ultimate_azarton-c1 | |
| - t20_lite_ec37-t11 | |
| - t31_lite_vstarcam-cs55 | |
| - t21_lite_chinamobile-hdc-51-a5-v12 | |
| - t21_lite_smartwares-cip-37210at | |
| - t21_lite_xyx-06s | |
| - t21_lite_wansview-q5-1080p | |
| - t23_lite_jooan-a6m-u | |
| - t23_lite_jooan-q3r-u | |
| - t23_lite_lsc-3215672 | |
| - t31_lite_aceline-aip-o4 | |
| - t31_lite_wansview-q5-2k | |
| - t31_lite_aoni-ep01j05 | |
| - t31_lite_chinamobile-hdc-51-a6-v11 | |
| - t31_lite_cmcc-hdc-51-a6-v10 | |
| - t31_lite_chinatelecom-y4h-50 | |
| - t31_lite_wyze-v3b | |
| - t31_lite_xiaomi-mjsxj03hl | |
| - t31_lite_xiaomi-mjsxj03hl-jxq03 | |
| - t31_lite_tuya-gv7630-t31-ptz | |
| - t31_ultimate_azarton-c1-t31x | |
| - t31_ultimate_gcraftsman-gca50 | |
| - t31_lite_zte-k540 | |
| - t40_lite_movols-mo-805p | |
| # APFPV | |
| - ssc30kq_apfpv_greg-generic-bu-eu | |
| - ssc30kq_apfpv_greg-generic-cu-eu | |
| - ssc338q_apfpv | |
| - ssc338q_apfpv_greg-generic-bu-eu | |
| - ssc338q_apfpv_greg-generic-cu-eu | |
| - ssc378qe_apfpv | |
| # FPV | |
| - hi3516ev200_fpv | |
| - hi3516ev300_fpv | |
| - hi3536dv100_fpv | |
| - gk7205v200_fpv | |
| - gk7205v210_fpv | |
| - gk7205v300_fpv | |
| - ssc30kq_fpv | |
| - ssc338q_fpv | |
| - ssc378qe_fpv | |
| # Ruby | |
| - ssc30kq_rubyfpv_generic | |
| - ssc338q_rubyfpv_generic | |
| - ssc338q_rubyfpv_thinker_internal_wifi | |
| # LTE | |
| - hi3516ev200_lte | |
| - hi3516ev300_lte | |
| - gk7205v200_lte | |
| - gk7205v300_lte | |
| # Venc | |
| - gk7205v200_venc | |
| - gk7205v210_venc | |
| - gk7205v300_venc | |
| # Mini | |
| - hi3516cv300_mini | |
| - hi3518ev200_mini | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| - name: Prepare firmware | |
| run: | | |
| echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf | |
| echo CACHE_DATE=$(date +%m) >> ${GITHUB_ENV} | |
| INPUT=${{inputs.platform}} | |
| MATRIX=$(echo ${{matrix.platform}} | cut -d_ -f1) | |
| if [ -z ${INPUT} ] || [ ${INPUT} = ${MATRIX} ]; then | |
| echo RUN=${MATRIX} >> ${GITHUB_ENV} | |
| fi | |
| - name: Setup ccache | |
| if: env.RUN | |
| uses: actions/cache@v4 | |
| with: | |
| path: /tmp/ccache | |
| key: ${{matrix.platform}}-${{env.CACHE_DATE}} | |
| # builder.sh does `rm -rf openipc` at the top of every run to force a | |
| # clean re-clone of OpenIPC/firmware, which also nukes the default | |
| # `openipc/output/dl/` directory Buildroot uses for downloaded source | |
| # tarballs. Without a cache, every cron run re-downloads ~1-3 GB of | |
| # tarballs from upstream mirrors — and any one of them randomly | |
| # failing (e.g. cgit `snapshot/` URLs that regenerate tarballs per | |
| # request with shifting sha256, like wireguard-tools on | |
| # git.zx2c4.com) takes down the matrix entry for that board. See | |
| # kaeru wireguard-zx2c4-tarball-regeneration-hash-drift for the | |
| # specific incident this caching addresses. | |
| # | |
| # Cache to /tmp/builder-dl (outside the openipc/ tree so builder.sh's | |
| # rm -rf doesn't touch it) and point Buildroot at it via BR2_DL_DIR | |
| # env var (honored per Buildroot manual section "Location of source | |
| # tarballs"). Mirrors OpenIPC/firmware/.github/workflows/build.yml's | |
| # output/dl cache, adapted for builder's clean-clone behavior. | |
| - name: Setup dl cache | |
| if: env.RUN | |
| uses: actions/cache@v4 | |
| with: | |
| path: /tmp/builder-dl | |
| key: builder-dl-${{env.CACHE_DATE}} | |
| restore-keys: builder-dl- | |
| - name: Refresh moving-ref package downloads | |
| if: env.RUN | |
| run: | | |
| # builder caches BR2_DL_DIR (/tmp/builder-dl) under a monthly key | |
| # (date +%m) and actions/cache only saves on a key miss, so the first build | |
| # of the month freezes it for weeks. Packages pinned to a moving ref | |
| # (VERSION = HEAD / branch, or the majestic-webui `dist` release asset) | |
| # download as a constant <pkg>-<ref>.tar.gz, so buildroot keeps reusing the | |
| # stale tarball — even though builder re-clones firmware HEAD each run for | |
| # freshness. (Empirically: a 06-14 builder nightly shipped a ~2-week-old | |
| # majestic-webui — full bootstrap.min.css, no mj-settings.js — while the | |
| # firmware nightly shipped the current UI.) Drop those archives so buildroot | |
| # re-fetches the current ref each run. Content-addressed packages | |
| # (S3 / semver / SHA pins) keep their cache. | |
| find /tmp/builder-dl -type f \ | |
| \( -name '*-HEAD.tar.gz' -o -name '*-master.tar.gz' -o -name '*-main.tar.gz' -o -name '*-dist.tar.gz' \) \ | |
| -print -delete 2>/dev/null || true | |
| - name: Build firmware | |
| if: env.RUN | |
| run: | | |
| export GIT_HASH=$(git rev-parse --short ${GITHUB_SHA}) | |
| export GIT_BRANCH=${GITHUB_REF_NAME} | |
| echo GIT_HASH=${GIT_HASH} >> ${GITHUB_ENV} | |
| echo GIT_BRANCH=${GIT_BRANCH} >> ${GITHUB_ENV} | |
| mkdir -p /tmp/ccache | |
| ln -s /tmp/ccache ${HOME}/.ccache | |
| mkdir -p /tmp/builder-dl | |
| export BR2_DL_DIR=/tmp/builder-dl | |
| NAME=${{matrix.platform}} | |
| # 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) | |
| echo TIME=${TIME} >> ${GITHUB_ENV} | |
| COMMON=$(echo ${NAME} | awk -F_ '{print NF-1}') | |
| NORFW=$(find output/images -name openipc*nor*) | |
| if [ ! -z ${NORFW} ]; then | |
| if [ ${COMMON} -eq 1 ]; then | |
| echo NORFW=openipc/${NORFW} >> ${GITHUB_ENV} | |
| else | |
| mv ${NORFW} ../${NAME}-nor.tgz | |
| echo NORFW=${NAME}-nor.tgz >> ${GITHUB_ENV} | |
| fi | |
| fi | |
| NANDFW=$(find output/images -name openipc*nand*) | |
| if [ ! -z ${NANDFW} ]; then | |
| if [ ${COMMON} -eq 1 ]; then | |
| echo NANDFW=openipc/${NANDFW} >> ${GITHUB_ENV} | |
| else | |
| mv ${NANDFW} ../${NAME}-nand.tgz | |
| echo NANDFW=${NAME}-nand.tgz >> ${GITHUB_ENV} | |
| fi | |
| fi | |
| if [ -z ${NORFW} ] && [ -z ${NANDFW} ]; then | |
| exit 1 | |
| fi | |
| - name: Build size report | |
| if: env.NORFW || env.NANDFW | |
| run: | | |
| cd openipc | |
| NAME=${{matrix.platform}} | |
| make BOARD=${NAME} size-report || \ | |
| { echo "::warning::size-report failed for ${NAME}"; exit 0; } | |
| SIZES=$(find output/images -name 'sizes.*.json' | head -1) | |
| if [ -z "${SIZES}" ]; then | |
| exit 0 | |
| fi | |
| # Mirror the .tgz rename trick: compound matrix entries | |
| # (`<soc>_<variant>_<vendor>-<model>`) share `<soc>_<variant>` and | |
| # would collide on the firmware-side `sizes.<soc>-<variant>.json` | |
| # filename when uploaded to the same release tag. Rename to | |
| # `sizes.<NAME>.json` so every compound device gets its own asset. | |
| COMMON=$(echo ${NAME} | awk -F_ '{print NF-1}') | |
| if [ ${COMMON} -eq 1 ]; then | |
| echo "SIZES=openipc/${SIZES}" >> ${GITHUB_ENV} | |
| else | |
| mv ${SIZES} ../sizes.${NAME}.json | |
| echo "SIZES=sizes.${NAME}.json" >> ${GITHUB_ENV} | |
| fi | |
| - 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}} | |
| ${{env.SIZES}} | |
| - 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}} | |
| ${{env.SIZES}} | |
| - name: Upload firmware (latest — legacy alias) | |
| if: env.NORFW || env.NANDFW | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: latest | |
| files: | | |
| ${{env.NORFW}} | |
| ${{env.NANDFW}} | |
| ${{env.SIZES}} | |
| - name: Send binary | |
| if: env.NORFW | |
| run: | | |
| 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}} | |
| TG_CHANNEL=${{secrets.TELEGRAM_CHANNEL_OPENIPC_DEV}} | |
| HTTP=$(curl -s -o /dev/null -w %{http_code} https://api.telegram.org/bot${TG_TOKEN}/sendDocument -F chat_id=${TG_CHANNEL} -F caption="${TG_HEADER}" -F document=@${NORFW}) | |
| echo Telegram response: ${HTTP} |