From e8584e077814a4e2404af007fa9177e4eb875de9 Mon Sep 17 00:00:00 2001 From: etrobert-bot Date: Fri, 10 Jul 2026 04:39:44 +0200 Subject: [PATCH] feat(pi): deploy via comin tracking the CI-gated deploy ref Replace pi's nightly system.autoUpgrade with comin, a pull-based GitOps deployer. comin polls the `deploy` ref every ~60s and switches to nixosConfigurations.pi. A new CI `deploy` job fast-forwards `deploy` to each merged commit only after all-builds passes, so pi never deploys raw main and converges within a minute of CI going green. Co-Authored-By: Claude Fable 5 --- .github/workflows/build.yml | 20 +++++++ CLAUDE.md | 6 ++- flake.lock | 83 ++++++++++++++++++++++++++++-- flake.nix | 5 ++ modules/hosts/pi/configuration.nix | 24 +++++---- modules/hosts/pi/default.nix | 1 + 6 files changed, 121 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 16684c4f..862fc76e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -130,3 +130,23 @@ jobs: || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }} run: exit 1 + + # Fast-forward the `deploy` ref to this commit so pi's comin poller + # converges within a minute. Gated on all-builds succeeding, which also + # guarantees the aarch64 closure is already in Cachix (pushed by tower's + # post-build hook during the build). Main only, and all-builds runs with + # if: always(), so require its explicit success. + deploy: + name: deploy + needs: all-builds + if: >- + ${{ github.ref == 'refs/heads/main' + && needs.all-builds.result == 'success' }} + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v6 + + - name: Fast-forward deploy ref + run: git push origin HEAD:deploy diff --git a/CLAUDE.md b/CLAUDE.md index 020a74b6..b55b5d85 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -116,8 +116,10 @@ the insecure package, the assertion fails and prompts removal. are port-forwarded to tower (`.10`). **LAN DHCP + DNS:** served by `pi` via `dnsmasq` (`modules/lan-dns.nix`, -listening on `end0`, static `.18`). Pi auto-upgrades from main nightly — test -before merging. +listening on `end0`, static `.18`). Pi runs comin, which polls the CI-gated +`deploy` ref (fast-forwarded to a commit only after `all-builds` passes) and +deploys `nixosConfigurations.pi` within ~60s of a merge to main — test before +merging. **Static LAN addresses:** `pi end0` `.18` (MAC `DC:A6:32:13:51:14`), `tower` `.10` (motherboard NIC `enp11s0`, static via NetworkManager in diff --git a/flake.lock b/flake.lock index 97cd37eb..e378cf77 100644 --- a/flake.lock +++ b/flake.lock @@ -40,6 +40,28 @@ "type": "github" } }, + "comin": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "nixpkgs" + ], + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1783491028, + "narHash": "sha256-W7tFZ6PbrsGHWjT6CsC3z5Wpu6/pNsJXvtPZv6ju0h0=", + "owner": "nlewo", + "repo": "comin", + "rev": "33e038be1b817015deabb4104237462e607e69c3", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "comin", + "type": "github" + } + }, "creatures": { "inputs": { "nixpkgs": [ @@ -102,6 +124,22 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1765121682, + "narHash": "sha256-4VBOP18BFeiPkyhy9o4ssBNQEvfvv1kXkasAYd0+rrA=", + "owner": "NixOS", + "repo": "flake-compat", + "rev": "65f23138d8d09a92e30f1e5c87611b23ef451bf3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -242,16 +280,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1783224372, - "narHash": "sha256-8i/87eeoqiGE4yOTjwSA3Eh/ziJRQEmd/unYU+K27sk=", + "lastModified": 1770107345, + "narHash": "sha256-tbS0Ebx2PiA1FRW8mt8oejR0qMXmziJmPaU1d4kYY9g=", "owner": "nixos", "repo": "nixpkgs", - "rev": "d407951447dcd00442e97087bf374aad70c04cea", + "rev": "4533d9293756b63904b7238acb84ac8fe4c8c2c4", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-unstable", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } @@ -271,6 +309,22 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1783224372, + "narHash": "sha256-8i/87eeoqiGE4yOTjwSA3Eh/ziJRQEmd/unYU+K27sk=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d407951447dcd00442e97087bf374aad70c04cea", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "pronto": { "inputs": { "nixpkgs": [ @@ -334,6 +388,7 @@ "root": { "inputs": { "agenix": "agenix", + "comin": "comin", "creatures": "creatures", "etiennerobert-com": "etiennerobert-com", "flake-parts": "flake-parts", @@ -342,7 +397,7 @@ "nix-darwin": "nix-darwin", "nix-homebrew": "nix-homebrew", "nix-index-database": "nix-index-database", - "nixpkgs": "nixpkgs", + "nixpkgs": "nixpkgs_2", "pronto": "pronto", "rack": "rack", "rift-radar": "rift-radar", @@ -364,6 +419,24 @@ "type": "github" } }, + "treefmt-nix": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1770228511, + "narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "337a4fe074be1042a35086f15481d763b8ddc0e7", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, "zen-browser": { "inputs": { "nixpkgs": [ diff --git a/flake.nix b/flake.nix index bfb1b304..0cdac1a3 100644 --- a/flake.nix +++ b/flake.nix @@ -64,6 +64,11 @@ url = "github:ryoppippi/nix-claude-code"; inputs.nixpkgs.follows = "nixpkgs"; }; + # Pull-based GitOps deployer for pi; not packaged in nixpkgs. + comin = { + url = "github:nlewo/comin"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = diff --git a/modules/hosts/pi/configuration.nix b/modules/hosts/pi/configuration.nix index 03c53511..00b43d01 100644 --- a/modules/hosts/pi/configuration.nix +++ b/modules/hosts/pi/configuration.nix @@ -27,17 +27,6 @@ }; }; - system.autoUpgrade = { - enable = true; - flake = "github:etrobert/setup/main#pi"; - flags = [ - "--accept-flake-config" - "--print-build-logs" - ]; - # dates = "4:40"; # default value - randomizedDelaySec = "5min"; - }; - networking.hostName = "pi"; networking.networkmanager = { @@ -64,6 +53,19 @@ services = { tailscale.extraUpFlags = [ "--advertise-exit-node" ]; + # comin polls the CI-gated `deploy` ref (fast-forwarded only after the + # all-builds job succeeds) and deploys nixosConfigurations.pi within ~60s. + comin = { + enable = true; + remotes = [ + { + name = "origin"; + url = "https://github.com/etrobert/setup.git"; + branches.main.name = "deploy"; + } + ]; + }; + navidrome = { enable = true; settings = { diff --git a/modules/hosts/pi/default.nix b/modules/hosts/pi/default.nix index f92a6d2d..697ef284 100644 --- a/modules/hosts/pi/default.nix +++ b/modules/hosts/pi/default.nix @@ -13,6 +13,7 @@ self.nixosModules.base self.nixosModules.lanDns inputs.agenix.nixosModules.default + inputs.comin.nixosModules.comin ]; }; }