secubox-deb/.github/workflows/build-kernel.yml
CyberMind-FR 6eb399eade fix(ci): heredoc → loop for arm64 ports.list (YAML parser couldn't handle col-0 EOF)
Previous attempt used a heredoc with EOF marker at column 0, which
YAML parses as a new top-level key, breaking the workflow file.
Replace with the same loop pattern used elsewhere in the step
(echo | tee -a with iteration over codename suites).
2026-06-02 13:29:37 +02:00

172 lines
8.3 KiB
YAML

name: Build SecuBox kernel (cross arm64)
on:
workflow_dispatch:
inputs:
kernel_version:
description: 'Upstream kernel version (e.g. 6.12.85)'
required: true
default: '6.12.85'
type: string
revision:
description: 'Local revision suffix (-Nsecubox)'
required: true
default: '2secubox'
type: string
# Single in-flight build to avoid wasted CI minutes on a long job.
concurrency:
group: build-kernel-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: cross-arm64 ${{ inputs.kernel_version }}
runs-on: ubuntu-latest
timeout-minutes: 90
env:
KERNEL_VERSION: ${{ inputs.kernel_version }}
REVISION: ${{ inputs.revision }}
DEBFULLNAME: SecuBox Builder
DEBEMAIL: devel@cybermind.fr
KDEB_PKGVERSION: ${{ inputs.kernel_version }}-${{ inputs.revision }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install cross toolchain + build deps
run: |
# Enable arm64 multi-arch with the proper Ubuntu ports mirror.
# security.ubuntu.com / archive.ubuntu.com serve amd64/i386 only ;
# arm64 comes from ports.ubuntu.com. Without this, `apt-get update`
# 404s on arm64 indices after `dpkg --add-architecture arm64`.
# bindeb-pkg under `dpkg-buildpackage -aarm64` then needs
# libssl-dev:arm64 to satisfy the kernel package Build-Depends.
sudo dpkg --add-architecture arm64
# Modern Ubuntu runners (noble+) use DEB822 sources.list.d/ubuntu.sources
# — not the legacy /etc/apt/sources.list. Pin EVERY existing source
# (legacy .list and DEB822 .sources) to amd64, then add an arm64
# pointer to ports.ubuntu.com (security/archive serve amd64 only).
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.list; do
[ -f "$f" ] && sudo sed -i 's|^deb http|deb [arch=amd64] http|; s|^deb https|deb [arch=amd64] https|' "$f"
done
for f in /etc/apt/sources.list.d/*.sources; do
[ -f "$f" ] && grep -q '^Architectures:' "$f" \
|| ([ -f "$f" ] && sudo sed -i '/^Types:/a Architectures: amd64' "$f")
done
CODENAME=$(. /etc/os-release && echo "$VERSION_CODENAME")
PORTS_LIST=/etc/apt/sources.list.d/arm64-ports.list
sudo rm -f "$PORTS_LIST"
for suite in "$CODENAME" "${CODENAME}-updates" "${CODENAME}-security" "${CODENAME}-backports"; do
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ $suite main restricted universe multiverse" \
| sudo tee -a "$PORTS_LIST" >/dev/null
done
sudo apt-get update -qq
# build-essential is needed because bindeb-pkg auto-generates a
# debian/control that lists `build-essential:native` in
# Build-Depends; dpkg-checkbuilddeps fails the run without it
# even though every individual binary it pulls in (gcc, g++,
# libc-dev, make) is independently installable.
sudo apt-get install -y --no-install-recommends \
build-essential \
gcc-aarch64-linux-gnu make bc flex bison \
libssl-dev libssl-dev:arm64 libelf-dev wget xz-utils \
kmod cpio rsync debhelper dpkg-dev fakeroot \
python3 git
- name: Download upstream kernel ${{ inputs.kernel_version }}
run: |
mkdir -p /tmp/build && cd /tmp/build
# 6.x major in URL — sufficient for the 6.x series.
MAJOR="$(echo "$KERNEL_VERSION" | cut -d. -f1)"
wget -q "https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${KERNEL_VERSION}.tar.xz"
tar xf "linux-${KERNEL_VERSION}.tar.xz"
- name: Apply SecuBox patches (if any)
run: |
cd /tmp/build/linux-${KERNEL_VERSION}
if [ -d "${GITHUB_WORKSPACE}/kernel-build/patches" ]; then
for p in "${GITHUB_WORKSPACE}/kernel-build/patches"/*.patch; do
[ -f "$p" ] && patch -p1 -N < "$p" || true
done
fi
- name: Merge SecuBox config fragments
run: |
cd /tmp/build/linux-${KERNEL_VERSION}
make ARCH=arm64 defconfig
# Merge order: upstream defconfig <- OpenWrt-merged base <- ZRAM (last write wins).
scripts/kconfig/merge_config.sh -m .config \
"${GITHUB_WORKSPACE}/board/mochabin/kernel/config-6.12-openwrt-merged.fragment" \
"${GITHUB_WORKSPACE}/board/mochabin/kernel/config-6.12.85-secubox-zram.fragment"
# Resolve deps + olddefconfig FIRST, then override the ZRAM
# compressor choice via sed. olddefconfig is what we're fighting:
# it re-resolves any kconfig `choice` block back to its declared
# default (ZRAM_DEF_COMP_LZORLE) even if a member is marked =y
# in .config. scripts/config --enable on a choice member applied
# BEFORE olddefconfig is silently undone by olddefconfig.
# These symbols are NOT inside a choice block — safe to set early.
scripts/config --enable ZSMALLOC \
--enable CRYPTO_ZSTD \
--enable CRYPTO_LZ4 \
--enable CRYPTO_LZO
make ARCH=arm64 olddefconfig
# ZRAM compressor choice — surgical sed AFTER olddefconfig. The
# rest of the tree is already consistent so no further olddefconfig
# is needed; choice members are leaf symbols with no downstream
# build-time dependencies. This is the only reliable way: choice
# resolution in olddefconfig honours `default <member>` from
# Kconfig and ignores individual member =y lines.
echo "=== ZRAM choice pre-fixup ==="
grep -E "^(# )?CONFIG_ZRAM_DEF_COMP" .config || true
if ! grep -q "^CONFIG_ZRAM_DEF_COMP_ZSTD=y" .config; then
echo "INFO: olddefconfig defaulted the choice to LZORLE; forcing ZSTD"
sed -i 's/^CONFIG_ZRAM_DEF_COMP_LZORLE=y/# CONFIG_ZRAM_DEF_COMP_LZORLE is not set/' .config
sed -i 's/^# CONFIG_ZRAM_DEF_COMP_ZSTD is not set/CONFIG_ZRAM_DEF_COMP_ZSTD=y/' .config
# If kconfig dropped the symbol entirely, append it.
grep -q "ZRAM_DEF_COMP_ZSTD" .config || echo "CONFIG_ZRAM_DEF_COMP_ZSTD=y" >> .config
fi
echo "=== ZRAM choice post-fixup ==="
grep -E "^(# )?CONFIG_ZRAM" .config || true
# Sanity-check key configs landed.
grep -q "CONFIG_LEDS_IS31FL319X=m" .config || (echo "FAIL: LED module missing" && exit 1)
grep -q "CONFIG_ZRAM=m" .config || (echo "FAIL: ZRAM module missing" && exit 1)
grep -q "^CONFIG_ZRAM_DEF_COMP_ZSTD=y" .config || (echo "FAIL: ZRAM zstd default missing" && exit 1)
# Wireless mesh stack (CM-MESH-MPCIE-2026-06 v0.2.1)
grep -q "CONFIG_MT76x2U=m" .config || (echo "FAIL: mt76x2u missing" && exit 1)
grep -q "CONFIG_ATH10K_PCI=m" .config || (echo "FAIL: ath10k_pci missing" && exit 1)
grep -q "CONFIG_ATH9K_HTC=m" .config || (echo "FAIL: ath9k_htc missing" && exit 1)
grep -q "CONFIG_MAC80211_MESH=y" .config || (echo "FAIL: 802.11s missing" && exit 1)
- name: Build kernel .deb (bindeb-pkg)
run: |
cd /tmp/build/linux-${KERNEL_VERSION}
# bindeb-pkg cross-builds a real linux-image-*.deb + linux-headers-*.deb.
# KDEB_PKGVERSION sets the .deb version string.
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
-j"$(nproc)" \
KDEB_PKGVERSION="${KDEB_PKGVERSION}" \
bindeb-pkg
- name: Collect .deb artifacts
run: |
mkdir -p /tmp/artifacts
# bindeb-pkg drops .deb files in /tmp/build (one level above the src tree).
cp /tmp/build/linux-image-*.deb /tmp/artifacts/ 2>/dev/null || true
cp /tmp/build/linux-headers-*.deb /tmp/artifacts/ 2>/dev/null || true
cp /tmp/build/linux-libc-dev*.deb /tmp/artifacts/ 2>/dev/null || true
ls -la /tmp/artifacts/
- name: Upload kernel .deb bundle
uses: actions/upload-artifact@v4
with:
name: secubox-kernel-${{ inputs.kernel_version }}-${{ inputs.revision }}-arm64
path: /tmp/artifacts/*.deb
if-no-files-found: error
retention-days: 30