diff --git a/README.md b/README.md index 8b1b840..c0cf488 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,26 @@ -

- Armbian logo +

+ Armbian logo

-

+ # Armbian CI -Central home for Armbian's build automation: the reusable GitHub Actions pipeline that produces Armbian artifacts and images, plus the `userpatches/` and release-notes headers those builds consume. +## Purpose of This Repository -## Purpose of this repository +Central home for Armbian's build automation: the reusable GitHub Actions pipeline that produces Armbian artifacts and images across nightly, stable, community and apps tracks, plus the `userpatches/` and release-notes headers those builds consume. -This repo drives the "build all the things" side of Armbian releases. It contains: +## What's inside -- **Reusable pipeline workflows** that clone [`armbian/build`](https://github.com/armbian/build), run `compile.sh` across a large per-board matrix, and publish the resulting artifacts to OCI (`ghcr.io/armbian/os/*`) and images to GitHub Releases. -- **Thin "track" wrappers** (nightly, stable, community, apps, standard-support) that call the reusable pipeline on schedules or on manual dispatch. -- **Userpatches** (`userpatches/`) — configs, image customization, and optional extensions that the build framework picks up during a run. -- **Release header generators** (`release-headers/`) — small scripts that emit the HTML body used when the release is created. -- **Operational workflows** — a watchdog that auto-retries jobs killed by self-hosted runner stalls, and a housekeeping job that prunes old releases. +- **A reusable pipeline** (`complete-artifact-matrix.yml`) that clones [`armbian/build`](https://github.com/armbian/build), runs `compile.sh` across a per-board matrix, and publishes artifacts to OCI (`ghcr.io/armbian/os/*`) and images to GitHub Releases. +- **Thin per-track wrappers** — nightly, all, all-stable, standard-support, community, apps, base-files — that call the reusable pipeline on schedules or on manual dispatch with track-specific inputs. +- **Chunk workers** — `build-artifacts-chunk.yml` and `build-images-chunk.yml` — each is the per-chunk build body, written once and fanned out over a chunk matrix by the orchestrator. +- **Userpatches** (`userpatches/`) — configs, image customization, and optional extensions the build framework picks up during a run. +- **Release header generators** (`release-headers/`) — small shell scripts that emit the HTML body used when a release is created. +- **Operational workflows** — a watchdog that auto-retries jobs killed by self-hosted runner stalls, housekeeping that prunes old releases, and PR maintenance (labels, review listening). + +For an overview of workflow runs on this repo, see the Armbian CI dashboard: + +**CI overview:** ## Repository layout @@ -24,18 +29,9 @@ This repo drives the "build all the things" side of Armbian releases. It contain ├── .github/ │ ├── actionlint.yaml │ ├── dependabot.yml -│ └── workflows/ -│ ├── auto-retry-stalled.yml # watchdog: re-run failed jobs of a stalled run -│ ├── build-all.yml # track: Build All Artifacts -│ ├── build-all-stable.yml # track: Build All Stable Artifacts -│ ├── build-apps.yml # track: Build Apps Images -│ ├── build-community.yml # track: Build Community Images -│ ├── build-nightly.yml # track: Build Nightly Images -│ ├── build-standard-support.yml # track: Build Standard Support (admin) -│ ├── complete-artifact-matrix.yml # THE reusable pipeline -│ ├── build-artifacts-chunk.yml # reusable: one chunk of artifacts -│ ├── build-images-chunk.yml # reusable: one chunk of images -│ └── delete-old-releases.yml # housekeeping: prune old releases +│ ├── labeler.yml +│ ├── labels.yml +│ └── workflows/ # reusable pipeline, track callers, ops ├── userpatches/ │ ├── config-armbian-apps.conf │ ├── config-armbian-cloud.conf @@ -43,6 +39,7 @@ This repo drives the "build all the things" side of Armbian releases. It contain │ ├── config-armbian-images.conf │ ├── customize-image.sh │ ├── targets-all-not-eos.yaml +│ ├── targets-base-files.yaml │ └── extensions/ │ ├── docker-ce.sh │ ├── ha.sh @@ -52,12 +49,14 @@ This repo drives the "build all the things" side of Armbian releases. It contain ├── release-headers/ │ ├── community.sh │ └── os.sh +├── tools/ +│ └── update-workflow-board-lists.py └── README.md ``` ## How the pipeline is organised -The pipeline is written **once** in `complete-artifact-matrix.yml`. Each per-track workflow is a thin wrapper that calls it via `uses:` with track-specific inputs (target repository, target path, team, targets file, defaults for the manual-dispatch menu). +The pipeline is written **once** in `.github/workflows/complete-artifact-matrix.yml`. Each per-track workflow is a thin wrapper that calls it via `uses:` with track-specific inputs (target repository, target path, team, targets file, defaults for the manual-dispatch menu). Flow inside the reusable pipeline: @@ -65,42 +64,39 @@ Flow inside the reusable pipeline: team_check └─> version_prep # resolves version, creates the GitHub Release up front └─> matrix_prep # runs `compile.sh gha-matrix` -> chunked JSON matrices - ├─> build-artifacts-chunk.yml (matrixed, one job per chunk) - └─> build-images-chunk.yml (matrixed, one job per chunk) + ├─> build-artifacts-chunk.yml (matrixed, one job per chunk) + └─> build-images-chunk.yml (matrixed, one job per chunk) └─> publish / closing ``` -The per-chunk build bodies live in `build-artifacts-chunk.yml` and `build-images-chunk.yml` — each is written once and fanned out over a chunk matrix by the orchestrator. - ## Tracks (callers of the reusable pipeline) | Workflow | Trigger | Release repo | Target path | Ref | Targets file | |---|---|---|---|---|---| -| `build-nightly.yml` — Build Nightly Images | `cron: 30 22 * * *` + manual | `os` | `nightly/` | `nightly` | `targets-release-nightly.yaml` | -| `build-all.yml` — Build All Artifacts | `cron: 0 20-23/2,0-4/2 * * *`, `0 8,14 * * *` + manual | `os` | `cron/` | `all` | `targets-all-not-eos.yaml` | -| `build-all-stable.yml` — Build All Stable Artifacts | `cron: 0 2 * * *` + manual | `os` | `stable/` | `all` | `targets-all-not-eos.yaml` | -| `build-standard-support.yml` — Build Standard Support (admin) | manual | `os` | `stable/` | `stable` | `targets-release-standard-support.yaml` | -| `build-community.yml` — Build Community Images | `cron: 0 23 * * THU` + manual | `community` | `community/` | `stable` | `targets-release-community-maintained.yaml` | +| `build-nightly.yml` — Build Nightly Images | daily `30 22 * * *` + manual | `os` | `nightly/` | `nightly` | `targets-release-nightly.yaml` | +| `build-all.yml` — Build All Artifacts | `0 20-23/2,0-4/2 * * *`, `0 8,14 * * *` + manual | `os` | `cron/` | `all` | `targets-all-not-eos.yaml` | +| `build-all-stable.yml` — Build All Stable Artifacts | weekly `0 18 * * 1` + manual | `os` | `stable/` | `all` | `targets-all-not-eos.yaml` | +| `build-standard-support.yml` — Build Standard Support (admin) | manual | `os` | `images/` | `stable` | `targets-release-standard-support.yaml` | +| `build-community.yml` — Build Community Images | weekly `0 23 * * THU` + manual | `community` | `community/` | `stable` | `targets-release-community-maintained.yaml` | | `build-apps.yml` — Build Apps Images | manual | `distribution` | `apps/` | `stable` | `targets-release-apps.yaml` | +| `build-base-files.yml` — Build Base Files | daily `0 4 * * *` + manual | `os` | `base-files/` | `all` | `targets-base-files.yaml` | -Common manual-dispatch inputs on the tracks that expose them: +Common manual-dispatch inputs exposed by the tracks that surface them: -- `skipImages` — build images or artifacts only. -- `checkOci` — reuse existing artifacts already in OCI, or rebuild everything. -- `extraParamsAllBuilds` — extra `KEY=value` passed to every `compile.sh` invocation (e.g. `DEBUG=yes`). - `branch` — framework build branch to check out from `armbian/build` (default `main`). +- `forceDockerPull` — pull latest Docker image (default `yes` for manual runs) or use cached. - `targetsFilterInclude` — matrix filter, e.g. `BOARD:odroidhc4,BOARD:odroidn2`. -- `nightlybuild` — nightly vs. stable semantics. - `versionOverride` — force a specific version string. - -`build-all.yml` and `build-nightly.yml` intentionally expose only a couple of inputs; everything else falls back to the per-track defaults declared inside the wrapper, so a manual run matches a scheduled run. +- `extraParamsAllBuilds` (base-files) — extra `KEY=value` passed to every `compile.sh` invocation (e.g. `DEBUG=yes`). +- `board` / `maintainer` (standard-support) — build a single board or all boards of a given maintainer. ## Versioning Versioning is driven entirely by GitHub releases on the target repository — there is no version file in this repo: -- **Stable** builds require `versionOverride` (e.g. `26.8.0`). +- **Stable** builds reuse the latest `X.Y.Z` release as-is; `versionOverride` cuts a new version. The weekly `build-all-stable` opts into `stable_bump: yes`, which bumps `X.Y.Z -> X.Y.(Z+1)`. - **Nightly** builds pick the newest `-trunk.N` release in the target repo and bump `N`; `versionOverride` can seed a new base series. +- A `-trunk.N` counter can be shared across a leader repo and peer repos (`trunk_peer_repositories`) so numbering stays monotonic across e.g. `armbian/ci` and `armbian/community`. The release is created empty up front by `version_prep`, and the image jobs attach assets to that tag. @@ -110,7 +106,7 @@ The `userpatches/` directory is checked out inside every build and copied into t - `config-armbian-images.conf`, `config-armbian-community.conf`, `config-armbian-apps.conf`, `config-armbian-cloud.conf` — per-config build settings (selected via each track's `prepare_config`). - `customize-image.sh` — image customization hook. -- `targets-all-not-eos.yaml` — targets list used by the "all" tracks (release-specific target lists are fetched at build time from [`armbian/armbian.github.io`](https://github.com/armbian/armbian.github.io) `data` branch). +- `targets-all-not-eos.yaml`, `targets-base-files.yaml` — targets lists (release-specific targets are additionally fetched at build time from [`armbian/armbian.github.io`](https://github.com/armbian/armbian.github.io) `data` branch). - `extensions/` — optional build extensions: `docker-ce.sh`, `ha.sh`, `kali.sh`, `omv.sh`, `openhab.sh`. ## Release headers @@ -119,50 +115,30 @@ The `userpatches/` directory is checked out inside every build and copied into t ## Operational workflows -### `auto-retry-stalled.yml` — self-healing against runner stalls - -Self-hosted runners occasionally drop mid-job (the build itself is green, but a later step like log upload dies), which marks the whole run failed. This watchdog listens for `workflow_run: completed` on the build tracks and, if the run failed: - -- Counts failed jobs in the latest attempt. -- If `run_attempt < 10` **and** `failed <= MAX_FAILED_TO_RETRY` (default `30`), calls `gh run rerun --failed` to restart only the failed jobs. -- Otherwise leaves the run red and emits a warning — that shape of failure looks systemic, not a stall. - -It also has a `workflow_dispatch` entry with a `run_id` input (and `ignore_threshold`) so an operator can force a re-run of a specific run's failed jobs. - -Note: the build chunks are `fail-fast: false`, so good jobs finish and upload artifacts even while a few stall. The watchdog therefore waits for the run to finish rather than cancelling it. - -### `delete-old-releases.yml` — release housekeeping - -Runs daily at 03:00 UTC (and on manual dispatch). Only runs when the repo owner is `armbian`. For both full releases and pre-releases, it keeps the newest 3 (sorted by `created_at`) and deletes the rest via the GitHub API. - -## Build execution details - -Per-chunk jobs (`build-artifacts-chunk.yml`, `build-images-chunk.yml`): +- **Auto-retry stalled runs.** Listens for `workflow_run: completed` on the build tracks and, if the run failed, re-runs only the failed jobs via `gh run rerun --failed`, guarded by an attempt budget and a majority-green threshold. A `workflow_dispatch` entry with `run_id` (and `ignore_threshold`) lets an operator force a re-run of a specific run. +- **Delete old releases.** Runs daily at 03:00 UTC; only runs when the repo owner is `armbian`. Keeps the newest 3 stable (`X.Y.Z`) and 3 trunk (`X.Y.Z-trunk.N`) releases sorted by parsed version, prunes the rest. +- **PR maintenance.** Auto-labels PRs by size, category, and quarter; removes `Ready to merge` on new commits; adds it back on committer approval; syncs `.github/labels.yml` to actual repo labels. -- Run with `fail-fast: false` so a single unstable board does not sink its neighbours. -- Timeouts: 65 min for artifact chunks (60 min build + OCI push), 75 min for image chunks (45 min build + sign/torrent/upload). -- Retry the actual `compile.sh` invocation up to `BUILD_ATTEMPTS` (default `3`) times to ride out transient network/runner flakes, replacing an older external watchdog. -- Look up per-runner metadata from `https://github.armbian.com/servers/github-runners.jq` and export `APT_PROXY_ADDR`, `GHCR_MIRROR_ADDRESS`, `CCACHE_REMOTE_STORAGE`, `GITPROXY_ADDRESS` when the runner advertises them. Any ambient `http_proxy`/`https_proxy` from the runner host is neutralised first; a configured apt proxy is probed before use and dropped if unreachable. -- Log in to `ghcr.io` and push artifacts to `ghcr.io/armbian/os/*`. This requires a PAT with `write:packages` on `armbian/os`; the workflow uses `ACCESS_TOKEN` and falls back to `GITHUB_TOKEN` when unset. -- Image chunks also pull release-target YAML files from the `data` branch of `armbian/armbian.github.io`. +## Tooling -## Secrets +`tools/update-workflow-board-lists.py` regenerates the `board` and `maintainer` choice lists in `build-standard-support.yml` between the `>>> board-options` / `>>> maintainer-options` sentinel comments — do not edit those lists by hand. -Used by the reusable pipeline / chunk workflows (declared as `secrets: inherit` on the callers): +## Built with -- `ACCESS_TOKEN` — cross-repo PAT (write to `armbian/os` etc., `write:packages` on GHCR). Optional; falls back to `GITHUB_TOKEN` for read/limited paths. -- `ORG_MEMBERS` — used by `armbian/actions/team-check` to gate who can trigger a run. -- `KEY_UPLOAD`, `KNOWN_HOSTS_ARMBIAN_UPLOAD` — required by image chunks to publish images. -- `GPG_KEY1`, `GPG_PASSPHRASE1` — optional, for signing. +- **YAML** — GitHub Actions workflows in `.github/workflows/`, Dependabot, actionlint and labeler configs. +- **Bash** — steps inside those workflows (via `run:`), release-header generators, `customize-image.sh`, and the extensions in `userpatches/extensions/`. +- **Python 3** — `tools/update-workflow-board-lists.py`. +- **Shell tools invoked by the pipeline**: `gh` (GitHub CLI), `jq`, `curl`, `rsync`, `mktorrent`, plus the `armbian/build` framework's `compile.sh`. +- **Shared actions**: [`armbian/actions`](https://github.com/armbian/actions) (`runner-clean`, `team-check`) and standard actions such as `actions/checkout`, `actions/labeler`, `docker/login-action`. ## Related repositories -- [`armbian/build`](https://github.com/armbian/build) — the build framework (`compile.sh`) this pipeline drives. -- [`armbian/os`](https://github.com/armbian/os), [`armbian/community`](https://github.com/armbian/community), [`armbian/distribution`](https://github.com/armbian/distribution) — release repositories where images and artifact metadata land. -- [`armbian/actions`](https://github.com/armbian/actions) — shared composite actions (`runner-clean`, `team-check`, …) used by the workflows here. -- [`armbian/armbian.github.io`](https://github.com/armbian/armbian.github.io) — hosts the release-target YAML files (`data` branch). +- [`armbian/build`](https://github.com/armbian/build) — the build framework this repo drives. +- [`armbian/armbian.github.io`](https://github.com/armbian/armbian.github.io) — release-target YAML consumed at build time (`data` branch). +- [`armbian/actions`](https://github.com/armbian/actions) — shared composite/JS actions used by these workflows. -## Further reading +## Links -- Armbian documentation: -- Project home: +- Documentation: +- Project website: +- CI overview for this repo: