feat(ci): checks-on-push workflow (Forgejo Actions, eval tier)
.forgejo/workflows/check.yml runs on every push to main/v1 (+ manual dispatch): nix flake check --no-build (full module-system eval incl. the downstream template through mkFlake), py_compile of nomarchy-theme-sync, and bash -n over tracked .sh files. The always-on net under direct-to-main pushes — first slice of the ROADMAP lock-bump CI item. Scoped to the eval tier deliberately: the instance's runner is an act_runner docker container (no systemd, no /dev/kvm — established from the legacy repo's .gitea/workflows/check.yml, which ran 57 times on it), so the checks.* VM suite and real builds can't run there. A commented vm-checks job documents the KVM-runner upgrade path; the legacy workflow's container gotchas (nixbld setup for the single-user installer, sandbox=false for Stylix IFD, Nix pinned 2.31.5 vs lazy-trees, no JS actions past node20) are carried over verbatim in the header. docs/TESTING.md §1b documents what a green run does and does not mean. Verified: V0 locally (the same check commands, minus the container Nix install) + YAML parse. A real green run depends on the runner still being registered — not API-visible unauthenticated, so that is queued as [human] BACKLOG item 20. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
101
.forgejo/workflows/check.yml
Normal file
101
.forgejo/workflows/check.yml
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# Nomarchy CI — the always-on net under direct-to-main pushes.
|
||||||
|
#
|
||||||
|
# Scope (deliberate): the EVAL tier only. The Forgejo runner behind this
|
||||||
|
# instance is act_runner + docker containers (the legacy repo's check.yml
|
||||||
|
# ran 57 times on it) — no systemd, no /dev/kvm — so the checks.* VM
|
||||||
|
# tests and full toplevel builds can't run here. `nix flake check
|
||||||
|
# --no-build` still catches most breakage (type errors, missing options,
|
||||||
|
# bad merges, template/mkFlake drift — see docs/TESTING.md §1); the VM
|
||||||
|
# suite stays a local/promotion gate until a KVM-capable NixOS runner
|
||||||
|
# exists (see the commented vm-checks job at the bottom).
|
||||||
|
#
|
||||||
|
# Inherited-from-legacy gotchas (learned over 57 runs, kept verbatim):
|
||||||
|
# - Single-user Nix (--no-daemon): no systemd in the container. The
|
||||||
|
# installer runs as root and honours build-users-group=nixbld from
|
||||||
|
# its bundled nix.conf, aborting unless the group exists AND has
|
||||||
|
# members — create nixbld + users first.
|
||||||
|
# - sandbox=false: Stylix/base16.nix do import-from-derivation; the
|
||||||
|
# single-user Nix in this container can't set up the build sandbox
|
||||||
|
# (no user namespaces), which otherwise surfaces as
|
||||||
|
# "path '…-source' is not valid".
|
||||||
|
# - Pin the Nix version: 2.34's lazy-trees git cache doesn't
|
||||||
|
# materialise flake-input `-source` paths into the store, breaking
|
||||||
|
# the same IFD reads. 2.31.5 matches what wrote flake.lock.
|
||||||
|
# - Plain-shell Nix install, not a JS action: act_runner's bundled act
|
||||||
|
# tops out at node20; a `run:` step has no node-runtime coupling.
|
||||||
|
|
||||||
|
name: Check
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, v1]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
eval:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 60
|
||||||
|
env:
|
||||||
|
NIX_CONFIG: |
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
sandbox = false
|
||||||
|
NIX_SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Nix
|
||||||
|
run: |
|
||||||
|
NIX_VERSION=2.31.5
|
||||||
|
groupadd -r nixbld 2>/dev/null || true
|
||||||
|
for i in $(seq 1 10); do
|
||||||
|
useradd -r -g nixbld -G nixbld -d /var/empty \
|
||||||
|
-s /usr/sbin/nologin -c "Nix build user $i" "nixbld$i" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
curl -L "https://releases.nixos.org/nix/nix-${NIX_VERSION}/install" | sh -s -- --no-daemon
|
||||||
|
echo "$HOME/.nix-profile/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- name: nix flake check (eval only)
|
||||||
|
# Full module-system evaluation of every output — both nixos
|
||||||
|
# configs, the home config, the checks.* derivations (instantiated,
|
||||||
|
# not run) and the downstream template through lib.mkFlake.
|
||||||
|
run: nix flake check --no-build
|
||||||
|
|
||||||
|
- name: Python syntax (nomarchy-theme-sync)
|
||||||
|
# Via nix shell so the step doesn't depend on the runner image
|
||||||
|
# preinstalling python3.
|
||||||
|
run: |
|
||||||
|
nix shell nixpkgs#python3 --command \
|
||||||
|
python3 -m py_compile pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py
|
||||||
|
|
||||||
|
- name: Shell syntax (tracked scripts)
|
||||||
|
# The distro's user-facing scripts are generated by Nix (their
|
||||||
|
# syntax is exercised by the eval + local builds); this covers the
|
||||||
|
# hand-written .sh files: installer helpers and maintainer tools.
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
fail=0
|
||||||
|
while IFS= read -r script; do
|
||||||
|
head -1 "$script" | grep -qE '^#!.*\b(bash|sh)\b' || continue
|
||||||
|
if ! bash -n "$script"; then
|
||||||
|
echo "::error file=$script::bash syntax error"
|
||||||
|
fail=1
|
||||||
|
fi
|
||||||
|
done < <(git ls-files '*.sh')
|
||||||
|
exit "$fail"
|
||||||
|
|
||||||
|
# ── vm-checks (DISABLED until a KVM runner exists) ────────────────────
|
||||||
|
# The real prize: running the checks.* VM suite + a toplevel build in
|
||||||
|
# CI. Needs a runner on a NixOS (or at least nix + /dev/kvm) host —
|
||||||
|
# register one with a dedicated label, then uncomment and set runs-on
|
||||||
|
# to that label. Do NOT enable this against a label that doesn't
|
||||||
|
# exist: Forgejo queues such jobs forever instead of failing.
|
||||||
|
#
|
||||||
|
# vm-checks:
|
||||||
|
# runs-on: nix-kvm
|
||||||
|
# timeout-minutes: 120
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v4
|
||||||
|
# - run: nix flake check # builds + runs the VM tests
|
||||||
|
# - run: nix build .#nixosConfigurations.nomarchy.config.system.build.toplevel --no-link
|
||||||
|
# - run: nix build .#homeConfigurations.nomarchy.activationPackage --no-link
|
||||||
@@ -22,20 +22,16 @@ next, in what order*.
|
|||||||
|
|
||||||
## NOW
|
## NOW
|
||||||
|
|
||||||
### 2. CI: run the check suite on every push (Forgejo Actions)
|
### 20. Confirm the Forgejo runner is alive `[human]`
|
||||||
First slice of ROADMAP § Automated upstream lock bumps, promoted to NOW
|
The checks-on-push workflow (`.forgejo/workflows/check.yml`) shipped;
|
||||||
because agents now push to `main` autonomously — an always-on net under
|
the repo has `has_actions: true` and the legacy `check.yml` ran 57
|
||||||
that is the single highest-stability lever available. A workflow that
|
times on an act_runner, but whether that runner still exists is not
|
||||||
runs `nix flake check` + the `checks.*` VM suite + a
|
API-visible without auth. Check the first run of the new workflow at
|
||||||
`system.build.toplevel` build on push to `main`. **Why:** pillar 1;
|
https://git.bemagri.xyz/bernardo/Nomarchy/actions — if it sits queued,
|
||||||
today nothing re-verifies a push. **Done when:** the workflow exists,
|
re-register an act_runner (docker, `ubuntu-latest` label). **Stretch:**
|
||||||
is documented (docs/TESTING.md), and a red run is visible/notifiable;
|
a second runner on a NixOS host with `/dev/kvm` (label `nix-kvm`) —
|
||||||
the runner requirements (Linux + KVM for the VM checks, or a documented
|
then uncomment the workflow's `vm-checks` job and the VM suite + real
|
||||||
no-KVM subset) are written down. **Verify:** V1 locally (the same
|
builds run in CI too (that upgrades half of item 14 for free).
|
||||||
commands the workflow runs) + a real green run on the Forgejo instance
|
|
||||||
— if runner infra doesn't exist yet, deliver the workflow + a `[human]`
|
|
||||||
note on registering a runner. **Verify the runner half is possible
|
|
||||||
before promising it.**
|
|
||||||
|
|
||||||
### 3. Memory-pressure protection (no more frozen desktops)
|
### 3. Memory-pressure protection (no more frozen desktops)
|
||||||
New. A workstation that compiles from source *will* hit memory
|
New. A workstation that compiles from source *will* hit memory
|
||||||
@@ -154,10 +150,13 @@ Each is a small, self-contained polish item in the existing patterns:
|
|||||||
`SUPER+CTRL` bind; pairs naturally with theme work.
|
`SUPER+CTRL` bind; pairs naturally with theme work.
|
||||||
|
|
||||||
### 14. Automated upstream lock bumps (maintainer CI, slices b+c) `[big]`
|
### 14. Automated upstream lock bumps (maintainer CI, slices b+c) `[big]`
|
||||||
ROADMAP § Automated upstream lock bumps — the scheduled half, after
|
ROADMAP § Automated upstream lock bumps — the scheduled half (the
|
||||||
NOW#2 lands: weekly job runs `nix flake update` (within pinned release
|
checks-on-push workflow shipped; see item 20 for the runner status):
|
||||||
branches) → full check suite → lands on `main` on green; `v1` promotion
|
weekly job runs `nix flake update` (within pinned release branches) →
|
||||||
stays human. Plus the fast-lane note for security bumps.
|
full check suite → lands on `main` on green; `v1` promotion stays
|
||||||
|
human. Plus the fast-lane note for security bumps. Note the current
|
||||||
|
runner is eval-only (no KVM) — a green bump run guards eval, not the VM
|
||||||
|
suite, until item 20's stretch runner exists.
|
||||||
|
|
||||||
### 15. Display profiles — docked/undocked switching
|
### 15. Display profiles — docked/undocked switching
|
||||||
ROADMAP § Display / monitor management, remaining: true profile
|
ROADMAP § Display / monitor management, remaining: true profile
|
||||||
|
|||||||
@@ -17,6 +17,25 @@ Template:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-07-04 — CI checks-on-push shipped (loop iteration #2)
|
||||||
|
- **Task:** BACKLOG NOW#2 — Forgejo Actions workflow.
|
||||||
|
- **Did:** `.forgejo/workflows/check.yml` (push to main/v1 + dispatch):
|
||||||
|
flake check --no-build, theme-sync py_compile, bash -n over tracked
|
||||||
|
.sh. Scoped to the **eval tier** deliberately — API probing +
|
||||||
|
archaeology of the legacy `.gitea/workflows/check.yml` (57 runs on
|
||||||
|
this instance) showed the runner is an act_runner docker container
|
||||||
|
(no KVM/systemd), so the VM suite can't run there; a commented
|
||||||
|
`vm-checks` job documents the KVM-runner upgrade path. Legacy's
|
||||||
|
hard-won container gotchas (nixbld setup, sandbox=false for Stylix
|
||||||
|
IFD, Nix 2.31.5 pin) carried over verbatim. TESTING.md §1b added.
|
||||||
|
- **Verified:** V0 locally (same commands the workflow runs, minus the
|
||||||
|
container Nix install) + yq YAML parse. The real green run needs the
|
||||||
|
runner to be alive — **not confirmable from here** (runners API is
|
||||||
|
401 unauthenticated); watching the run after push.
|
||||||
|
- **Pending:** new `[human]` item 20 — confirm/re-register the runner;
|
||||||
|
stretch: a KVM runner unlocks the vm-checks job.
|
||||||
|
- **Next suggestion:** NOW#3 (memory-pressure protection).
|
||||||
|
|
||||||
## 2026-07-04 — Opt-in auto-commit shipped (loop iteration #1)
|
## 2026-07-04 — Opt-in auto-commit shipped (loop iteration #1)
|
||||||
- **Task:** BACKLOG NOW#1 — auto-commit of state mutations (in-flake
|
- **Task:** BACKLOG NOW#1 — auto-commit of state mutations (in-flake
|
||||||
state Phase 4). First autonomous /loop iteration.
|
state Phase 4). First autonomous /loop iteration.
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ here the moment a debugging session teaches you something a future
|
|||||||
iteration would otherwise rediscover.
|
iteration would otherwise rediscover.
|
||||||
|
|
||||||
## Testing & VM recipes
|
## Testing & VM recipes
|
||||||
|
- CI (`.forgejo/workflows/check.yml`) is **eval-tier only**: the Forgejo
|
||||||
|
act_runner is a docker container (no systemd, no /dev/kvm). Container
|
||||||
|
gotchas are documented in the workflow header (single-user Nix +
|
||||||
|
nixbld users, `sandbox=false` for Stylix IFD, Nix pinned 2.31.5 vs
|
||||||
|
lazy-trees, no JS actions past node20) — learned over the legacy
|
||||||
|
repo's 57 runs; read them before touching the workflow.
|
||||||
- Reusable headless VM harness: `checks.*` via runNixOSTest — existing
|
- Reusable headless VM harness: `checks.*` via runNixOSTest — existing
|
||||||
examples to crib from: `distro-id` (boots + `switch-to-configuration
|
examples to crib from: `distro-id` (boots + `switch-to-configuration
|
||||||
dry-activate`), `hardware-toggles` (kernel cmdline/PAM assertions),
|
dry-activate`), `hardware-toggles` (kernel cmdline/PAM assertions),
|
||||||
|
|||||||
@@ -22,6 +22,17 @@ bad merges — most breakage stops here. It also evaluates the downstream
|
|||||||
template through `lib.mkFlake` (including a real nixos-hardware profile),
|
template through `lib.mkFlake` (including a real nixos-hardware profile),
|
||||||
so template/wrapper drift fails fast too.
|
so template/wrapper drift fails fast too.
|
||||||
|
|
||||||
|
## 1b. CI (automatic on push)
|
||||||
|
|
||||||
|
Every push to `main`/`v1` runs `.forgejo/workflows/check.yml`: the §1
|
||||||
|
cheap checks (flake eval, Python + shell syntax) on the Forgejo instance.
|
||||||
|
That's the **eval tier only** — the runner is a docker container without
|
||||||
|
KVM, so the `checks.*` VM suite and real builds stay local (this file)
|
||||||
|
until a KVM-capable runner is registered; the workflow carries a
|
||||||
|
commented `vm-checks` job ready for that day. A green CI run is *not* "it
|
||||||
|
renders" (the honesty rule below still applies) — it means "nobody broke
|
||||||
|
evaluation".
|
||||||
|
|
||||||
## 2. Build and boot the live ISO
|
## 2. Build and boot the live ISO
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
Reference in New Issue
Block a user