ci: run build directly in Fedora job container, drop addnab nest

forgejo-runner labels nullstone -> fedora:43 image. Switching
runs-on: ubuntu-24.04 -> nullstone makes the job container itself
the build environment, eliminating the docker-in-docker workspace
bind-mount problem (host path != act-container path).

Build now runs as root in fedora:43, installs livecd-tools directly
via dnf, and writes outputs to $GITHUB_WORKSPACE which is the natural
runner workdir on host. No nested docker, no userns juggling, no
explicit -v workspace bind needed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
claude-veilor-bot 2026-05-06 14:35:44 +01:00 committed by s8n-ru
parent 58c2f95986
commit c362530bc0

View file

@ -29,7 +29,10 @@ permissions:
jobs: jobs:
build: build:
name: Build live ISO name: Build live ISO
runs-on: ubuntu-24.04 # nullstone label resolves to a privileged Fedora 43 container per
# the runner's RUNNER_LABELS map. Build runs directly in this job
# container — no nested docker-run-action, no bind-mount juggling.
runs-on: nullstone
timeout-minutes: 90 timeout-minutes: 90
steps: steps:
@ -38,36 +41,10 @@ jobs:
# node24 which forgejo-runner v6.4.0 (node20) cannot exec. # node24 which forgejo-runner v6.4.0 (node20) cannot exec.
uses: actions/checkout@v4.1.7 uses: actions/checkout@v4.1.7
- name: Free up disk - name: Install build tooling (Fedora)
run: |
sudo rm -rf /opt/hostedtoolcache /usr/share/dotnet /usr/local/lib/android /usr/local/share/boost
sudo apt-get clean
df -h
- name: Run build inside Fedora 43 container
# v3 is composite/docker-based — no node runtime in the action
# itself. Safe under node20 forgejo-runner. TODO(infra): consider
# SHA pinning in a follow-up sweep.
uses: addnab/docker-run-action@v3
with:
# Pinned to amd64 digest from `skopeo inspect --raw` on 2026-05-06.
# Refresh by re-running skopeo against fedora:43 and picking the amd64 entry.
image: registry.fedoraproject.org/fedora:43@sha256:3207ed0f3765f81675f6ce2aa04f52a6cdbb2dddddc5ab9be6e0b0441ece136d
options: |
--privileged
--userns=host
-v ${{ github.workspace }}:/work
-v /dev:/dev
--tmpfs /tmp:rw,nosuid,nodev,exec,size=16G
run: | run: |
set -euxo pipefail set -euxo pipefail
# Update Fedora image to latest packages — guarantees pcre2 +
# libselinux + selinux-policy are matched (the local build's
# core problem). CI runners always start fresh, no version skew.
dnf -y upgrade --refresh dnf -y upgrade --refresh
# Install build tooling
dnf -y install \ dnf -y install \
lorax \ lorax \
livecd-tools \ livecd-tools \
@ -82,35 +59,26 @@ jobs:
shadow-utils \ shadow-utils \
syslinux \ syslinux \
tar \ tar \
curl curl \
sudo
# Vendor gum binary onto the ISO so the TTY1 installer can use - name: Vendor gum binary into overlay
# Charm.sh TUI primitives. gum is not packaged in Fedora repos, run: |
# so pull the upstream release tarball pinned by sha256. set -euxo pipefail
GUM_VERSION="0.17.0" GUM_VERSION="0.17.0"
GUM_URL="https://github.com/charmbracelet/gum/releases/download/v${GUM_VERSION}/gum_${GUM_VERSION}_Linux_x86_64.tar.gz" GUM_URL="https://github.com/charmbracelet/gum/releases/download/v${GUM_VERSION}/gum_${GUM_VERSION}_Linux_x86_64.tar.gz"
GUM_SHA256="69ee169bd6387331928864e94d47ed01ef649fbfe875baed1bbf27b5377a6fdb" GUM_SHA256="69ee169bd6387331928864e94d47ed01ef649fbfe875baed1bbf27b5377a6fdb"
mkdir -p /work/overlay/usr/local/bin mkdir -p overlay/usr/local/bin
curl -fsSL "$GUM_URL" -o /tmp/gum.tgz curl -fsSL "$GUM_URL" -o /tmp/gum.tgz
echo "$GUM_SHA256 /tmp/gum.tgz" | sha256sum -c - echo "$GUM_SHA256 /tmp/gum.tgz" | sha256sum -c -
tar -xzf /tmp/gum.tgz -C /tmp/ tar -xzf /tmp/gum.tgz -C /tmp/
install -m 0755 "/tmp/gum_${GUM_VERSION}_Linux_x86_64/gum" /work/overlay/usr/local/bin/gum install -m 0755 "/tmp/gum_${GUM_VERSION}_Linux_x86_64/gum" overlay/usr/local/bin/gum
/work/overlay/usr/local/bin/gum --version overlay/usr/local/bin/gum --version
echo "[OK] gum ${GUM_VERSION} vendored into overlay/usr/local/bin/" echo "[OK] gum ${GUM_VERSION} vendored into overlay/usr/local/bin/"
cd /work - name: Build ISO with livecd-creator
run: |
# Diagnostic: dump workspace state so a path/perm issue surfaces set -euxo pipefail
# before commands silently no-op.
echo "=== /work diagnostic ==="
id
pwd
mountpoint /work || true
ls -la /work | head -20
ls -la /work/kickstart 2>&1 | head -10
touch /work/kickstart/.write-test && echo "[OK] /work/kickstart writable" || echo "[ERR] /work/kickstart NOT writable"
rm -f /work/kickstart/.write-test 2>/dev/null
echo "=== end diagnostic ==="
# PATCH: livecd-creator bug — __get_efi_image_stanza writes # PATCH: livecd-creator bug — __get_efi_image_stanza writes
# `root=live:LABEL=...` instead of `live:CDLABEL=...` for dracut. # `root=live:LABEL=...` instead of `live:CDLABEL=...` for dracut.
@ -122,11 +90,8 @@ jobs:
echo "[OK] livecd-creator patched: LABEL= → CDLABEL= for EFI dracut stanza" echo "[OK] livecd-creator patched: LABEL= → CDLABEL= for EFI dracut stanza"
# CI uses ks-ci.ks (no local fix-repo line). Generated from main ks. # CI uses ks-ci.ks (no local fix-repo line). Generated from main ks.
# Also strip flags livecd-creator doesn't recognize. # Drop `updates` repo: previously 404'd on repodata zchunk during
# Drop `updates` repo: 3 consecutive builds 404'd on its # Fedora mid-push windows. Base 43 ships the selinux-policy fix.
# repodata zchunk file across all mirrors — Fedora infra issue
# mid-push window. Original reason for `updates` (selinux-policy
# 43.7 pcre2 fix) is no longer needed; base 43 ships fixed.
sed -e '/veilor-fix/d' \ sed -e '/veilor-fix/d' \
-e '/^shutdown$/d' \ -e '/^shutdown$/d' \
-e '/repo --name=updates/d' \ -e '/repo --name=updates/d' \
@ -135,11 +100,6 @@ jobs:
ksvalidator kickstart/veilor-os-ci.ks ksvalidator kickstart/veilor-os-ci.ks
mkdir -p build/out mkdir -p build/out
# livecd-creator (livecd-tools) — purpose-built for live ISOs.
# Handles EFI/BOOT + isohybrid + grafting that livemedia-creator
# --make-iso --no-virt does not. Produces UEFI+BIOS bootable ISO.
# --tmpdir /var/lmc to avoid GitHub Actions /tmp tmpfs constraints.
# /var on the runner is the host's ext4 (~80GB free post-disk-cleanup).
mkdir -p /var/lmc /var/lmc-cache mkdir -p /var/lmc /var/lmc-cache
livecd-creator \ livecd-creator \
--verbose \ --verbose \
@ -151,48 +111,37 @@ jobs:
--tmpdir /var/lmc \ --tmpdir /var/lmc \
--cache /var/lmc-cache 2>&1 | tee build/out/build.log --cache /var/lmc-cache 2>&1 | tee build/out/build.log
# Graft veilor source tree onto the ISO so the installer-generated - name: Graft veilor source tree onto ISO
# kickstart's `%post --nochroot` can find SRC at run: |
# /run/install/repo/veilor/{overlay,scripts,assets}/ when the user set -euxo pipefail
# promotes the live ISO into a real install. ISO_FILE=$(ls ./*.iso 2>/dev/null | head -1)
ISO_FILE=$(ls /work/*.iso 2>/dev/null | head -1)
[ -n "$ISO_FILE" ] || { echo "[ERR] no ISO produced by livecd-creator"; exit 1; } [ -n "$ISO_FILE" ] || { echo "[ERR] no ISO produced by livecd-creator"; exit 1; }
echo "[INFO] grafting /veilor/ onto $ISO_FILE" echo "[INFO] grafting /veilor/ onto $ISO_FILE"
# Extract original ISO's exact boot stanza so the rebuild matches
# livecd-creator's layout byte-for-byte. This is immune to upstream
# Fedora layout changes (e.g. images/ vs isolinux/ for efiboot.img,
# partition geometry flags, hybrid MBR/GPT options).
xorriso -indev "$ISO_FILE" -report_el_torito as_mkisofs 2>&1 | tee /tmp/iso-boot.txt || true xorriso -indev "$ISO_FILE" -report_el_torito as_mkisofs 2>&1 | tee /tmp/iso-boot.txt || true
ORIG_FLAGS=$(xorriso -indev "$ISO_FILE" -report_el_torito as_mkisofs 2>/dev/null | \ ORIG_FLAGS=$(xorriso -indev "$ISO_FILE" -report_el_torito as_mkisofs 2>/dev/null | \
grep -v '^xorriso :' | grep -E '^-' | tr '\n' ' ') grep -v '^xorriso :' | grep -E '^-' | tr '\n' ' ')
[ -n "$ORIG_FLAGS" ] || { echo "[ERR] could not extract boot stanza from $ISO_FILE"; exit 1; } [ -n "$ORIG_FLAGS" ] || { echo "[ERR] could not extract boot stanza from $ISO_FILE"; exit 1; }
echo "[INFO] re-pack flags from original ISO: $ORIG_FLAGS"
mkdir -p /tmp/iso-mod mkdir -p /tmp/iso-mod
xorriso -osirrox on -indev "$ISO_FILE" -extract / /tmp/iso-mod xorriso -osirrox on -indev "$ISO_FILE" -extract / /tmp/iso-mod
chmod -R u+w /tmp/iso-mod chmod -R u+w /tmp/iso-mod
mkdir -p /tmp/iso-mod/veilor mkdir -p /tmp/iso-mod/veilor
cp -a /work/overlay /work/scripts /work/assets /tmp/iso-mod/veilor/ cp -a overlay scripts assets /tmp/iso-mod/veilor/
# Replay the exact stanza captured above. eval is needed because
# ORIG_FLAGS contains multiple flag/value pairs that must word-split.
eval xorriso -as mkisofs \ eval xorriso -as mkisofs \
-volid "veilor-os-43" \ -volid "veilor-os-43" \
$ORIG_FLAGS \ $ORIG_FLAGS \
-o "${ISO_FILE}.tmp" /tmp/iso-mod -o "${ISO_FILE}.tmp" /tmp/iso-mod
mv "${ISO_FILE}.tmp" "$ISO_FILE" mv "${ISO_FILE}.tmp" "$ISO_FILE"
rm -rf /tmp/iso-mod rm -rf /tmp/iso-mod
echo "[OK] /veilor/ grafted onto $ISO_FILE"
# Move output ISO to expected dir mv "$ISO_FILE" build/out/
mv ./veilor-os-43.iso build/out/ 2>/dev/null || mv ./*.iso build/out/ 2>/dev/null || true
# Rename + checksum
ISO_NAME="veilor-os-${{ github.event.inputs.releasever || '43' }}-$(date +%Y%m%d-%H%M%S).iso" ISO_NAME="veilor-os-${{ github.event.inputs.releasever || '43' }}-$(date +%Y%m%d-%H%M%S).iso"
cd build/out cd build/out
for f in *.iso; do for f in *.iso; do
[[ -f $f && $f != $ISO_NAME ]] && mv "$f" "$ISO_NAME" [[ -f $f && $f != "$ISO_NAME" ]] && mv "$f" "$ISO_NAME"
done done
sha256sum "$ISO_NAME" > "$ISO_NAME.sha256" sha256sum "$ISO_NAME" > "$ISO_NAME.sha256"
ls -lh "$ISO_NAME" ls -lh "$ISO_NAME"
@ -205,9 +154,6 @@ jobs:
- name: Split ISO into 2GiB chunks - name: Split ISO into 2GiB chunks
if: success() && github.ref == 'refs/heads/main' if: success() && github.ref == 'refs/heads/main'
run: | run: |
# ISO + sidecars created by Fedora container as root. Reclaim
# ownership so this step (running as runner user) can write.
sudo chown -R "$(id -u):$(id -g)" build/out
cd build/out cd build/out
ISO=$(ls *.iso | head -1) ISO=$(ls *.iso | head -1)
[ -n "$ISO" ] || { echo "[ERR] no ISO"; exit 1; } [ -n "$ISO" ] || { echo "[ERR] no ISO"; exit 1; }