version: '3' vars: IMAGE: quine-linux LIVE_IMAGE: quine-linux-live # What the Containerfile builds FROM: our Aurora fork # (quine-global-labs/aurora), built and published by that repo's workflow. # Override with a local build of the fork (BASE_IMAGE=localhost/aurora:stable, # see README) or stock upstream (BASE_IMAGE=ghcr.io/ublue-os/aurora:stable). BASE_IMAGE: forge.quinefoundation.com/quine-global-labs/aurora:stable # What installed systems follow for updates: Aurora's uupd.timer stages # whatever is newest there daily, for the next boot. Our own name, so it # outlives where the images are stored: today a pull-only proxy to the # forge's registry (petersweb-infra nixos/edge.nix), where iso.yml pushes. UPDATE_IMAGE: registry.quineglobal.com/quine-linux:latest OUTPUT_DIR: '{{.ROOT_DIR}}/output' # Root is needed for the container builds and bootc; skip {{.SUDO}} when already # root (e.g. on a CI runner, which may not have {{.SUDO}} at all). SUDO: sh: '[ "$(id -u)" = 0 ] || echo sudo' # Any docker-CLI-compatible runtime works for plain builds. Prefers podman, # falls back to docker; override with CONTAINER_RUNTIME=... (env or task var). CONTAINER_RUNTIME: sh: echo "${CONTAINER_RUNTIME:-$(command -v podman >/dev/null 2>&1 && echo podman || echo docker)}" # bootc-image-builder now lives in github.com/osbuild/image-builder and is # published here; quay.io/centos-bootc/bootc-image-builder is frozen. BIB_IMAGE: ghcr.io/osbuild/bootc-image-builder:latest # Aurora is amd64-only (and the kmod stage hardcodes x86_64), so pin it # explicitly; otherwise an arm64 host (e.g. Apple Silicon) builds for arm64. PLATFORM: linux/amd64 TARGET_ARCH: amd64 SKOPEO_IMAGE: quay.io/skopeo/stable:latest # Titanoboa's ISO step runs in this (live/titanoboa-build-iso.sh). FEDORA_IMAGE: quay.io/fedora/fedora:latest # bootc-image-builder reads images from a containers-storage mounted at # /var/lib/containers/storage. Under podman that's root's real store; docker # has no such store, so images get copied (via skopeo) into this volume. DOCKER_STORAGE_VOLUME: quine-containers-storage STORAGE: '{{if eq .CONTAINER_RUNTIME "podman"}}/var/lib/containers/storage{{else}}{{.DOCKER_STORAGE_VOLUME}}{{end}}' PULL_FLAG: '{{if eq .CONTAINER_RUNTIME "podman"}}--pull=newer{{else}}--pull=always{{end}}' tasks: default: desc: List available tasks cmds: - task --list silent: true build-image: desc: >- Build the quine-linux bootc container image on top of BASE_IMAGE (our Aurora build from the forge's registry by default), as root (under podman this lands in root's containers-storage, which bootc and bootc-image-builder read; under docker, the ISO tasks copy it over). cmds: - >- {{.SUDO}} {{.CONTAINER_RUNTIME}} build --platform {{.PLATFORM}} --build-arg BASE_IMAGE={{.BASE_IMAGE}} -t {{.IMAGE}} -f Containerfile . sources: - Containerfile - overlay/**/* - patches/**/* build-disk-image: desc: >- Build a ready-installed disk image (qcow2) of the local quine-linux image, via bootc-image-builder: boot it in a VM and plasma-setup asks for the first user. Output lands in {{.OUTPUT_DIR}}/qcow2/disk.qcow2. preconditions: - sh: | case "$(uname -m)" in x86_64|amd64) a=amd64 ;; aarch64|arm64) a=arm64 ;; *) a="$(uname -m)" ;; esac [ "$a" = "{{.TARGET_ARCH}}" ] msg: >- Disk image builds need a host of architecture {{.TARGET_ARCH}}. This one is {{ARCH}}, and bootc-image-builder's cross-arch mode fails partway (it runs the image for inspection, which needs emulation inside its own container). cmds: # Not a dep: deps run before preconditions, and this should fail fast. - task: build-image - task: export-to-storage vars: { IMAGES: "{{.IMAGE}}" } # An install follows the image name its disk was built from for # updates, so build it from UPDATE_IMAGE's name, not localhost/: # same image, under the name installs should pull from. # (bootc-image-builder's --target-imgref did this; image-builder # dropped it.) - >- {{if eq .CONTAINER_RUNTIME "podman"}}{{.SUDO}} podman tag localhost/{{.IMAGE}} {{.UPDATE_IMAGE}}{{else}}{{.SUDO}} {{.CONTAINER_RUNTIME}} run --rm --privileged -v {{.STORAGE}}:/var/lib/containers/storage {{.SKOPEO_IMAGE}} copy containers-storage:localhost/{{.IMAGE}}:latest containers-storage:{{.UPDATE_IMAGE}}{{end}} - mkdir -p {{.OUTPUT_DIR}} # Root on btrfs, as Aurora installs it: disk/config.toml. - >- {{.SUDO}} {{.CONTAINER_RUNTIME}} run --rm --privileged {{.PULL_FLAG}} --security-opt label=type:unconfined_t -v {{.OUTPUT_DIR}}:/output -v {{.ROOT_DIR}}/disk/config.toml:/config.toml:ro -v {{.STORAGE}}:/var/lib/containers/storage {{.BIB_IMAGE}} --type qcow2 {{.UPDATE_IMAGE}} generates: - "{{.OUTPUT_DIR}}/qcow2/disk.qcow2" build-live-image: desc: >- Build the live ISO's root filesystem (live/Containerfile): quine-linux plus the live session and Anaconda WebUI, with PAYLOAD_IMAGE (what the installer installs) pulled into it. Podman only. vars: PAYLOAD_IMAGE: '{{.PAYLOAD_IMAGE | default .UPDATE_IMAGE}}' preconditions: - sh: '[ "{{.CONTAINER_RUNTIME}}" = podman ]' msg: The live ISO tasks need podman (they mount the image into Titanoboa's container). cmds: - >- {{.SUDO}} podman build --platform {{.PLATFORM}} --cap-add sys_admin --security-opt label=disable --build-arg BASE_IMAGE=localhost/{{.IMAGE}} --build-arg PAYLOAD_IMAGE={{.PAYLOAD_IMAGE}} -t {{.LIVE_IMAGE}} -f live/Containerfile live/ build-live-iso: desc: >- Build the live ISO: boots into a Quine Linux session, with an installer. Titanoboa's script (live/titanoboa-build-iso.sh) packs the live image into it. Output lands in {{.OUTPUT_DIR}}/live/Quine-Linux-Live.iso. PAYLOAD_IMAGE: see build-live-image. preconditions: - sh: '[ "{{.CONTAINER_RUNTIME}}" = podman ]' msg: The live ISO tasks need podman (they mount the image into Titanoboa's container). cmds: - task: build-image - task: build-live-image - mkdir -p {{.OUTPUT_DIR}}/live - >- {{.SUDO}} podman run --rm {{.PULL_FLAG}} --cap-add sys_admin --security-opt label=disable -v {{.ROOT_DIR}}/live/titanoboa-build-iso.sh:/src/build_iso.sh:ro --mount type=image,source=localhost/{{.LIVE_IMAGE}},dst=/rootfs -v {{.OUTPUT_DIR}}/live:/output {{.FEDORA_IMAGE}} /src/build_iso.sh generates: - "{{.OUTPUT_DIR}}/live/Quine-Linux-Live.iso" export-to-storage: internal: true desc: >- Under docker, copy IMAGES (space-separated local tags) from the docker daemon into the containers-storage volume bootc-image-builder reads. No-op under podman, which builds straight into containers-storage. status: - '[ "{{.CONTAINER_RUNTIME}}" = podman ]' cmds: - for: { var: IMAGES } cmd: >- {{.SUDO}} {{.CONTAINER_RUNTIME}} run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v {{.STORAGE}}:/var/lib/containers/storage {{.SKOPEO_IMAGE}} copy docker-daemon:{{.ITEM}}:latest containers-storage:localhost/{{.ITEM}}:latest status: desc: Show current bootc deployment status (what's booted, what's staged/rollback). cmds: - bootc status test:stage: desc: >- Build the local image and stage it as the next-boot target on THIS machine (bootc switch, no reboot yet). This is the fast way to test a change -- especially the CS8409 mic-fix kernel module -- against the real running system without building an ISO or reinstalling anything. Reboot separately when ready: `task test:boot`, or `sudo systemctl reboot`. deps: [build-image] cmds: # bootc reads the host's own containers-storage, i.e. podman's (which # every bootc host ships), so a docker-built image is loaded into it. - cmd: '{{.SUDO}} docker save {{.IMAGE}} | {{.SUDO}} podman load' platforms: [linux] if: '[ "{{.CONTAINER_RUNTIME}}" != podman ]' - '{{.SUDO}} bootc switch --transport containers-storage localhost/{{.IMAGE}}' - bootc status --booted - echo "Staged localhost/{{.IMAGE}} for next boot. Run task test:boot when ready to reboot into it." test:boot: desc: Stage the local image (if not already) and reboot into it now. prompt: This will reboot this machine into the locally-built {{.IMAGE}} image. Continue? deps: [test:stage] cmds: - '{{.SUDO}} systemctl reboot' revert: desc: >- Roll back to the previously-booted deployment and reboot into it -- undoes a `test:boot` switch (or any other deployment change) if something's wrong. Safe even if nothing was ever switched: bootc/ rpm-ostree always keep the prior deployment around for exactly this. prompt: This will reboot this machine back into the previous deployment. Continue? cmds: - '{{.SUDO}} bootc rollback' - '{{.SUDO}} systemctl reboot'