Repository navigation
Building with GitHub Actions
GitHub Actions can build your distro on GitHub's machines: it builds the ISO, boots it in QEMU five ways, and checks the result against your spec. You need no Linux, and it's free in a public repository. There are two ways in, and both run the same reusable workflow, .github/workflows/build.yml in the linuxlive repository.
| Route | For | You need |
|---|---|---|
| The template, Eric-Ness/linuxlive-distro | Making a distro. Recommended. | A browser |
| A fork of Eric-Ness/linuxlive | Changing linuxlive itself (the catalog, the compiler, the boot tests) and testing your change | git and Python on your computer |
Getting Started walks through the template route once with an example. This page is the reference for both.
A repository made from the template holds your spec, your art, and this workflow:
name: build
on:
push:
branches: [main]
paths-ignore: [README.md]
workflow_dispatch:
permissions:
contents: read
packages: write
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
uses: Eric-Ness/linuxlive/.github/workflows/build.yml@v0.4.2
with:
spec: linuxlive.yaml
publish-image: trueEvery push to main builds, except one that only changes README.md. Run workflow on the Actions tab builds by hand. A newer push cancels a build still running.
@v0.4.2 picks the release of linuxlive to build with. It fixes both the workflow and the pipeline it runs, so a build stays reproducible until you change it. To move to a newer release, change the tag in .github/workflows/build.yml and commit. The releases page lists what changed.
Set these under with:. All of them are optional.
| Input | Default | What it does |
|---|---|---|
spec |
linuxlive.yaml |
Path of the spec in your repository. Image paths in it are relative to the spec. |
name |
the spec's id
|
Base name of the ISO and the artifacts: <name>.iso, iso-<name>, results-<name>. Letters, digits, ., - and _. |
keep-iso |
true |
Upload the ISO as an artifact. Set it to false to keep only the test results. |
iso-retention-days |
7 |
Days GitHub keeps the ISO artifact. |
publish-image |
false |
Fedora bases: push the system image to your repository's packages on ghcr.io (needs packages: write), tagged :latest once the build passes. The Fedora installer installs from it and installed systems update from it, so without it a Fedora-based ISO cannot install. Ubuntu bases ignore it. |
linuxlive-repository |
Eric-Ness/linuxlive |
Where the pipeline comes from. Change it only to test a fork of linuxlive. |
linuxlive-ref |
the release in the @ tag |
Pipeline version: a tag, branch or commit of linuxlive-repository. |
Give each spec its own file and build them side by side with a matrix. Each one gets its own artifacts, named after its id:
jobs:
build:
strategy:
fail-fast: false
matrix:
spec: [kiosk.yaml, classroom.yaml]
uses: Eric-Ness/linuxlive/.github/workflows/build.yml@v0.4.2
with:
spec: ${{ matrix.spec }}They work, with two limits. Builds use your account's included Actions minutes (GitHub Free includes 2,000 a month), and a build takes about 20 to 40 minutes. GitHub Free also includes only 500 MB of artifact storage for private repositories, which is too small for an ISO. Keep your distro's repository public, or set keep-iso: false and use the runs only as tests.
The reusable workflow runs one job, build, on an Ubuntu 24.04 runner with KVM:
-
Check the spec:
python -m linuxlive validate. A bad spec stops here with every problem listed. -
Compile spec:
python -m linuxlive compilewrites the build context. -
Build image:
podman buildinstalls the base system, desktop and kernel. -
Assemble ISO:
assemble-iso.shinstalls the Flatpak apps and writes the hybrid ISO. -
Inspect ISO:
python -m linuxlive inspect-isorecords its boot structures. -
Boot tests:
boottest.pyboots the ISO in QEMU in five modes. The first mode waits for the desktop and takes screenshots. If the first boot never reaches the running system, the other four are skipped. -
Verify:
python -m linuxlive verify-resultschecks the results against the spec. The ISO must have both boot catalogs, the USB partition tables and the boot files. Every boot must reach the running system with the right firmware, Secure Boot on only in the Secure Boot mode, and your distro's name. The desktop must start with the right desktop shell, name, id, version and boot splash, your Flatpak apps must be installed, and your wallpaper's colour must be on screen. No system service may fail, the live session must start no update notifiers, and on Ubuntu every checksum in the ISO'smd5sum.txtmust match. - Summary: the run's summary page says whether it passed and lists every check.
| Mode | Firmware | Started from |
|---|---|---|
uefi-usb |
UEFI | USB stick (this boot also checks the desktop) |
uefi-sb-cd |
UEFI with Secure Boot on | DVD |
uefi-cd |
UEFI | DVD |
bios-cd |
BIOS | DVD |
bios-usb |
BIOS | USB stick |
The Verify step checks that your wallpaper really shows on the booted desktop, by finding its main colour in screenshots. For that the wallpaper must be a PNG (8-bit, non-interlaced) with one dominant colour; see Writing a Spec: Images. A JPEG builds and boots, but fails the Verify step.
Every build uploads these, whether it passed or not:
| Artifact | Kept | Contents |
|---|---|---|
iso-<name> |
7 days by default (iso-retention-days) |
the ISO, its SHA-256 checksum and its package list (<name>.iso.packages: each package, its version and its source package) |
results-<name> |
14 days |
meta.json (commits of your repository and of linuxlive, and the base), iso.json (the inspect report), and for each boot mode modes/<mode>/: result.json, the serial console log and, for uefi-usb, screenshots of the desktop |
Artifacts can only be downloaded while signed in to GitHub. Save the ISO somewhere of your own to keep it longer. GitHub releases are no help here: a release file must be under 2 GiB, and ISOs are 2.7 to 4.5 GiB.
The screenshots in results-<name>/modes/uefi-usb/ are the quickest way to see your distro without booting it.
You can re-run the verifier on your own computer, on any OS, against a downloaded results artifact. It needs a checkout of linuxlive with its requirements installed (see Building Locally step 2). Unzip the artifact and point --results at the folder:
python -m linuxlive verify-results --spec ../my-distro/linuxlive.yaml --results results-my-distroIt prints a PASS or FAIL line for each check (about 55 of them) and ends with VERIFY OK when all pass. Add --check iso,boot to skip the desktop checks, or --expect-commit <sha> to confirm the results come from a particular commit.
Use this when you want to change linuxlive itself and see your change build and boot. The repository's own CI, .github/workflows/spike.yml, runs the tests and then builds every example through the reusable workflow, with the pipeline at the commit being tested.
- Fork Eric-Ness/linuxlive. Keep the fork public for free runners.
- Open the fork's Actions tab and click I understand my workflows, go ahead and enable them. Forks start with workflows turned off.
- Clone the fork and install the requirements:
git clone https://github.com/YOUR-NAME/linuxlive.git
cd linuxlive
python -m venv .venv
. .venv/bin/activate # Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install -r requirements-dev.txt
python -m pytestAn example in CI is four things:
| What | Where |
|---|---|
| The spec | examples/<name>.yaml |
| Its art | anywhere under examples/, by convention examples/assets/<name>/
|
| The compiler's reference output |
tests/golden/<name>/, made by the command below |
| A build entry | its name in the matrix in .github/workflows/spike.yml
|
The reference output. The unit job runs the test suite, and one test compares the compiler's output for every examples/*.yaml with a saved copy in tests/golden/. A new or changed example, or a change to the compiler, fails that test until you save the new output:
LINUXLIVE_UPDATE_GOLDEN=1 python -m pytest tests/test_compiler.py
python -m pytestIn Windows PowerShell:
$env:LINUXLIVE_UPDATE_GOLDEN = "1"; python -m pytest tests/test_compiler.py; Remove-Item Env:LINUXLIVE_UPDATE_GOLDEN
python -m pytestRead the diff, and commit tests/golden/ with your change. If unit fails, nothing is built.
The build entry. Build jobs come from the example list in the matrix, one name per spec in examples/:
strategy:
fail-fast: false
matrix:
example: [testos-ubuntu, testos-fedora, lawndarts-ubuntu, lawndarts-fedora, mydistro]Every spec in examples/ is compiled and tested by unit, but only the names listed here are built and booted.
A push keeps only the test results. To get ISOs, choose Actions → spike → Run workflow, tick Upload the ISOs as artifacts (kept for one day) (the keep_iso input), and run it. A push to the same branch while it runs cancels it. spike also uploads unit-summary: test counts and the list of compiled examples.
On your fork's main page, click Sync fork. If GitHub reports a conflict, it's almost always the matrix in spike.yml: keep the project's version of the file and add your names again. Then regenerate the reference output, since compiler changes alter it, and push.
| What you see | What to do |
|---|---|
| "Check the spec" fails | The message names each problem; see Writing a Spec: Common errors. |
unit fails in test_examples_match_golden_output[<name>] (fork) |
Regenerate the reference output and commit tests/golden/. |
unit fails in another test (fork) |
Run python -m pytest on your computer to see why. |
| Warning "No /dev/kvm on this runner" | QEMU falls back to emulation, which is very slow. Re-run later; GitHub-hosted Linux runners normally have KVM. |
| "The first boot never reached userspace" | The ISO didn't boot. Open results-<name>/modes/uefi-usb/ and read the serial log for the last thing that happened. |
| "Verify" fails on the wallpaper | Use a PNG with a stronger single colour. |
| "Verify" fails on something else | The message says which check failed. If it's not about your art, open an issue and link the run. |
| The run was cancelled | A newer push or run on the same branch replaced it. |
| No "Run workflow" button | The workflow file must be on the default branch, and Actions must be enabled. |
Please keep your own distro in your own repository. examples/ in the main repository holds the project's test distros. Fixes, new catalog apps and new features are welcome as pull requests; see CONTRIBUTING.md.
Make a distro
Build it
Use it
Project