feat(ci): scheduled weekly lock bump + dispatch fast-lane (item 14 b+c)
Some checks failed
Check / eval (push) Has been cancelled

.gitea/workflows/bump.yml: Mondays 05:17 UTC (+ workflow_dispatch for
security bumps), nix flake update — within the pinned release branches
by construction, never a release jump — gated by nix flake check
--no-build, then a pathspec-limited flake.lock commit pushed to main
with the update's change list as the body. That push triggers check.yml
as a second net. Red gate or push race = a visibly failed run, nothing
lands. v1 promotion stays human. py_compile/bash -n deliberately not in
the gate: they don't read the lock. Container recipe inherited from
check.yml (nixbld, sandbox=false, pinned Nix 2.31.5).

Verified: V0 (yq parse, bash -n per run block); the update/commit/push
logic simulated end-to-end in a scratch clone with a real nix flake
update and a bare remote (changed + unchanged branches, bystander file
stays uncommitted, push lands); today's bumped lock evals green.
Remains: the first real run (cron pickup + Actions-token push) is not
confirmable from a session — BACKLOG item 14 slimmed to that watch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-07-05 17:18:54 +01:00
parent 26e393b65d
commit 5eadf0cff6
4 changed files with 125 additions and 8 deletions

90
.gitea/workflows/bump.yml Normal file
View File

@@ -0,0 +1,90 @@
# Nomarchy scheduled lock bump — the automated half of "rock-stable
# without rotting": once a week, update flake.lock (inputs track pinned
# release branches, so this never jumps a NixOS release — that's a
# deliberate hand-edited v2, see agent/GOALS.md), gate it, and land it
# on main only on green. `v1` promotion stays human, always.
#
# Fast lane: workflow_dispatch. For a security fix upstream, run this
# workflow manually from the Actions tab instead of waiting for Monday.
#
# Gate scope: `nix flake check --no-build` — the same eval tier as
# check.yml (this runner has no KVM; see item 20 for the VM-suite
# upgrade path). The py_compile/bash -n steps are skipped on purpose:
# they don't read flake.lock, so a lock bump cannot break them. The
# bump commit's own push then triggers check.yml as a second net.
# A green bump therefore guards evaluation, not VM behaviour — the
# checks.* suite still runs locally / at promotion time.
#
# Failure mode: a red gate fails this run visibly and pushes nothing;
# next schedule retries. A push race (someone landed on main mid-run)
# also just fails the final push — rerun or wait a week.
#
# Container recipe (nixbld users, sandbox=false, pinned Nix, plain-shell
# install) inherited from check.yml — the gotchas are documented there.
name: Lock bump
on:
schedule:
- cron: '17 5 * * 1' # Mondays 05:17 UTC
workflow_dispatch:
jobs:
bump:
runs-on: ubuntu-latest
timeout-minutes: 90
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: Update flake.lock
# Inputs track release branches (nixos-26.05, release-26.05), so
# the update stays within them by construction. The human-readable
# change list goes into the commit body below.
run: |
nix flake update 2>&1 | tee /tmp/bump-log
if git diff --quiet flake.lock; then
echo "Lock already up to date — nothing to do."
echo "changed=0" >> "$GITHUB_OUTPUT"
else
echo "changed=1" >> "$GITHUB_OUTPUT"
fi
id: update
- name: Gate — nix flake check (eval only)
if: steps.update.outputs.changed == '1'
run: nix flake check --no-build
- name: Commit + push on green
if: steps.update.outputs.changed == '1'
# The checkout step persists the Actions token, so this push
# authenticates as the workflow; its push triggers check.yml as
# the second net. Only flake.lock is committed — pathspec-limited,
# nothing else can ride along.
run: |
{
echo "chore(lock): scheduled upstream bump"
echo
grep -E '^(• | )' /tmp/bump-log || true
echo
echo "Gate: nix flake check --no-build (eval tier — see bump.yml header)."
} > /tmp/bump-msg
git -c user.name="nomarchy-bump" -c user.email="actions@git.bemagri.xyz" \
commit --only flake.lock -F /tmp/bump-msg
git push origin HEAD:main

View File

@@ -26,14 +26,17 @@ next, in what order*.
## NEXT ## NEXT
### 14. Automated upstream lock bumps (maintainer CI, slices b+c) `[big]` ### 14. Automated lock bumps — confirm the first real run
ROADMAP § Automated upstream lock bumps — the scheduled half (the Slices b+c shipped 2026-07-05 (`.gitea/workflows/bump.yml`): weekly
checks-on-push workflow shipped; see item 20 for the runner status): schedule (Mon 05:17 UTC) + `workflow_dispatch` as the security
weekly job runs `nix flake update` (within pinned release branches) → fast-lane; `nix flake update` → eval gate → pathspec-limited lock
full check suite → lands on `main` on green; `v1` promotion stays commit pushed to `main` on green (that push triggers check.yml as the
human. Plus the fast-lane note for security bumps. Note the current second net). Update/commit/push logic simulated locally end-to-end in
runner is eval-only (no KVM) — a green bump run guards eval, not the VM a scratch clone, incl. a real update; today's bumped lock evals green.
suite, until item 20's stretch runner exists. Remaining (not confirmable from a session): the first scheduled or
dispatched run must land — watch that the runner picks up the cron and
that the Actions token can push. Then delete this item. Item 20's KVM
runner later upgrades the gate from eval-only to the VM suite.
### 20. KVM runner → VM suite in CI `[human]` ### 20. KVM runner → VM suite in CI `[human]`
The remaining stretch of the CI item — checks-on-push is live and The remaining stretch of the CI item — checks-on-push is live and

View File

@@ -17,6 +17,27 @@ Template:
--- ---
## 2026-07-05 — scheduled lock-bump workflow (iteration #26, item 14 b+c)
- **Task:** BACKLOG NEXT#14 `[big]` — split: (a) checks-on-push shipped
earlier; this ships (b) the weekly bump + (c) the fast-lane as
workflow_dispatch on the same job.
- **Did:** .gitea/workflows/bump.yml — Mon 05:17 UTC cron + dispatch:
nix flake update (pinned branches by construction) → gate `nix flake
check --no-build` (py_compile/bash -n skipped: they don't read the
lock) → commit --only flake.lock with the update's change list as
body → push main (triggers check.yml as second net). Red gate/push
race = failed run, nothing lands. Container recipe from check.yml.
- **Verified:** V0 (yq parse + bash -n each run block); logic simulated
end-to-end in a scratch clone with a REAL nix flake update + bare
remote: changed/unchanged branches, bystander file stays uncommitted,
push lands; today's bumped lock evals green (Monday's baseline).
Gitea 1.25.4 confirmed (schedule supported). The real cron pickup +
token push are NOT confirmable from here → item 14 slimmed to
"confirm first run".
- **Pending:** watch the first scheduled/dispatched bump run.
- **Next suggestion:** #16 greeter theming (next codeable item; #15
needs its design pass written first).
## 2026-07-05 — color picker (iteration #25, item 13 final slice → item done) ## 2026-07-05 — color picker (iteration #25, item 13 final slice → item done)
- **Task:** BACKLOG NEXT#13 last slice — hyprpicker → clipboard from - **Task:** BACKLOG NEXT#13 last slice — hyprpicker → clipboard from
the menu + a direct bind. Item 13 complete; deleted from BACKLOG. the menu + a direct bind. Item 13 complete; deleted from BACKLOG.

View File

@@ -13,6 +13,9 @@ iteration would otherwise rediscover.
`sandbox=false` for Stylix IFD, Nix pinned 2.31.5 vs lazy-trees, no JS `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 actions past node20) — learned over the legacy repo's 57 runs; read
them before touching the workflow. them before touching the workflow.
- The Gitea instance is **1.25.4**`on: schedule` workflows are
supported; bump.yml assumes the Actions token can push to `main`
(standard Gitea behaviour, but unconfirmed until the first run lands).
- The git server is **Gitea** (gitea/act_runner via docker-compose), NOT - The git server is **Gitea** (gitea/act_runner via docker-compose), NOT
Forgejo — workflows are read from `.gitea/workflows/` (or `.github/`), Forgejo — workflows are read from `.gitea/workflows/` (or `.github/`),
never `.forgejo/workflows/` (a whole push cycle was lost to that). never `.forgejo/workflows/` (a whole push cycle was lost to that).