Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8addbad
ci: add real qemu boot checks for CapOS
fwerkor Jun 24, 2026
9d035e7
ci: reduce real boot build log noise
fwerkor Jun 24, 2026
4fc4c94
ci: cancel stale real boot runs
fwerkor Jun 24, 2026
519d290
ci: keep experimental mips real boot non-gating
fwerkor Jun 24, 2026
e230401
ci: fix mips64el rust target mapping
fwerkor Jun 24, 2026
d738d92
ci: drop mips64el real boot target
fwerkor Jun 24, 2026
da57811
ci: reclaim disk space for real boot builds
fwerkor Jun 24, 2026
37b775d
ci: skip gpgme tool in real boot builds
fwerkor Jun 24, 2026
8acc79a
ci: avoid building gpgme utilities in boot check
fwerkor Jun 24, 2026
9d839a7
ci: pin gpgme gpgrt-config to target staging
fwerkor Jun 25, 2026
bb71458
ci: install host fuse3 development files
fwerkor Jun 25, 2026
21c7f2f
ci: fix ArgosFS package version for apk builds
fwerkor Jun 26, 2026
bc3b1b2
armsr: use compressed arm64 kernel image
fwerkor Jun 26, 2026
706b581
armsr: boot compressed arm64 EFI kernels
fwerkor Jun 26, 2026
45d663c
ci: test aarch64 with 64MiB kernel partition
fwerkor Jun 26, 2026
e83fe42
armsr: build arm64 EFI zboot kernels
fwerkor Jun 27, 2026
68569c7
armsr: boot arm64 EFI zboot images
fwerkor Jun 27, 2026
b0a4c58
armsr: enable compressed EFI zboot
fwerkor Jun 27, 2026
83863cb
armsr: enable compressed EFI zboot
fwerkor Jun 27, 2026
ffd5bb3
armsr: add ArgosFS autoscan to EFI boot
fwerkor Jun 28, 2026
78e4282
ci: use stable arm64 ArgosFS root device in QEMU
fwerkor Jun 28, 2026
d50b9a4
armsr: keep EFI grub template generic
fwerkor Jun 28, 2026
6c0f596
armsr: use ArgosFS autoscan for root boot
fwerkor Jun 28, 2026
489aafb
ci: rely on armsr ArgosFS boot defaults
fwerkor Jun 28, 2026
33a0b22
ci: remove arm64 root device override
fwerkor Jun 28, 2026
62d2015
armsr: keep ArgosFS autoscan as system default
fwerkor Jun 28, 2026
68493dd
ci: confirm generic arm64 boot configuration
fwerkor Jun 28, 2026
60bdef3
armsr: finalize ArgosFS autoscan default
fwerkor Jun 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 208 additions & 0 deletions .github/workflows/os-real-boot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
name: OS Real Boot Check

on:
pull_request:
branches: ["main"]
paths:
- ".config"
- ".github/workflows/os-real-boot.yml"
- "config/**"
- "feeds.conf*"
- "include/**"
- "package/capos/**"
- "package/utils/argosfs/**"
- "scripts/ci/**"
- "target/linux/generic/**"
- "target/linux/x86/**"
- "target/linux/armsr/**"
- "toolchain/**"
push:
branches: ["main"]
paths:
- ".config"
- ".github/workflows/os-real-boot.yml"
- "config/**"
- "feeds.conf*"
- "include/**"
- "package/capos/**"
- "package/utils/argosfs/**"
- "scripts/ci/**"
- "target/linux/generic/**"
- "target/linux/x86/**"
- "target/linux/armsr/**"
- "toolchain/**"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: os-real-boot-${{ github.ref }}
cancel-in-progress: true

jobs:
real-boot:
name: Build + QEMU boot (${{ matrix.name }})
runs-on: ubuntu-22.04
timeout-minutes: 360
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
CCACHE_MAXSIZE: 2G

strategy:
fail-fast: false
matrix:
include:
- name: x86_64
target: x86
subtarget: "64"
- name: aarch64
target: armsr
subtarget: armv8

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Install build and QEMU prerequisites
shell: bash
run: |
set -euxo pipefail
sudo apt-get update
sudo apt-get install -y \
bash build-essential ccache clang flex bison g++ gawk gcc-multilib \
gettext git jq libelf-dev libncurses-dev libssl-dev make patch perl \
python3 python3-distutils python3-pyelftools python3-setuptools \
rsync unzip wget zlib1g-dev file curl netcat-openbsd \
pkg-config fuse3 libfuse3-dev \
qemu-system-arm qemu-system-x86 qemu-utils qemu-efi-aarch64

- name: Free runner disk space
shell: bash
run: |
set -euxo pipefail
mkdir -p ci-artifacts
{
echo "===== before cleanup ====="
df -h
echo
sudo du -sh /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache /usr/local/.ghcup 2>/dev/null || true
docker system df || true
} | tee "ci-artifacts/disk-cleanup-${{ matrix.name }}.txt"

sudo rm -rf \
/usr/share/dotnet \
/usr/local/lib/android \
/opt/ghc \
/opt/hostedtoolcache/CodeQL \
/opt/hostedtoolcache/go \
/opt/hostedtoolcache/node \
/opt/hostedtoolcache/Python \
/usr/local/.ghcup || true
docker system prune -af --volumes || true
sudo apt-get clean

{
echo
echo "===== after cleanup ====="
df -h
docker system df || true
} | tee -a "ci-artifacts/disk-cleanup-${{ matrix.name }}.txt"

- name: Cache downloads
uses: actions/cache@v4
with:
path: dl
key: capos-dl-${{ matrix.name }}-${{ hashFiles('feeds.conf.default', 'feeds.conf', 'package/**/Makefile', 'target/linux/**/Makefile') }}
restore-keys: |
capos-dl-${{ matrix.name }}-
capos-dl-

- name: Cache compiler output
uses: actions/cache@v4
with:
path: .ccache
key: capos-ccache-${{ matrix.name }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
capos-ccache-${{ matrix.name }}-${{ github.ref_name }}-
capos-ccache-${{ matrix.name }}-

- name: Limit compiler cache size
shell: bash
run: |
set -euxo pipefail
mkdir -p "$CCACHE_DIR" ci-artifacts
ccache --max-size="$CCACHE_MAXSIZE"
ccache --cleanup || true
ccache --show-stats | tee "ci-artifacts/ccache-before-${{ matrix.name }}.txt"

- name: Configure CapOS target
shell: bash
run: |
set -euxo pipefail
mkdir -p ci-artifacts
if [ ! -f feeds.conf ] && [ -f feeds.conf.default ]; then
cp feeds.conf.default feeds.conf
fi
./scripts/feeds list >/dev/null
./scripts/feeds install -a
scripts/ci/capos-real-boot-config.sh "${{ matrix.target }}" "${{ matrix.subtarget }}"
make defconfig
cp .config "ci-artifacts/config-${{ matrix.name }}"
./scripts/diffconfig.sh | tee "ci-artifacts/diffconfig-${{ matrix.name }}.txt"

- name: Download sources
shell: bash
run: |
set -euxo pipefail
scripts/ci/run-with-log.sh "ci-artifacts/download-${{ matrix.name }}.log" \
"Download sources (${{ matrix.name }})" -- \
make -j"$(nproc)" download V=s

- name: Build image
shell: bash
run: |
set -euxo pipefail
mkdir -p ci-artifacts
{
echo "===== before build ====="
df -h
echo
du -sh dl .ccache build_dir staging_dir tmp 2>/dev/null || true
} | tee "ci-artifacts/disk-before-build-${{ matrix.name }}.txt"
set +e
scripts/ci/run-with-log.sh "ci-artifacts/build-${{ matrix.name }}.log" \
"Parallel image build (${{ matrix.name }})" -- \
make -j"$(nproc)" V=s
status=$?
set -e
if [ "$status" -ne 0 ]; then
echo "parallel build failed; retrying serially for a deterministic error log"
df -h | tee -a "ci-artifacts/disk-before-serial-retry-${{ matrix.name }}.txt" || true
scripts/ci/run-with-log.sh --append "ci-artifacts/build-${{ matrix.name }}.log" \
"Serial image build retry (${{ matrix.name }})" -- \
make -j1 V=sc
fi

- name: QEMU boot and probe 2000/tcp
shell: bash
run: |
set -euxo pipefail
CAPOS_CI_ARTIFACT_DIR=ci-artifacts \
CAPOS_CI_BOOT_TIMEOUT_S=360 \
scripts/ci/qemu-port-check.sh "${{ matrix.target }}" "${{ matrix.subtarget }}"

- name: Upload diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: capos-real-boot-${{ matrix.name }}
path: |
ci-artifacts/**
logs/**
bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/*.manifest
bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/*sha256sums
if-no-files-found: ignore
retention-days: 14
1 change: 1 addition & 0 deletions .github/workflows/os-sanity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ jobs:
tests/capbox_logic_tests.sh
tests/webpanel_frontend_smoke.sh
tests/webpanel_proxy_smoke.sh
tests/webpanel_runtime_config_smoke.sh

- name: Kconfig sanity (defconfig)
shell: bash
Expand Down
2 changes: 2 additions & 0 deletions feeds/packages/libs/gpgme/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ PKG_BUILD_PARALLEL:=1

include $(INCLUDE_DIR)/package.mk

CONFIGURE_VARS += ac_cv_path_GPGRT_CONFIG="$(STAGING_DIR)/usr/bin/gpgrt-config"

define Package/libgpgme
SECTION:=libs
CATEGORY:=Libraries
Expand Down
12 changes: 12 additions & 0 deletions package/capos/capos-webpanel/files/90-capos-webpanel-uhttpd
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
#!/bin/sh

# CapOS exposes its built-in web panel on stable, documented ports instead of
# OpenWrt's stock 80/443 defaults.
uci -q delete uhttpd.main.listen_http
uci add_list uhttpd.main.listen_http='0.0.0.0:2000'
uci add_list uhttpd.main.listen_http='[::]:2000'
uci -q delete uhttpd.main.listen_https
uci add_list uhttpd.main.listen_https='0.0.0.0:2020'
uci add_list uhttpd.main.listen_https='[::]:2020'
uci -q set uhttpd.main.home='/www'
uci -q set uhttpd.main.cgi_prefix='/cgi-bin'
uci -q set uhttpd.main.redirect_https='0'

# ArgosFS currently rejects fsync for px5g output under /etc on first boot.
# Generate uhttpd's self-signed certificate on tmpfs instead.
uci -q set uhttpd.main.cert='/tmp/uhttpd.crt'
Expand Down
1 change: 1 addition & 0 deletions package/utils/argosfs/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=argosfs
PKG_VERSION:=0.1.0
PKG_RELEASE:=1

PKG_SOURCE_PROTO:=git
Expand Down
91 changes: 91 additions & 0 deletions scripts/ci/capos-real-boot-config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/env bash

set -euo pipefail

if [[ $# -ne 2 ]]; then
echo "usage: $0 <target> <subtarget>" >&2
exit 2
fi

target="$1"
subtarget="$2"

patch_pinned_rust_feed_for_ci() {
local rust_values="feeds/packages/lang/rust/rust-values.mk"

if [[ "$target/$subtarget" != "malta/le64" || ! -f "$rust_values" ]]; then
return 0
fi

if grep -q 'mips64el-unknown-linux-muslabi64' "$rust_values"; then
return 0
fi

python3 - <<'PY'
from pathlib import Path

path = Path("feeds/packages/lang/rust/rust-values.mk")
text = path.read_text()
old = """else ifeq ($(ARCH),riscv64)\n RUSTC_TARGET_ARCH:=$(subst riscv64,riscv64gc,$(RUSTC_TARGET_ARCH))\nendif\n"""
new = """else ifeq ($(ARCH),riscv64)\n RUSTC_TARGET_ARCH:=$(subst riscv64,riscv64gc,$(RUSTC_TARGET_ARCH))\nelse ifeq ($(ARCH),mips64el)\n RUSTC_TARGET_ARCH:=$(subst linux-musl,linux-muslabi64,$(RUSTC_TARGET_ARCH))\nendif\n"""
if old not in text:
raise SystemExit("could not patch pinned rust feed target mapping")
path.write_text(text.replace(old, new, 1))
PY
}

case "$target/$subtarget" in
x86/64|armsr/armv8|malta/le64)
;;
*)
echo "unsupported CapOS real boot CI target: $target/$subtarget" >&2
exit 2
;;
esac

patch_pinned_rust_feed_for_ci

cat > .config <<CONFIG
CONFIG_TARGET_${target}=y
CONFIG_TARGET_${target}_${subtarget}=y
CONFIG_PACKAGE_capos-core=y
CONFIG_TARGET_ROOTFS_ARGOSFS=y
CONFIG_TARGET_KERNEL_PARTSIZE=64
CONFIG_TARGET_ROOTFS_PARTSIZE=512
CONFIG_TARGET_IMAGES_GZIP=y
CONFIG_BUILD_LOG=y
CONFIG_CCACHE=y
CONFIG_DOWNLOAD_FOLDER="dl"
CONFIG_GRUB_SERIAL=y
CONFIG_GRUB_BAUDRATE=115200
CONFIG_GRUB_TIMEOUT="1"
CONFIG

case "$target/$subtarget" in
x86/64)
cat >> .config <<'CONFIG'
CONFIG_GRUB_IMAGES=y
# CONFIG_GRUB_EFI_IMAGES is not set
# CONFIG_ISO_IMAGES is not set
# CONFIG_VDI_IMAGES is not set
# CONFIG_VMDK_IMAGES is not set
# CONFIG_VHDX_IMAGES is not set
CONFIG_TARGET_SERIAL="ttyS0"
CONFIG_GRUB_BOOTOPTS="panic=5"
CONFIG
;;
armsr/armv8)
cat >> .config <<'CONFIG'
CONFIG_GRUB_EFI_IMAGES=y
# CONFIG_VMDK_IMAGES is not set
CONFIG_TARGET_SERIAL="ttyAMA0"
CONFIG_GRUB_BOOTOPTS="panic=5"
CONFIG
;;
malta/le64)
cat >> .config <<'CONFIG'
CONFIG_TARGET_SERIAL="ttyS0"
CONFIG_KERNEL_CMDLINE="panic=5"
CONFIG
;;
esac
Loading
Loading