name: build-image # A full build takes ~25 min on the runner and executes the checked-out code # as root there, so it never runs on a plain push. Recipes are still linted # and validated on every push and PR by ci.yml. Images are built: # - on a release tag (v*.*.*): build, smoke test, publish as a release; # - on a PR into main carrying the `build-image` label, i.e. once a # maintainer has reviewed it (Gitea does not let authors approve their # own PRs, so approval cannot be the gate). Re-runs on every new push to # the PR while the label stays. Only for changes that affect images; # - weekly, to catch breakage from upstream Fedora package changes; # - by hand (workflow_dispatch) on any branch. on: push: tags: ["v*.*.*"] pull_request: branches: [main] types: [labeled, synchronize, reopened] paths: - "cook/**" - "build-image.sh" - "smoke-test.sh" - ".gitea/workflows/build-image.yaml" schedule: - cron: "0 3 * * 1" # Mondays 03:00 workflow_dispatch: # Builds raw disk images of the two default-tier editions (see # cook/recipes_manifest.yaml) with build-image.sh, i.e. # `livemedia-creator --no-virt --make-disk`. Other tiers (guest, experimental) # are built on demand with `./build-image.sh --tier `. # # The build job runs on the registered `fedora:host` runner (a Fedora VM, jobs # run as root), not in a container: --make-disk needs real loop devices and a # live systemd-udevd. The runner needs lorax-lmc-novirt, qemu-img, make, # python3-pip, pykickstart and xz installed, plus qemu-system-x86_64, # /dev/kvm and edk2-ovmf for smoke-test.sh. It must run with SELinux enabled: # anaconda inherits the runner's own selinux=0, if any (smoke-test.sh fails # such images). jobs: validate: # On PRs, only once the `build-image` label is set (see `on:` above), and # not again when some other label is added to an already-labeled PR. if: >- github.event_name != 'pull_request' || (contains(github.event.pull_request.labels.*.name, 'build-image') && (github.event.action != 'labeled' || github.event.label.name == 'build-image')) runs-on: fedora defaults: run: shell: bash container: image: git.phyllo.me/devops/fedora-runner-image:latest steps: - uses: https://git.phyllo.me/devops/checkout@v5 with: fetch-depth: 0 - name: Install Python deps run: pip install -r cook/requirements.txt - name: Generate, lint, and validate dishes run: | cd cook make all build-image: needs: validate runs-on: fedora strategy: fail-fast: false # NB: Gitea runs every matrix entry as its own task, so `max-parallel` # does not serialize them; build-image.sh takes a host-wide flock instead. matrix: include: - edition: phyllomeos root_size: 16384 - edition: phyllomeos-headless root_size: 8192 defaults: run: shell: bash env: # /tmp is a small tmpfs on the runner; livemedia-creator writes the whole # disk image under $TMPDIR TMPDIR: /var/tmp steps: - uses: https://git.phyllo.me/devops/checkout@v5 with: fetch-depth: 0 - name: Check runner prerequisites run: | missing=0 for tool in livemedia-creator qemu-img make pip xz sudo qemu-system-x86_64 debugfs; do command -v "$tool" >/dev/null || { echo "missing on runner: $tool"; missing=1; } done [ -e /dev/loop-control ] || { echo "missing on runner: /dev/loop-control"; missing=1; } [ -e /dev/kvm ] || { echo "missing on runner: /dev/kvm"; missing=1; } [ -e /usr/share/edk2/ovmf/OVMF_CODE.fd ] || { echo "missing on runner: edk2-ovmf"; missing=1; } [ "$missing" = 0 ] || exit 1 - name: Install Python deps run: pip install -r cook/requirements.txt - name: Build raw image run: | # Editions are named "_.cfg"; the trailing "_" keeps # "phyllomeos" from matching "phyllomeos-headless". (cd cook && make all) dish="$(basename "$(ls cook/dishes/${{ matrix.edition }}_*.cfg)" .cfg)" echo "DISH=$dish" >> "$GITHUB_ENV" ./build-image.sh --dish "$dish" --root-size ${{ matrix.root_size }} - name: Smoke test (static checks + boot) run: ./smoke-test.sh "build/$DISH.img" - name: Compress image run: xz -T0 "build/$DISH.img" - name: Upload image and kickstart as artifact if: "!startsWith(github.ref, 'refs/tags/')" uses: actions/upload-artifact@v3 with: name: ${{ matrix.edition }} path: | build/${{ env.DISH }}.img.xz cook/dishes/${{ env.DISH }}.cfg if-no-files-found: error retention-days: 7 - name: Publish image and kickstart as release if: startsWith(github.ref, 'refs/tags/') uses: https://git.phyllo.me/devops/action-gh-release@v2 with: files: | build/${{ env.DISH }}.img.xz cook/dishes/${{ env.DISH }}.cfg draft: false prerelease: false - name: Clean up build products if: always() run: rm -rf build /var/tmp/lmc-result.*