Build #424
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 | |
| # All build/release/cleanup behavior reads its configuration from builder.yml. | |
| # The pipeline is a matrix over builder.yml's `variants:` list: | |
| # config -> check-updates -> build (matrix) -> prune | |
| # The cron schedule below is the only knob that cannot be expressed in builder.yml | |
| # (GitHub Actions cron values must be static strings in this file). | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| variant: | |
| description: "Variant(s) to build" | |
| type: choice | |
| options: | |
| - all | |
| - edma-nss | |
| default: all | |
| push: | |
| branches: [main] | |
| paths: | |
| - builder.yml | |
| - 'devices/**' | |
| - 'common/**' | |
| - 'patches/**' | |
| - 'scripts/**' | |
| - '.github/workflows/build.yml' | |
| schedule: | |
| - cron: "0 */2 * * *" | |
| concurrency: | |
| group: build-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| config: | |
| name: Load builder.yml | |
| runs-on: ubuntu-26.04 | |
| timeout-minutes: 2 | |
| outputs: | |
| matrix: ${{ steps.cfg.outputs.matrix }} | |
| release_keep: ${{ steps.cfg.outputs.release_keep }} | |
| artifact_retention_days: ${{ steps.cfg.outputs.artifact_retention_days }} | |
| prefixes: ${{ steps.cfg.outputs.prefixes }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - id: cfg | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| VARIANT_INPUT: ${{ github.event.inputs.variant }} | |
| run: bash scripts/load-config.sh | |
| check-updates: | |
| name: Check upstreams | |
| needs: config | |
| runs-on: ubuntu-26.04 | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| outputs: | |
| matrix: ${{ steps.check.outputs.matrix }} | |
| has_builds: ${{ steps.check.outputs.has_builds }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - id: check | |
| env: | |
| CONFIG_MATRIX: ${{ needs.config.outputs.matrix }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| REPO: ${{ github.repository }} | |
| run: bash scripts/check-updates.sh | |
| build: | |
| name: Build ${{ matrix.variant }} (${{ matrix.device }}) | |
| needs: [config, check-updates] | |
| if: needs.check-updates.outputs.has_builds == 'true' | |
| runs-on: ubuntu-26.04 | |
| timeout-minutes: 360 | |
| permissions: | |
| contents: write | |
| actions: read | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJSON(needs.check-updates.outputs.matrix) }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| steps: | |
| - name: Install build dependencies | |
| run: | | |
| set -euo pipefail | |
| # Pinned to the ubuntu-26.04 runner. OpenWrt main (as of May 2026) builds its own | |
| # flex/bison/etc. host tools, so the host set is the minimal OpenWrt prerequisite list | |
| # for Ubuntu 26.04. rsync is for prepare-build.sh's overlay step. Everything else | |
| # (file, wget, unzip, yq, jq, gh) is preinstalled on the GitHub runner image. | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| bzip2 g++ gawk gcc git glibc-source libncurses-dev make rsync | |
| - name: Checkout OpenWrt source | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: ${{ matrix.upstream_repo }} | |
| ref: ${{ matrix.upstream_sha }} | |
| fetch-depth: 0 | |
| path: openwrt | |
| - name: Checkout builder repo | |
| uses: actions/checkout@v7 | |
| with: | |
| path: builder | |
| - name: Prepare build environment | |
| env: | |
| OPENWRT_DIR: ${{ github.workspace }}/openwrt | |
| BUILDER_REPO: ${{ github.workspace }}/builder | |
| VARIANT: ${{ matrix.variant }} | |
| DEVICE: ${{ matrix.device }} | |
| run: bash builder/scripts/prepare-build.sh | |
| - name: Set reproducible-build env | |
| working-directory: openwrt | |
| run: | | |
| set -euo pipefail | |
| { | |
| echo "SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)" | |
| echo "TZ=UTC" | |
| echo "LC_ALL=C" | |
| echo "KBUILD_BUILD_USER=builder" | |
| echo "KBUILD_BUILD_HOST=github" | |
| } >>"$GITHUB_ENV" | |
| - name: Download sources | |
| working-directory: openwrt | |
| run: | | |
| set -euo pipefail | |
| for attempt in 1 2 3; do | |
| make download -j"$(nproc)" V=s && break | |
| echo "Download attempt $attempt failed; retrying..." | |
| sleep 5 | |
| done | |
| - name: Build | |
| working-directory: openwrt | |
| run: | | |
| set -euo pipefail | |
| if ! make -j"$(nproc)"; then | |
| echo "::warning::Parallel build failed; retrying single-threaded for diagnostics" | |
| make -j1 V=s | |
| fi | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.variant }}-${{ matrix.device }}-images | |
| path: openwrt/bin/targets/${{ matrix.target }} | |
| if-no-files-found: error | |
| retention-days: ${{ needs.config.outputs.artifact_retention_days }} | |
| - name: Publish release | |
| id: release | |
| env: | |
| VARIANT: ${{ matrix.variant }} | |
| DEVICE: ${{ matrix.device }} | |
| TARGET: ${{ matrix.target }} | |
| RELEASE_PREFIX: ${{ matrix.release_prefix }} | |
| UPSTREAM_REPO: ${{ matrix.upstream_repo }} | |
| UPSTREAM_SHA: ${{ matrix.upstream_sha }} | |
| NSS_SHA: ${{ matrix.nss_sha }} | |
| run: | | |
| set -euo pipefail | |
| date=$(date -u +%F) | |
| timestamp=$(date -u +%Y%m%dT%H%M%SZ) | |
| tag_name="${RELEASE_PREFIX}-${timestamp}-${GITHUB_RUN_ID}" | |
| echo "release_tag=$tag_name" >>"$GITHUB_OUTPUT" | |
| { | |
| echo "## OpenWrt Build — ${VARIANT}" | |
| echo "- **Date**: $date" | |
| echo "- **Variant**: \`${VARIANT}\`" | |
| echo "- **Device**: \`${DEVICE}\`" | |
| echo "- **Target**: \`${TARGET}\`" | |
| echo "- **Upstream**: \`${UPSTREAM_REPO}@${UPSTREAM_SHA}\`" | |
| if [[ -n "${NSS_SHA}" ]]; then | |
| echo "- **NSS**: \`${NSS_SHA}\`" | |
| fi | |
| echo "- **Trigger**: \`${GITHUB_EVENT_NAME}\`" | |
| } >release_notes.md | |
| mapfile -t assets < <(find "openwrt/bin/targets/${TARGET}/" -type f -not -path "*/packages/*") | |
| gh release create "$tag_name" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --title "OpenWrt ${VARIANT} $date" \ | |
| --notes-file release_notes.md \ | |
| "${assets[@]}" | |
| { | |
| echo "## Release (${VARIANT})" | |
| echo "- tag: \`${tag_name}\`" | |
| echo "- assets: ${#assets[@]}" | |
| } >>"$GITHUB_STEP_SUMMARY" | |
| prune: | |
| name: Prune old releases | |
| needs: [config, build] | |
| runs-on: ubuntu-26.04 | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: write | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPO: ${{ github.repository }} | |
| KEEP: ${{ needs.config.outputs.release_keep }} | |
| PREFIXES: ${{ needs.config.outputs.prefixes }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Prune each variant prefix | |
| run: | | |
| set -euo pipefail | |
| while IFS= read -r prefix; do | |
| [[ -z "$prefix" ]] && continue | |
| echo "::group::prune $prefix" | |
| PREFIX="$prefix" bash scripts/prune-releases.sh | |
| echo "::endgroup::" | |
| done <<< "$PREFIXES" |