Repository navigation
feat(devenv-image): move to nixos-26.05 (devenv 2.1.2), VERSION 2.0.0 - #480
Conversation
Pin NIXPKGS_REV to nixos-26.05 so the image ships devenv 2.x, which first appears there. The devenv major is part of the image contract, so this is a major VERSION bump; 1.x consumers keep the immutable 1.0.0 tag.
… notes Document that the devenv major is part of the image contract and what a 2.x CLI changes for repos still locked to 1.x modules: the explicit git-hooks input, lock rewrites between majors, .devenv reuse, and the devenv processes down behavior observed in sandboxes.
|
AI-assisted review (OpenCode), advisory. Reviewed head VerifiedThe pin is a genuine
It really ships devenv 2.1.2: The major This unblocks quickstart#474, and neither PR says so
Same channel, same version, same "record the major in the contract" requirement. I reached the channel and version independently before reading that ADR, so this is agreement rather than one document being derived from the other. Worth stating explicitly in one of the two places, because right now:
So the dependency is real but invisible from either side. #480 should land before #474 can claim its substrate contract is met. One supporting check: ADR-0030:84 says "No existing kit uses devenv, so there is no 1.x-to-2.x migration cost for kit authors." I confirmed the other half — quickstart One gap in the 2.x notes, from the same ADRThe README's "devenv 2.x notes for consuming repos" covers four CLI-major changes (implicit
The README currently says Suggest one line under the existing The other ADR-0030 items I checked and would not add — they are additive on 2.1.2 and not consumer-visible breaks: Two I am less sure about and raise as questions rather than findings:
NetThe pin, the version, and the major bump all check out, and keeping existing consumers on the immutable Not blocking on my read. |
|
Reviewed the 32-line diff, then went looking for cross-repo consumers because a major version bump on a published image is mostly a question about who pins it. No findings. One sequencing fact worth recording, because neither PR states it. The pin and the version claim both check outVerified rather than taken from the description:
And that rev really does ship the version the major bump is justified by: The "existing consumers keep the immutable so This unblocks quickstart#474, and neither PR says so
That is exactly what this PR does: Two things follow that I think are worth stating on the PRs:
On the 2.x notes listI compared this README's consumer notes against ADR-0030's survey of 2.x, expecting gaps. There aren't any that matter, and the reason is worth noting rather than filed as a finding: Most of the ADR's items are 2.2+ features that are not in 2.1.2, so a narrower list is the correct one for the version actually shipped. The One I could not verify offline: whether SecretSpec is present in 2.1.2 or arrives in 2.2+. If it is in 2.1.2 it is a behaviour a consuming repo could encounter, and a line in the notes would help. Flagging as a question, not a finding — I have no evidence either way. What I checked and found clean
No changes requested. The only thing I'd add is a cross-reference to quickstart#474 in the body, so whoever merges knows the ordering. AI-assisted review (OpenCode), prepared on operator instruction. Advisory. |
…d SecretSpec Record three devenv 2.1.2 behaviors a consuming repo can hit in a sandbox: .devenv/ lives in the workspace (lost on recreate under --clone), built-in services auto-allocate the next free port once a repo uses 2.x modules (strict_ports: true keeps a published port fixed), and SecretSpec is opt-in and prompts only on a terminal.
|
Thanks. Taken in
|
|
AI-assisted review (OpenCode), advisory — needs a human to confirm before it drives a change. Reviewed head Checked every version claim against upstream rather than reading the diff. One finding; the change itself is correct. Verified
Should-fix: the "why not newer" justification is stale and partly unverifiableThe PR body says 26.05 is the only viable channel because "2.2 and 2.3 exist only in
This doesn't change the decision: pinning a release branch over unstable is right regardless, and 26.05 remains the only release channel carrying 2.x. But the stated reason is load-bearing for the "only channel that is both devenv 2.x and release-pinned" conclusion, and as written it doesn't check out. Either cite where the darwin drop is observable (upstream release notes or a nixpkgs commit), or drop that half and rest on "unstable isn't release-pinned," which is sufficient on its own. Not blocking — it's the rationale in the PR body, not the change. Note on the quickstart#474 sequencing claimYou state this "satisfies the substrate requirement in GSA-TTS/agentic-coding-quickstart#474 (ADR-0030) … so it should land before #474 claims that requirement is met." I looked for a mechanical dependency and didn't find one: on Worth stating explicitly in the PR body if the ordering matters, since a reader checking README accuracyThe devenv 2.x consumer notes match what your testing section reports, and the behaviours documented (implicit Method: upstream API/raw-file checks against UNVERIFIED: the image build, the smoke test (devenv 2.1.2 in-sandbox, store ownership/permissions, |
|
Thanks. Fixed in the body: |
|
@wz-gsa can I get another review and verdict for this PR? |
|
Both findings closed. Verified rather than taken on assertion, since the darwin claim was the one I couldn't substantiate last time. The
That settles the "only channel that is both devenv 2.x and release-pinned" conclusion, which was the part the rationale was load-bearing for. The version correction matches what I measured. "2.2 and later exist only in The Head moved Verdict: no remaining findings from me. Still carrying the same unverified set as before — the image build, the in-sandbox smoke test, and the two-repo consumer-compatibility runs are taken on your reported evidence, since I have no sandbox-capable host. |
wz-gsa
left a comment
There was a problem hiding this comment.
Approving. One non-blocking nit — a quoted error string that devenv does not emit. Everything else verified, and this time I had a working sandbox, so the claims I previously took on your reported evidence are now measured.
First, a correction to my earlier reviews: I said I had "no sandbox-capable host." That was wrong — Docker 29.8.0 was running the whole time and I should have checked instead of asserting. I rebuilt this image locally and exercised the README's claims directly.
Built both pins, so the cross-major claims could actually be tested
pr480-devenv-1x:local devenv 1.11.2 direnv 2.36.0 (old pin, nixos-25.05)
pr480-devenv-review:local devenv 2.1.2 direnv 2.37.1 (this PR, nixos-26.05)
pr480-devenv-oc:local devenv 2.1.2 opencode 1.18.32 (opencode variant)
All arm64. The 1.x build also independently confirms the README's channel progression table.
Verified in-image
devenv version 2.1.2 (aarch64-linux) matches the pin
direnv version 2.37.1 matches
/nix owner agent:agent single-user, no daemon socket
nix on PATH 2.24.9 installer's
devenv's bundled nix devenv-nix-2.34-source
store db one /nix/var/nix/db/db.sqlite, agent-owned
non-interactive `sh -c` devenv, direnv, nix all resolve
flakes experimental-features = nix-command flakes
That fourth group is the README's most substantive claim — "devenv 2.x bundles its own Nix … and shares the single-user store … both read and write the same store database" — and it is exactly right: two Nix versions, one store. The non-interactive check confirms the ENV PATH comment's reasoning too (bash -c never reads .bashrc).
The lock-churn claim: reproduced, full round trip
1.x: devenv, flake-compat, git-hooks, nixpkgs, root (5)
2.x: devenv, nixpkgs, root (3) <- strips
1.x again: devenv, flake-compat, git-hooks, nixpkgs, root (5) <- re-adds
Worth recording a nuance I had to find the hard way: the churn only manifests when 2.x succeeds. On a repo that uses git-hooks.hooks, 2.x fails the assertion and leaves the lock untouched at 5 nodes. My first attempt tested the wrong shape and gave a misleading result.
.devenv/ cross-major reuse: verified in the risky direction
1.x -> 2.x -> 1.x on one shared .devenv/, all three exit 0. I specifically tested 1.x reading a .devenv/ that 2.x had rewritten, since that is the direction a mixed-CI team would hit.
Resolved two things I previously flagged as unverifiable
- SecretSpec is in 2.1.2.
src/modules/integrations/secretspec.nixexists at tagv2.1.2(it arrived in 1.8). So the opt-in note is correct and load-bearing for the shipped version — this was my open question last round. strict_portsis in 2.1.2, atdevenv-core/src/config.rs:383with analias = "strictPorts". Not a 2.2-only key.
Also built the opencode variant
A merge publishes four images (shell and opencode × amd64/arm64), and I had only built shell. The opencode variant verifies identically, with its base toolchain intact (opencode 1.18.32), so the matrix is not broken by the pin bump.
Nit — the quoted error string does not exist
README:49-51:
A repo using
git-hooks.hooksfails withgit-hooks or pre-commit-hooks input required
The behaviour is right; the quote is not. Actual output from the built image:
error: Failed assertions:
- To use 'git-hooks', run the following command:
$ devenv inputs add git-hooks github:cachix/git-hooks.nix --follows nixpkgs
The template is "To use '${attribute}', ${command}" (v2.1.2 src/modules/lib.nix:46). I checked whether the README was merely stale — the phrase appears in no tag I tested (v1.11.2, v2.0.0, v2.1.0, v2.1.2) and returns 0 code-search hits, so it is invented rather than outdated.
Not blocking, but worth fixing: it is what someone greps for when debugging, and the real message is more useful since it hands you the exact remediation command. The actual string also lets a reader distinguish this failure from an unrelated input error.
Two small things, take or leave
A local rebuild behind a TLS-inspecting proxy needs EXTRA_CA_CERT, and only the Dockerfile says so. The bare build fails at exit 60, and the cause is not obvious: github.com 302s to release-assets.githubusercontent.com, whose signed URL carries the path claim releaseassetproduction.blob.core.windows.net — an intercepted host on some corporate networks, while github.com itself is often on a bypass list. So the failure looks like a broken pin rather than a proxy. One line in the README's local-rebuild notes would save the next person the trace. The hatch itself works exactly as designed.
CI never builds this image on a PR — on: push: branches: [main] plus workflow_dispatch. A Dockerfile change merges unbuilt, and the first real build is the publish. That is a deliberate tradeoff (a PR build that pushed tags would be worse), but it does mean a local build is currently the only pre-merge signal. If a build-only, no-push PR job is cheap, it would close the gap.
Not verified
devenv processes downSIGKILL timing and the next-free-port behaviour — both need a long-running service in the container. Doable, not done.- amd64 for either variant. I built arm64 only; amd64 is emulated on this host.
- Live
acq/kit integration — image-level only.
AI-assisted review (OpenCode), approved on the maintainer's authority with their explicit go-ahead for this PR. Advisory — a human owns the merge.
wz-gsa
left a comment
There was a problem hiding this comment.
Approving. Converting my 2026-10-08 verdict into a formal review — it was posted as a comment, which left this sitting at REVIEW_REQUIRED and reading as unreviewed on the dashboard. My fault, not yours.
Confirmed the verdict still applies at the current head: 7838d574 → cf4db27d is main arriving (#453's paseo identity gate, #423's ADR). This PR's own three files are untouched:
git diff 7838d574 cf4db27d -- integrations/isolation/images/devenv
(empty)
Both findings from my first review are closed:
The x86_64-darwin claim is substantiated. I had flagged it as unverifiable because it is not in nixpkgs' package.nix metadata — no platforms or badPlatforms there. I was looking in the wrong place. Pulled cachix/devenv's v2.2 release notes:
Dropped
x86_64-darwin(Intel macOS): devenv is no longer built, tested, or released forx86_64-darwin. Intel Mac users should pin an older devenv CLI release.
Your citation is accurate, and it settles the "only channel that is both devenv 2.x and release-pinned" conclusion the rationale was load-bearing for.
The version range is corrected. "2.2 and later exist only in nixpkgs-unstable (currently 2.4.0)" matches what I measured at unstable HEAD.
The #474 dependency is now stated accurately — "conceptual: that PR pins no devenv image tag, so nothing enforces the order" is exactly what I found when I searched that branch.
Carrying forward the pin verifications from the first pass, which still hold since the files did not change:
- The pinned rev is genuinely on the release branch, not a cherry-pick:
compare 0d9e9b8...nixos-26.05@HEADreturnsahead_by: 311, behind_by: 0. - devenv
2.1.2and direnv2.37.1at that exact rev, not just at branch HEAD. - Channel progression confirms 2.x first appears in 26.05:
25.05 → 1.11.2,25.11 → 1.11.1,26.05 → 2.1.2. - No orphaned
1.0.0image references anywhere in either repo, so theVERSIONbump does not strand a consumer.
Unverified, unchanged: the image build, the in-sandbox smoke test (devenv 2.1.2, store ownership/permissions, nix store verify, cachix fetches), and the two-repo consumer-compatibility runs. No sandbox-capable host here; those stay on your reported evidence.
Summary
Move the devenv image's
NIXPKGS_REVtonixos-26.05(0d9e9b832d03ac387417e16ce1febf73b2e631e1), which ships devenv 2.1.2, and bumpVERSIONto2.0.0because the devenv major is part of the image contract. The README records that contract and what a 2.x CLI changes for repos still locked to 1.x modules. Existing consumers keep the immutable1.0.0tag.Eligibility & Accountability
@GSA-TTS/agentic-coding-teamcode-owner approval; eligibility is attested here, not authenticated). Anyone may open issues without this.AI Assistance Disclosure
Type of Change
integrations/)Motivation
Toolchain currency for the generic devenv image (item 1 of #418): devenv 2.x is absent from
nixos-25.05andnixos-25.11and first appears innixos-26.05. This PR is only the pin bump plus consumer documentation; size/startup measurement, thedevenv containergeneration model, and persistence docs from that issue are left for follow-ups.This satisfies the substrate requirement in GSA-TTS/agentic-coding-quickstart#474 (ADR-0030: a channel carrying the intended devenv major, with the major recorded in the image contract), so it should land before GSA-TTS/agentic-coding-quickstart#474 claims that requirement is met. The dependency is conceptual: that PR pins no devenv image tag, so nothing enforces the order.
nixos-26.05is the only channel that is both devenv 2.x and release-pinned: 2.2 and later exist only innixpkgs-unstable(currently 2.4.0), and devenv 2.2 stopped building forx86_64-darwin(devenv v2.2 release notes).Testing
make validatelocally (all checks pass)Build:
workflow_dispatchofdevenv-image.ymlon this branch succeeded on all four legs (shell/opencode × amd64/arm64); the manifest job skipped as designed offmain. Run: https://github.com/GSA-TTS/agentic-coding-patterns/actions/runs/37489740805Image smoke test (arm64
devenv-opencodedigest from that run, in an msb sandbox created throughacqwith a real kit stack):devenv version→devenv 2.1.2 (aarch64-linux); installer Nix 2.24.9 and direnv 2.37.1 present; non-interactivebash -c 'devenv version'works;agent:agentowns/nix,/nix/store(1775) and/nix/var/nix/db. A minimal devenv 2.x project built in the sandbox: its outputs are registered in the shared store DB (schema 10) as seen by the installer'snix path-info,nix store verifypasses, and no group/world-writable outputs are produced (the single-user-store regression fixed upstream in cachix/devenv#2757 is absent). Locked GitHub inputs, cache.nixos.org and cachix fetches all succeeded through the kit-provided CA via devenv's bundled Nix.Consumer compatibility (devenv 2.1.2 from the same nixpkgs rev, run against scratch copies of two team repos that stay locked to 1.x modules): a Python/venv/tasks repo passes unchanged; a Ruby/Postgres/
git-hooksrepo fails until thegit-hooksinput is declared indevenv.yaml, then passes includingdevenv up -dPostgres.devenv shellunder 2.x rewritesdevenv.lock(drops implicitgit-hooks/pre-commit-hooks/flake-compatnodes) and a 1.x CLI adds them back at current HEAD;.devenv/is reusable across majors. These behaviors are what the README section documents.Safety Checklist
Quality Checklist
Validation Results
Related Issues
Relates to #418
Additional Context
The feature-branch build wrote to the shared
devenv-*:cache-{amd64,arm64}registry cache tags, so the nextmainbuild after merge rebuilds more layers than usual.Known follow-ups not in this PR: a post-build smoke-test job in
devenv-image.yml(fixture withgit-hooks,direnv exec . true, store-permission check);devenv processes downcan time out and SIGKILL the process group without stopping a service's children (observed with Postgres under the 2.1.2 CLI); thedevenv updatepath (2.x modules,prekdefault, native process manager) could not be exercised behind a GitHub-API-rate-limited proxy because the bundled Nix's libgit2 fallback fails withauthentication required but no callback set.Reviewer Notes
Reviewers should verify:
NIXPKGS_REVresolves to anixos-26.05commit and the Dockerfile comment matchesVERSIONis2.0.0and not previously publishedmake validatepasses in CI