From 18aab773f6bee67ced002af81e7bd5c55beae8c5 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 14:11:06 +0000 Subject: [PATCH 1/2] fix(update): skip Nix calls when --no-install is set (#2585) `devbox update --no-install` still shelled out to Nix after refreshing the lockfile: it unconditionally ran `nix flake update` (via FlakeUpdate) and `nix path-info` (via FixMissingStorePaths). This defeats the purpose of --no-install and breaks the command in environments where Nix isn't fully set up (e.g. CI/Renovate), where those calls print "Running nix flake update" or crash with "cannot determine user's home directory". Guard both Nix-invoking steps behind `!opts.NoInstall` so the flag only updates the lockfile. Add a regression testscript asserting that `devbox update --no-install` does not run `nix flake update`. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01Gtqrm1XgX3ZvcjHCJjuBgt --- internal/devbox/update.go | 25 ++++++++++++++++--------- testscripts/update/update.test.txt | 5 +++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/internal/devbox/update.go b/internal/devbox/update.go index acd6592a529..7ab2578b0d8 100644 --- a/internal/devbox/update.go +++ b/internal/devbox/update.go @@ -85,15 +85,22 @@ func (d *Devbox) Update(ctx context.Context, opts devopt.UpdateOpts) error { return err } - // I'm not entirely sure this is even needed, so ignoring the error. - // It's definitely not needed for non-flakes. (which is 99.9% of packages) - // It will return an error if .devbox/gen/flake is missing - // TODO: Remove this if it's not needed. - _ = nix.FlakeUpdate(shellgen.FlakePath(d)) - - // fix any missing store paths. - if err = d.FixMissingStorePaths(ctx); err != nil { - return errors.WithStack(err) + // With --no-install we only refresh the lockfile, so skip every step that + // shells out to Nix. This keeps `devbox update --no-install` usable in + // environments where Nix isn't fully set up (e.g. CI/Renovate), where + // running "nix flake update" or "nix path-info" would otherwise fail. + // See jetify-com/devbox#2585. + if !opts.NoInstall { + // I'm not entirely sure this is even needed, so ignoring the error. + // It's definitely not needed for non-flakes. (which is 99.9% of packages) + // It will return an error if .devbox/gen/flake is missing + // TODO: Remove this if it's not needed. + _ = nix.FlakeUpdate(shellgen.FlakePath(d)) + + // fix any missing store paths. + if err = d.FixMissingStorePaths(ctx); err != nil { + return errors.WithStack(err) + } } return plugin.Update() diff --git a/testscripts/update/update.test.txt b/testscripts/update/update.test.txt index 8c9169df8af..a63c8a155d4 100644 --- a/testscripts/update/update.test.txt +++ b/testscripts/update/update.test.txt @@ -4,6 +4,11 @@ exec devbox install exec devbox update +# `devbox update --no-install` only refreshes the lockfile and must not shell +# out to Nix (e.g. "nix flake update"). Regression test for #2585. +exec devbox update --no-install +! stderr 'nix flake update' + -- devbox.json -- { "packages": [ From be2ea109f8d9af67261739de687f7530a5f12bcb Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 14:15:38 +0000 Subject: [PATCH 2/2] docs(update): clarify --no-install comments per review Reword the code and testscript comments to describe exactly the two post-update Nix steps that --no-install skips (nix flake update and nix path-info), rather than implying the whole update flow avoids Nix. Flake-ref resolution earlier in the flow may still invoke Nix. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01Gtqrm1XgX3ZvcjHCJjuBgt --- internal/devbox/update.go | 12 +++++++----- testscripts/update/update.test.txt | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/internal/devbox/update.go b/internal/devbox/update.go index 7ab2578b0d8..5b991ae25a7 100644 --- a/internal/devbox/update.go +++ b/internal/devbox/update.go @@ -85,11 +85,13 @@ func (d *Devbox) Update(ctx context.Context, opts devopt.UpdateOpts) error { return err } - // With --no-install we only refresh the lockfile, so skip every step that - // shells out to Nix. This keeps `devbox update --no-install` usable in - // environments where Nix isn't fully set up (e.g. CI/Renovate), where - // running "nix flake update" or "nix path-info" would otherwise fail. - // See jetify-com/devbox#2585. + // With --no-install, skip the two post-update steps that shell out to Nix: + // "nix flake update" (via FlakeUpdate) and "nix path-info" (via + // FixMissingStorePaths). This keeps `devbox update --no-install` usable in + // environments where Nix isn't fully set up (e.g. CI/Renovate), where those + // calls would otherwise fail. Earlier steps in the update flow may still + // resolve flake refs via Nix; --no-install only avoids these install-like + // steps. See jetify-com/devbox#2585. if !opts.NoInstall { // I'm not entirely sure this is even needed, so ignoring the error. // It's definitely not needed for non-flakes. (which is 99.9% of packages) diff --git a/testscripts/update/update.test.txt b/testscripts/update/update.test.txt index a63c8a155d4..156db22ae3d 100644 --- a/testscripts/update/update.test.txt +++ b/testscripts/update/update.test.txt @@ -4,8 +4,8 @@ exec devbox install exec devbox update -# `devbox update --no-install` only refreshes the lockfile and must not shell -# out to Nix (e.g. "nix flake update"). Regression test for #2585. +# `devbox update --no-install` must not run the post-update "nix flake update" +# step. Regression test for #2585. exec devbox update --no-install ! stderr 'nix flake update'