From 238a814d612c28a7eeecd3ae41e49bf1b28e161b Mon Sep 17 00:00:00 2001 From: Mathias Beaulieu-Duncan Date: Tue, 16 Jun 2026 09:54:19 -0400 Subject: [PATCH] ci: run pipeline natively on arm64 act runners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - runs-on: arm64 (was talos-rpi5/macOS Mac Mini) - replace Homebrew deps with native arm64 (crane+jq static binaries) - gmake -> make across workflows and auto-update.sh - guard Homebrew gnu-sed PATH in Makefile for Linux - no QEMU/binfmt — builds are native arm64 - docs: TECHNICAL.md runner setup for ASUS GX10 Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/build.yaml | 42 ++++++++++++++++++----------- .gitea/workflows/check-updates.yaml | 21 ++++++++++----- Makefile | 5 +++- TECHNICAL.md | 32 +++++++++++++--------- scripts/auto-update.sh | 9 ++++--- 5 files changed, 72 insertions(+), 37 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 6ffd851..d0eeb32 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -1,13 +1,13 @@ # Build and release custom Talos CM5 image # # Triggered by pushing a version tag (e.g. v1.11.5-1) -# Runs on ARM64 self-hosted runner (ASUS GX10) # # Produces: # - Installer container image → Docker Hub (svrnty/talos-rpi5:) # - Raw disk image → Gitea release (metal-arm64.raw.zst) # -# Runner: Apple Silicon Mac Mini (self-hosted, macOS, arm64) +# Runner: ASUS GX10 (self-hosted, Linux, arm64), host mode. +# Builds natively on arm64 — no QEMU/binfmt emulation. name: Build Talos CM5 Image @@ -18,7 +18,7 @@ on: jobs: build: - runs-on: talos-rpi5 + runs-on: arm64 timeout-minutes: 180 steps: @@ -30,14 +30,26 @@ jobs: - name: Install build dependencies run: | - for pkg in make gnu-sed crane; do - brew list --formula "$pkg" &>/dev/null || brew install "$pkg" - done - echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> "$GITHUB_PATH" - gmake --version | head -1 + # Native arm64 host — make, sed, git, docker and buildx come from the host. + # Only crane + jq are fetched (static arm64 binaries, no sudo, no QEMU). + mkdir -p "$HOME/.local/bin" + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + export PATH="$HOME/.local/bin:$PATH" + if ! command -v crane >/dev/null 2>&1; then + curl -fsSL https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_arm64.tar.gz \ + | tar -xz -C "$HOME/.local/bin" crane + fi + if ! command -v jq >/dev/null 2>&1; then + curl -fsSL https://github.com/jqlang/jq/releases/latest/download/jq-linux-arm64 -o "$HOME/.local/bin/jq" + chmod +x "$HOME/.local/bin/jq" + fi + make --version | head -1 + crane version || true - name: Set up Docker Buildx run: | + # Native arm64 builder — the docker-container driver is used only for + # SBOM/provenance attestation, not for cross-arch (no QEMU registered). docker buildx version docker buildx create --name talos-builder --driver docker-container --use 2>/dev/null || docker buildx use talos-builder docker buildx inspect --bootstrap @@ -50,22 +62,22 @@ jobs: run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" - name: Clone upstream sources - run: gmake checkouts + run: make checkouts - name: Apply patches - run: gmake patches + run: make patches - name: Build kernel - run: gmake kernel + run: make kernel - name: Build SBC overlay - run: gmake overlay + run: make overlay - name: Build installer and disk image - run: gmake installer + run: make installer - name: Tag release images - run: gmake release TAG=${{ steps.version.outputs.tag }} + run: make release TAG=${{ steps.version.outputs.tag }} - name: Compress disk image run: | @@ -126,4 +138,4 @@ jobs: - name: Clean up if: always() - run: gmake clean + run: make clean diff --git a/.gitea/workflows/check-updates.yaml b/.gitea/workflows/check-updates.yaml index 1b6badc..e3dcbac 100644 --- a/.gitea/workflows/check-updates.yaml +++ b/.gitea/workflows/check-updates.yaml @@ -13,7 +13,7 @@ on: jobs: check-and-build: - runs-on: talos-rpi5 + runs-on: arm64 timeout-minutes: 15 steps: @@ -24,10 +24,19 @@ jobs: - name: Install dependencies run: | - for pkg in make gnu-sed crane jq; do - brew list --formula "$pkg" &>/dev/null || brew install "$pkg" - done - echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> "$GITHUB_PATH" + # Native arm64 host — make, sed, git come from the host. + # Only crane + jq are fetched (static arm64 binaries, no sudo, no QEMU). + mkdir -p "$HOME/.local/bin" + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + export PATH="$HOME/.local/bin:$PATH" + if ! command -v crane >/dev/null 2>&1; then + curl -fsSL https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_arm64.tar.gz \ + | tar -xz -C "$HOME/.local/bin" crane + fi + if ! command -v jq >/dev/null 2>&1; then + curl -fsSL https://github.com/jqlang/jq/releases/latest/download/jq-linux-arm64 -o "$HOME/.local/bin/jq" + chmod +x "$HOME/.local/bin/jq" + fi - name: Check for upstream updates id: check @@ -86,7 +95,7 @@ jobs: ### Steps 1. Check out this repo and run \`scripts/auto-update.sh\` to see what fails 2. Port patches to the new upstream version - 3. Verify: \`gmake checkouts patches && gmake checkouts-clean\` + 3. Verify: \`make checkouts patches && make checkouts-clean\` 4. Push changes — the next scheduled run will pick them up ### Links diff --git a/Makefile b/Makefile index 0126245..f549858 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,11 @@ PKG_VERSION = v1.13.0 TALOS_VERSION = v1.13.2 SBCOVERLAY_VERSION = main -# Prefer GNU coreutils (macOS: brew install gnu-sed coreutils) +# Prefer GNU coreutils. Native on the Linux arm64 runner; on macOS use the +# Homebrew gnu-sed if present (brew install gnu-sed coreutils). +ifneq ($(wildcard /opt/homebrew/opt/gnu-sed/libexec/gnubin),) export PATH := /opt/homebrew/opt/gnu-sed/libexec/gnubin:$(PATH) +endif REGISTRY ?= docker.io REGISTRY_USERNAME ?= svrnty diff --git a/TECHNICAL.md b/TECHNICAL.md index 45732c2..90bcc93 100644 --- a/TECHNICAL.md +++ b/TECHNICAL.md @@ -37,32 +37,40 @@ A weekly scheduled workflow checks for new Talos and RPi kernel releases and cre | `REGISTRY_USERNAME` | Docker Hub username (org-level) | | `REGISTRY_PASSWORD` | Docker Hub access token (org-level) | -## Runner Setup (Apple Silicon Mac Mini) +## Runner Setup (ASUS GX10 — Linux arm64) -The build runner needs: -- Docker Desktop with Buildx (arm64 native) -- Gitea `act_runner` registered with labels: `self-hosted`, `macOS`, `arm64` +Builds run **natively on arm64** — no QEMU/binfmt emulation. The runner executes +jobs in **host mode** (directly on the Linux host, not in a container), so the +host provides the toolchain. + +The build host needs: +- Docker Engine + the Buildx plugin (arm64 native) +- `make`, `git`, `curl`, `tar` (e.g. `apt-get install -y make git curl tar`) - Sufficient disk space for kernel builds (~20GB) -```bash -# Install act_runner via Homebrew -brew install act_runner +`crane` and `jq` are fetched automatically by the workflows (static arm64 +binaries into `~/.local/bin`), so they don't need to be pre-installed. -# Or download directly -curl -sL https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-darwin-arm64 -o act_runner +```bash +# Download the act_runner for linux/arm64 +curl -sL https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-linux-arm64 -o act_runner chmod +x act_runner -# Register +# Register — the `:host` label runs jobs directly on the host (no container) ./act_runner register \ --instance https://git.openharbor.io \ --token \ - --name mac-mini \ - --labels self-hosted,macOS,arm64 + --name gx10 \ + --labels arm64:host # Run as service ./act_runner daemon ``` +> The workflows use `runs-on: arm64`. The `arm64:host` label maps that to host +> execution; drop `:host` only if you switch to container-based jobs (which then +> need Docker-in-Docker for the privileged build steps). + ## Project Structure ``` diff --git a/scripts/auto-update.sh b/scripts/auto-update.sh index 7f09b04..8848e4b 100755 --- a/scripts/auto-update.sh +++ b/scripts/auto-update.sh @@ -21,6 +21,9 @@ LATEST_RPI_TAG=${LATEST_RPI_TAG:-} MAKEFILE="Makefile" PATCH_FILE="patches/siderolabs/pkgs/0001-Patched-for-Raspberry-Pi-5.patch" +# GNU make: `gmake` on macOS (Homebrew), `make` on the Linux arm64 runner. +MAKE=$(command -v gmake || command -v make) + # Helper: extract kernel semver (e.g. 6.12.47) from the RPi repo Makefile get_kernel_version() { local tag="$1" @@ -81,13 +84,13 @@ fi # ── Smoke test — verify patches apply ─────────────────────────────── echo "Running patch smoke test ..." >&2 -if ! gmake checkouts patches; then +if ! "$MAKE" checkouts patches; then echo "Patches failed to apply!" >&2 - gmake checkouts-clean >/dev/null 2>&1 || true + "$MAKE" checkouts-clean >/dev/null 2>&1 || true echo "patch_failed=true" exit 0 fi -gmake checkouts-clean >/dev/null 2>&1 +"$MAKE" checkouts-clean >/dev/null 2>&1 # ── Generate tag ──────────────────────────────────────────────────── TALOS_VER=$(grep '^TALOS_VERSION' "$MAKEFILE" | awk '{print $NF}')