veilor-os/.github/workflows/build-installer-iso.yml
claude-veilor-bot 705f99d8dc
Some checks failed
Build veilor-os OCI (BlueBuild) / Build + push OCI (push) Failing after 2h55m5s
Build veilor-os Installer ISO / Build installer ISO (push) Failing after 41s
fix(v0.7): bluebuild type:copy + livemedia-creator clean resultdir
bluebuild (159): 'type: files' module fails 'chmod: Operation not
permitted' inside its own bind-mounted /tmp/modules/files/files.sh
under buildah + privileged-podman in our runner. Switch all four
`type: files` modules to `type: copy` (low-level COPY, no chmod, no
helper script needed).

installer-iso (160): livemedia-creator refused build/out which
checkout had already created (Forgejo runner reuses workspace dir
between runs). rm -rf build/out before invocation; mkdir not needed,
livemedia-creator creates the dir itself.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 01:55:08 +01:00

167 lines
6.3 KiB
YAML

name: Build veilor-os Installer ISO
# v0.7+ — produces a small Anaconda installer ISO that consumes
# kickstart/install-ostreecontainer-installer.ks. The ISO boots
# Anaconda, asks for LUKS pw + admin pw interactively, then
# `ostreecontainer` populates / from the v0.7 OCI image at
# ghcr.io/veilor-org/veilor-os:43.
on:
push:
branches: [v0.7-bluebuild-spike]
paths:
- 'kickstart/install-ostreecontainer.ks'
- 'kickstart/install-ostreecontainer-installer.ks'
- 'bluebuild/recipe.yml'
- '.github/workflows/build-installer-iso.yml'
workflow_dispatch:
inputs:
releasever:
description: 'Fedora release version'
required: false
default: '43'
permissions:
contents: write # needed to create+update installer-latest release
jobs:
build:
name: Build installer ISO
runs-on: nullstone
timeout-minutes: 120
env:
RELEASEVER: ${{ github.event.inputs.releasever || '43' }}
steps:
- name: Checkout
uses: actions/checkout@v4.1.7
- name: Install build tooling (Fedora)
run: |
set -euxo pipefail
dnf -y upgrade --refresh
dnf -y install --skip-unavailable \
lorax \
pykickstart \
anaconda-tui \
syslinux \
xorriso \
grub2-efi-x64 \
grub2-efi-x64-modules \
grub2-pc \
grub2-pc-modules \
shim-x64 \
efibootmgr
- name: Validate installer kickstart
run: |
set -euxo pipefail
ksvalidator kickstart/install-ostreecontainer-installer.ks
- name: Build installer ISO with livemedia-creator
run: |
set -euxo pipefail
# livemedia-creator refuses an existing non-empty resultdir.
rm -rf build/out
mkdir -p /var/lmc
ln -sfn "$GITHUB_WORKSPACE" /work
# livemedia-creator does NOT support --title (that's livecd-creator).
# --volid replaces it for the ISO volume label.
livemedia-creator \
--make-iso \
--no-virt \
--ks kickstart/install-ostreecontainer-installer.ks \
--resultdir build/out \
--tmp /var/lmc \
--volid "veilor-os-installer-${RELEASEVER}" \
--project "veilor-os" \
--releasever "$RELEASEVER" \
--logfile build/out/build.log \
2>&1 | tee -a build/out/build.log
- name: Rename ISO + sha256
run: |
set -euxo pipefail
ISO_FILE=$(ls build/out/*.iso 2>/dev/null | head -1)
[ -n "$ISO_FILE" ] || { echo "[ERR] no ISO produced"; exit 1; }
ISO_NAME="veilor-os-installer-${RELEASEVER}-$(date +%Y%m%d-%H%M%S).iso"
mv "$ISO_FILE" "build/out/$ISO_NAME"
cd build/out
sha256sum "$ISO_NAME" > "$ISO_NAME.sha256"
ls -lh "$ISO_NAME"
- name: Split ISO into 1900M chunks
if: success() && github.ref == 'refs/heads/v0.7-bluebuild-spike'
run: |
set -euo pipefail
cd build/out
ISO=$(ls *.iso | head -1)
[ -n "$ISO" ] || { echo "[ERR] no ISO"; exit 1; }
split -b 1900M -d --suffix-length=2 "$ISO" "${ISO}.part-"
rm -f "$ISO"
sha256sum *.part-* > "${ISO}.parts.sha256"
ls "${ISO}".part-*
- name: Publish to installer-latest rolling prerelease (Forgejo)
if: success() && github.ref == 'refs/heads/v0.7-bluebuild-spike' && github.server_url != 'https://github.com'
env:
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FORGEJO_API: ${{ github.server_url }}/api/v1
REPO: ${{ github.repository }}
GIT_SHA: ${{ github.sha }}
run: |
set -euo pipefail
TAG="installer-latest"
REL_JSON=$(curl -fsSL -H "Authorization: token ${FORGEJO_TOKEN}" \
"${FORGEJO_API}/repos/${REPO}/releases/tags/${TAG}" 2>/dev/null || echo "")
if [ -n "$REL_JSON" ]; then
REL_ID=$(echo "$REL_JSON" | grep -oE '"id":\s*[0-9]+' | head -1 | grep -oE '[0-9]+')
if [ -n "$REL_ID" ]; then
curl -fsSL -X DELETE -H "Authorization: token ${FORGEJO_TOKEN}" \
"${FORGEJO_API}/repos/${REPO}/releases/${REL_ID}" || true
curl -fsSL -X DELETE -H "Authorization: token ${FORGEJO_TOKEN}" \
"${FORGEJO_API}/repos/${REPO}/git/refs/tags/${TAG}" || true
fi
fi
BODY="Rolling auto-build from v0.7-bluebuild-spike. Latest commit: ${GIT_SHA}.
Installer ISO — boots Anaconda, prompts for LUKS pw + admin pw,
then ostreecontainer-pulls / from ghcr.io/veilor-org/veilor-os:43.
Reassemble:
cat veilor-os-installer-*.iso.part-* > veilor-os-installer.iso
sha256sum -c veilor-os-installer-*.iso.parts.sha256
Not a stable release — for testing only."
PAYLOAD=$(BODY="$BODY" TAG="$TAG" python3 -c "
import json,os
print(json.dumps({
'tag_name': os.environ['TAG'],
'target_commitish': 'v0.7-bluebuild-spike',
'name': 'installer-latest (auto)',
'body': os.environ['BODY'],
'prerelease': True,
'draft': False,
}))")
REL_ID=$(curl -fsSL -X POST -H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
"${FORGEJO_API}/repos/${REPO}/releases" | \
grep -oE '"id":\s*[0-9]+' | head -1 | grep -oE '[0-9]+')
[ -n "$REL_ID" ] || { echo "[ERR] failed to create release"; exit 1; }
cd build/out
for f in *.iso.part-* *.sha256; do
[ -f "$f" ] || continue
curl -fsSL -X POST -H "Authorization: token ${FORGEJO_TOKEN}" \
-F "attachment=@${f}" \
"${FORGEJO_API}/repos/${REPO}/releases/${REL_ID}/assets?name=${f}"
done
- name: Print build log on failure
if: failure()
run: |
echo "─── build/out/build.log ───"
tail -200 build/out/build.log 2>/dev/null || echo "(no build.log)"
find build/out -name 'program.log' -exec tail -100 {} \; 2>/dev/null || true
find /var/lmc -name '*.log' -exec tail -50 {} \; 2>/dev/null || true