Skip to content

Commit dfb48e1

Browse files
feat(devenv): de-pin 3 agent-image devenv-fork sites onto the tool (RIG-2812)
Route three executable hand-pins of the RigelBuild/devenv fork rev through tools/toolchain/devenv-cli, resolving the flakeref from agent-image/devenv.lock at runtime instead of a literal github:RigelBuild/devenv/<40hex>#devenv: - tools/agent-image-env-gate/index.ts: direct core.ts import (devenvSource + flakeref), no CLI hop. - agent-image/moon.yml: build task command: -> script: (resolve-then-run), runFromWorkspaceRoot so the tool/lock paths match ci.yml's seed step. - devenv.nix dogfood:agent-image: ${config.devenv.root}-anchored tool call. Behavior-preserving: the tool resolves the lock's devenv node to exactly the removed literal (15a81f3e...). The fourth pin (agent-image/publish.sh) is deferred to a stacked PR — it runs in release.yml's publish-image job, which bootstraps no bun. Part of RIG-2546 (T2a, RD-2 full-kill). Spec-impact: none. Co-authored-by: Matt Wilkinson <matt@rigel.build>
1 parent ff5bfab commit dfb48e1

3 files changed

Lines changed: 40 additions & 24 deletions

File tree

‎agent-image/moon.yml‎

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# yaml-language-server: $schema=https://moonrepo.dev/schemas/project.json
22
#
33
# compass-agent-image (agent-image/): the compass-agent runtime image. A
4-
# standalone nix devenv, not a bun package — the build is
5-
# `nix run github:RigelBuild/devenv/15a81f3e15619187fcbe10c2eac40878e0b4ce28#devenv -- container build agent`, the same
6-
# fork-pinned derivation the publish lane ships (agent-image/publish.sh) and the
7-
# local `dogfood:agent-image` load produce. A green build here is proof the
8-
# exact artifact that publishes still builds.
4+
# standalone nix devenv, not a bun package — the build resolves the devenv fork
5+
# rev from agent-image/devenv.lock (via tools/toolchain/devenv-cli) and runs
6+
# `nix run "$src" -- container build agent`, the same derivation the publish lane
7+
# ships (agent-image/publish.sh) and the local `dogfood:agent-image` load
8+
# produce. A green build here is proof the exact artifact that publishes still
9+
# builds.
910
#
1011
# WHY THIS IS A MOON PROJECT. Registering it in .moon/workspace.yml is what puts
1112
# the image build in the gate: on a PR `moon ci :ci` runs this project's `ci`
@@ -34,19 +35,26 @@ workspace:
3435
tasks:
3536
build:
3637
# Realise the image exactly as the publish lane and the dogfood load do —
37-
# the same fork-pinned derivation, so a green build here proves the exact
38-
# artifact that publishes builds. Runs from agent-image/ (moon's default
39-
# project-dir cwd) so `devenv container build` resolves this image's
38+
# the same derivation, so a green build here proves the exact artifact that
39+
# publishes builds. The devenv fork rev is resolved from
40+
# agent-image/devenv.lock at runtime (never hand-pinned) via
41+
# tools/toolchain/devenv-cli, matching ci.yml's seed step. moon `command:`
42+
# is a single command with no shell to compose the `$(…)` resolve, so this is
43+
# a `script:` running the two-step resolve-then-run. Runs from the workspace
44+
# root (runFromWorkspaceRoot below) so the tool path and lock are the same
45+
# repo-root-relative strings ci.yml uses; the `cd agent-image` then puts the
46+
# nix run in agent-image/ so `devenv container build` resolves this image's
4047
# devenv.yaml/devenv.lock, matching publish.sh. The substituters the build
4148
# fetches from are named in ci.yml's install-nix-action config, the reviewed
4249
# trust surface for this gate.
4350
#
44-
# cache:false — nix owns its store-path caching; moon must not false-green a
45-
# build it did not re-run (the same posture the fork builds take).
46-
command: 'nix run github:RigelBuild/devenv/15a81f3e15619187fcbe10c2eac40878e0b4ce28#devenv -- container build agent'
51+
# cache:false — nix owns its store-path caching, so moon must not false-green
52+
# a build it did not re-run (the same posture the fork builds take).
53+
script: 'src=$(bun tools/toolchain/devenv-cli/index.ts --lock agent-image/devenv.lock --mode flakeref); cd agent-image && nix run "$src" -- container build agent'
4754
options:
4855
cache: false
4956
runInCI: true
57+
runFromWorkspaceRoot: true
5058
# The image's build closure. MIRRORS publish-agent-image.yml's
5159
# on.push.paths — the reviewed source of truth for what changes the
5260
# published artifact — so affected-detection schedules this build on exactly

‎devenv.nix‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -530,13 +530,14 @@ in
530530
# targets the Linux dev box.
531531
# agent-image: build AND load the agent base image into
532532
# containers-storage:compass-agent:latest (the ref the runner resolves with
533-
# no pull). `container copy` builds then copies; the invocation is pinned to
534-
# the shared RigelBuild/devenv fork's own CLI, pinned by rev
535-
# (`nix run github:RigelBuild/devenv/<rev>#devenv`) so it cannot diverge
536-
# from the fork source the agent-image module set is pinned to. Opt-in (per
537-
# D5): NOT wired `after` into up — the image closure is large and rebuilding
538-
# it on every `up` would violate the never-heavy-on-up constraint. The runner
539-
# starts fine without the image; it only resolves it at Provision time.
533+
# no pull). `container copy` builds then copies; the devenv fork rev is
534+
# resolved from agent-image/devenv.lock at runtime (via
535+
# tools/toolchain/devenv-cli, `nix run "$src" -- …`) so it names exactly the
536+
# fork source the agent-image module set is pinned to — the same source
537+
# ci.yml's seed step resolves. Opt-in (per D5): NOT wired `after` into up —
538+
# the image closure is large and rebuilding it on every `up` would violate
539+
# the never-heavy-on-up constraint. The runner starts fine without the image;
540+
# it only resolves it at Provision time.
540541
"dogfood:agent-image" = {
541542
exec = ''
542543
set -euo pipefail
@@ -549,7 +550,8 @@ in
549550
# Removing it first makes the bare ref resolve to the image we just built.
550551
# `podman rmi` exits non-zero when the tag is absent, so tolerate that.
551552
podman rmi -f localhost/compass-agent:latest 2>/dev/null || true
552-
nix run github:RigelBuild/devenv/15a81f3e15619187fcbe10c2eac40878e0b4ce28#devenv -- container copy agent
553+
src=$(bun "${config.devenv.root}/tools/toolchain/devenv-cli/index.ts" --lock "${config.devenv.root}/agent-image/devenv.lock" --mode flakeref)
554+
nix run "$src" -- container copy agent
553555
'';
554556
cwd = "${config.devenv.root}/agent-image";
555557
};

‎tools/agent-image-env-gate/index.ts‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { existsSync } from "node:fs";
2222
import { dirname, join } from "node:path";
2323
import { fileURLToPath } from "node:url";
2424
import { $ } from "bun";
25+
import { devenvSource, flakeref } from "../toolchain/devenv-cli/core.ts";
2526
import { findForbiddenEnv } from "./env-check.ts";
2627

2728
// The platform the consumer's frozen record pins (compass-native #1073,
@@ -96,13 +97,18 @@ if (import.meta.main) {
9697
const agentImageDir = join(repoRoot, "agent-image");
9798

9899
// Build the image spec exactly as the publish lane does. devenv tracing goes
99-
// to stderr; the spec store path is the last stdout line.
100+
// to stderr; the spec store path is the last stdout line. The devenv fork rev
101+
// is resolved from agent-image/devenv.lock at runtime (never hand-pinned), so
102+
// this gate builds the exact derivation the lock names — the same source
103+
// ci.yml's seed step resolves.
104+
const ref = flakeref(
105+
devenvSource(await Bun.file(join(agentImageDir, "devenv.lock")).text()),
106+
);
100107
let buildOut: string;
101108
try {
102-
buildOut =
103-
await $`nix run github:RigelBuild/devenv/15a81f3e15619187fcbe10c2eac40878e0b4ce28#devenv -- container build agent`
104-
.cwd(agentImageDir)
105-
.text();
109+
buildOut = await $`nix run ${ref} -- container build agent`
110+
.cwd(agentImageDir)
111+
.text();
106112
} catch (cause) {
107113
fail(`image build failed: ${String(cause)}`);
108114
}

0 commit comments

Comments
 (0)