Skip to content

sneak preview: uv, Click, Rich, tui; flavors #149

sneak preview: uv, Click, Rich, tui; flavors

sneak preview: uv, Click, Rich, tui; flavors #149

Workflow file for this run

name: For each commit and PR
on:
push:
branches:
- "main"
pull_request:
permissions:
contents: read
packages: write
env:
DEFAULT_FLAVOR_ID: "trixie-slim"
FORCE_COLOR: "1"
jobs:
# -------------------------------------------------------------------
# Lint — ruff (lint + format) and pyright (type checking)
# -------------------------------------------------------------------
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install lint tools
run: make lint-install
- name: Lint
run: make lint
# -------------------------------------------------------------------
# Download tools (containerd, runc, nerdctl, CNI plugins)
# -------------------------------------------------------------------
download-tools:
needs: [ lint ]
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix:
arch: [ amd64, arm64 ]
env:
ARCH: ${{ matrix.arch }}
MKOSI_MODE: skip
TOOLS_MODE: native
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Restore tools cache
id: tools-cache
uses: actions/cache/restore@v5
with:
path: |
mkosi.output/tools/${{ matrix.arch }}/usr/local/bin
mkosi.output/tools/${{ matrix.arch }}/opt/cni
key: tools-${{ matrix.arch }}-${{ hashFiles('captain/tools.py') }}
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Download tools
env:
TOOLS_MODE: native
run: uv run captain tools
- name: Save tools cache
if: github.ref == 'refs/heads/main' && steps.tools-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: |
mkosi.output/tools/${{ matrix.arch }}/usr/local/bin
mkosi.output/tools/${{ matrix.arch }}/opt/cni
key: tools-${{ matrix.arch }}-${{ hashFiles('captain/tools.py') }}
- name: Upload tools artifacts
uses: actions/upload-artifact@v6
with:
name: tools-${{ matrix.arch }}
path: |
mkosi.output/tools/${{ matrix.arch }}/usr/local/bin
mkosi.output/tools/${{ matrix.arch }}/opt/cni
retention-days: 1
# -------------------------------------------------------------------
# Build Docker builder image, per-arch; pushes to ghcr.io.
# -------------------------------------------------------------------
build-dockerfile:
needs: [ lint ]
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix: { arch: [ amd64, arm64 ] }
env:
ARCH: ${{ matrix.arch }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Dockerfile
run: uv run captain builder
# only if a PR, since we don't want to push images for PRs from forks
if: github.event_name == 'pull_request'
- name: Build Dockerfile and push
run: uv run captain builder --push
# only if not a PR, since we don't want to push images for PRs from forks (no perms to push)
if: github.event_name != 'pull_request'
# -------------------------------------------------------------------
# Download tools (containerd, runc, nerdctl, CNI plugins)
# -------------------------------------------------------------------
build-captainos-kernel:
needs: [ build-dockerfile ]
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix:
arch: [ amd64, arm64 ]
env:
ARCH: ${{ matrix.arch }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Restore kernel cache
id: kernel-cache
uses: actions/cache/restore@v5
with:
path: |
mkosi.output/kernel/${{ matrix.arch }}
key: kernel-${{ matrix.arch }}-${{ hashFiles('**/*.py', 'kernel.configs/*', 'Dockerfile', 'pyproject.toml') }}
# any "previous" cache can also be useful; we'll just churn cache misses more often, but that's better than a complete cache miss and rebuild every time
restore-keys: |
kernel-${{ matrix.arch }}
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Build kernel
run: uv run captain --verbose kernel
- name: Save kernel cache
if: github.ref == 'refs/heads/main' && steps.tools-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: |
mkosi.output/kernel/${{ matrix.arch }}
key: kernel-${{ matrix.arch }}-${{ hashFiles('**/*.py', 'kernel.configs/*', 'Dockerfile', 'pyproject.toml') }}
- name: Upload kernel artifacts
uses: actions/upload-artifact@v6
with:
name: kernel-${{ matrix.arch }}
path: |
mkosi.output/kernel/${{ matrix.arch }}
retention-days: 1
build-captainos-with-kernel: # only for flavors that require the custom CaptainOS kernel; otherwise, just build-captainos
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
needs: [ download-tools, build-dockerfile, build-captainos-kernel ]
strategy:
fail-fast: false
matrix:
include:
- { arch: amd64, output_arch: x86_64, captainos_kernel: true, iso: true, FLAVOR_ID: "trixie-slim" }
- { arch: arm64, output_arch: aarch64, captainos_kernel: true, iso: true, FLAVOR_ID: "trixie-slim" }
env: &build_env
ARCH: ${{ matrix.arch }}
MKOSI_MODE: docker
ISO_MODE: docker
FLAVOR_ID: ${{ matrix.FLAVOR_ID }}
steps: &build_steps
- name: Checkout code
uses: actions/checkout@v6
- name: Download tools artifacts
uses: actions/download-artifact@v8
with:
name: tools-${{ matrix.arch }}
path: mkosi.output/tools/${{ matrix.arch }}
- name: Download kernel artifacts == ${{ matrix.captainos_kernel }}
uses: actions/download-artifact@v8
if: ${{ matrix.captainos_kernel }} # only if matrix entry had captainos_kernel: true
with:
name: kernel-${{ matrix.arch }}
path: mkosi.output/kernel/${{ matrix.arch }}
- name: Restore tool binary permissions
run: |
# GitHub Actions artifact upload/download strips execute permissions.
# Restore +x on all tool binaries so they work inside the initramfs.
chmod +x mkosi.output/tools/${{ matrix.arch }}/usr/local/bin/*
chmod +x mkosi.output/tools/${{ matrix.arch }}/opt/cni/bin/*
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Build initramfs
run: uv run captain build # full build, incl initramfs and iso when appropriate
- name: Upload initramfs artifacts
uses: actions/upload-artifact@v6
with:
name: initramfs-${{ matrix.FLAVOR_ID }}-${{ matrix.arch }}
# The full 'out/' directory contents, but not any .iso files (if any) since those are uploaded later
path: |
out/
!out/**/*.iso
retention-days: 1
# do not upload any .iso files (exclude)
# -------------------------------------------------------------------
# UEFI-bootable ISO - only for certain flavors (eg trixie-full)
# -------------------------------------------------------------------
- name: Upload ISO artifact
if: ${{ matrix.iso }} # only if matrix entry had iso: true
uses: actions/upload-artifact@v6
with:
name: iso-${{ matrix.FLAVOR_ID }}-${{ matrix.arch }}
path: out/captainos-${{ matrix.FLAVOR_ID }}-${{ matrix.output_arch }}.iso
retention-days: 1
# -------------------------------------------------------------------
# Publish per-arch artifacts and compute checksums
# -------------------------------------------------------------------
- name: Log in to GHCR
if: github.ref == 'refs/heads/main'
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Publish artifacts to GHCR
# only pushes to main, and not PR workflows, should try to push to OCI registry
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
env:
TARGET: ${{ matrix.arch }}
run: uv run captain release-publish
build-captainos: # those use regular Debian apt repos for kernels
steps: *build_steps
env: *build_env
runs-on: ${{ matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
needs: [ download-tools, build-dockerfile ]
strategy:
fail-fast: false
matrix:
include:
- { arch: amd64, output_arch: x86_64, captainos_kernel: false, iso: true, FLAVOR_ID: "trixie-full" }
- { arch: arm64, output_arch: aarch64, captainos_kernel: false, iso: true, FLAVOR_ID: "trixie-full" }
- { arch: arm64, output_arch: aarch64, captainos_kernel: false, iso: false, FLAVOR_ID: "trixie-rockchip64" }
- { arch: arm64, output_arch: aarch64, captainos_kernel: false, iso: false, FLAVOR_ID: "trixie-rockchip64-vendor" }
- { arch: arm64, output_arch: aarch64, captainos_kernel: false, iso: false, FLAVOR_ID: "trixie-meson64" }
- { arch: arm64, output_arch: aarch64, captainos_kernel: false, iso: false, FLAVOR_ID: "trixie-armbian-rpi" }
# -------------------------------------------------------------------
# Publish combined multi-arch image (reuses per-arch registry blobs)
# -------------------------------------------------------------------
publish-combined:
if: github.ref == 'refs/heads/main'
name: "publish-combined"
runs-on: ubuntu-latest
needs: [ build-captainos ]
env:
ARCH: amd64
TARGET: combined
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Load shared config
run: cat .github/config.env >> "$GITHUB_ENV"
- name: Download initramfs artifacts (amd64)
uses: actions/download-artifact@v8
with:
name: initramfs-${{ env.DEFAULT_FLAVOR_ID }}-amd64
path: out
- name: Download ISO artifact (amd64)
uses: actions/download-artifact@v8
with:
name: iso-${{ env.DEFAULT_FLAVOR_ID }}-amd64
path: out
- name: Download initramfs artifacts (arm64)
uses: actions/download-artifact@v8
with:
name: initramfs-${{ env.DEFAULT_FLAVOR_ID }}-arm64
path: out
- name: Download ISO artifact (arm64)
uses: actions/download-artifact@v8
with:
name: iso-${{ env.DEFAULT_FLAVOR_ID }}-arm64
path: out
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Publish combined image to GHCR
# only pushes to main, and not PR workflows, should try to push to OCI registry
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
env:
FLAVOR_ID: "${{ env.DEFAULT_FLAVOR_ID }}"
run: uv run captain release-publish