Files
scoutfs-build/docs/local-ci-setup.md
William Gill f36e06f545 Switch to self-hosted runner with cached incremental builds
Replaces the ephemeral EL8/EL9/watch-kernels workflows with a single
ScoutFS CI workflow that runs on a self-hosted Gitea Act Runner using
pre-baked builder images and a persistent /var/cache/scoutfs-ci volume.
cache-kernels.sh downloads only new kernel-devel RPMs and diffs against
the Gitea manifest so each run only builds kernels that aren't already
published, dramatically reducing run time for the common case.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:55:05 -05:00

4.0 KiB

ScoutFS Local CI Setup

This repo uses a self-hosted Gitea Act Runner with pre-baked builder images and a persistent kernel-devel cache. Compared to the old fully- ephemeral workflows, this makes incremental kernel builds ~10x faster because build deps are baked in and kernel RPMs are cached on disk.

Host prerequisites

  • Linux host with podman (or docker) and git
  • Network reachability to your Gitea instance
  • Root (or rootless podman) to manage /var/cache/scoutfs-ci

1. Create the cache volume directory

sudo mkdir -p /var/cache/scoutfs-ci
sudo chown "$(id -u):$(id -g)" /var/cache/scoutfs-ci

The workflow bind-mounts this into each build container at /var/cache/scoutfs. Layout after first run:

/var/cache/scoutfs-ci/
  el8/kernel-devel/*.rpm
  el9/kernel-devel/*.rpm

2. Build the pre-baked builder images

git clone https://git.anomalous.dev/<owner>/scoutfs-build.git
cd scoutfs-build
./ci/images/build.sh

This produces:

  • localhost/scoutfs-builder:el8
  • localhost/scoutfs-builder:el9

Re-run whenever you want to refresh build deps (e.g., a new rpm-build release). Consider a weekly cron.

3. Register the Gitea Act Runner

Download act_runner from your Gitea instance (/-/admin/actions/runners) and register it with the two labels the workflow expects:

./act_runner register \
    --instance https://git.anomalous.dev \
    --token <registration-token> \
    --name scoutfs-local \
    --labels scoutfs-el8:docker://localhost/scoutfs-builder:el8,scoutfs-el9:docker://localhost/scoutfs-builder:el9

Run it as a systemd service:

sudo cp act_runner /usr/local/bin/
sudo tee /etc/systemd/system/act_runner.service <<'EOF'
[Unit]
Description=Gitea Act Runner
After=network.target

[Service]
ExecStart=/usr/local/bin/act_runner daemon
WorkingDirectory=/var/lib/act_runner
Restart=always
User=act_runner

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now act_runner

4. Configure secrets and variables in Gitea

Under Repo Settings → Actions → Secrets:

Secret Purpose
TOKEN_GITEA API token with write:package scope
GPG_PRIVATE_KEY ASCII-armored GPG private key
GPG_PASSPHRASE GPG key passphrase

Under Variables (optional):

Variable Default
SCOUTFS_REPO_URL https://github.com/versity/scoutfs.git

5. Trigger a build

  • Manual: Gitea UI → Actions → ScoutFS CI → Run workflow
  • On new scoutfs release: push a tag v*
  • Scheduled: cron fires daily at 06:00 UTC and only builds new kernels

How incremental builds work

  1. ci/cache-kernels.sh lists available kernel-devel packages, downloads any not already in /var/cache/scoutfs/el${EL}/kernel-devel/, and installs all cached RPMs with rpm -ivh --force --nodeps.
  2. It fetches the already-built kernel manifest from the Gitea generic package registry (scoutfs-built-kernels/el${EL}/manifest.txt) and writes only the new kernel versions to output/kernels-to-build.txt.
  3. If that file is empty, all downstream steps (build-rpm, sign, publish, manifest update) are skipped via if: steps.cache.outputs.build == 'yes'.
  4. ci/build-rpm.sh iterates that file and runs rpmbuild -tb per kernel, writing results to output/build-results.jsonl.
  5. ci/update-kernel-manifest.sh merges successful builds back into the Gitea manifest so the next run skips them.

Verification checklist

  • podman images | grep scoutfs-builder → el8 and el9 tags present
  • systemctl status act_runner → active, labels visible in Gitea UI
  • First manual dispatch: cold cache → downloads all kernels, builds all
  • Second dispatch (immediately after): <30 s, 0 builds
  • Delete one entry from scoutfs-built-kernels/el9/manifest.txt → next dispatch rebuilds only that kernel
  • Push v1.29.1-test tag → utils RPM also builds and publishes
  • Fresh AlmaLinux 9 VM → curl .../setup-scoutfs.sh | sudo bashdnf install kmod-scoutfsmodinfo scoutfs succeeds