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 ANY pre-existing resultdir, even # one we just rm'd — somewhere in /var the path is recreated. # Use /tmp (act-job-container fresh tmpfs) + unique suffix. OUT="/tmp/lmc-out-$$" TMPD="/tmp/lmc-$$" rm -rf "$OUT" "$TMPD" mkdir -p "$TMPD" ln -sfn "$GITHUB_WORKSPACE" /work ls -ld "$OUT" 2>&1 || echo "[OK] $OUT does not exist (expected)" livemedia-creator \ --make-iso \ --no-virt \ --ks kickstart/install-ostreecontainer-installer.ks \ --resultdir "$OUT" \ --tmp "$TMPD" \ --volid "veilor-os-installer-${RELEASEVER}" \ --project "veilor-os" \ --releasever "$RELEASEVER" \ --logfile "$OUT/build.log" \ 2>&1 | tee /tmp/build.log mkdir -p build/out cp -a "$OUT"/. build/out/ cp -a /tmp/build.log build/out/build.log 2>/dev/null || true ls -lh build/out/ - 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