Skip to content

Commit 85f832e

Browse files
authored
[update] Show warning for legacy packages and fix with update (#1107)
## Summary Add warning if devbox.json contains legacy packages. Fix them with update command. Update will turn legacy packages to `<pkg>@latest` and resolve them to current hash. This guarantees version will not change. If they run update again, it will update to newest version. ## How was it tested? <img width="840" alt="image" src="https://github.com/jetpack-io/devbox/assets/544948/fe612548-356a-4ed5-810a-78a3942913d1"> ```bash # modified devbox.json to have `curl` package. devbox update ``` Inspected devbox.json and devbox.lock and verified it was now `curl@latest`
1 parent 0ac23f5 commit 85f832e

File tree

13 files changed

+136
-44
lines changed

13 files changed

+136
-44
lines changed

devbox.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ type Devbox interface {
3434
ListScripts() []string
3535
PrintEnv(ctx context.Context, includeHooks bool) (string, error)
3636
PrintGlobalList() error
37-
PrintEnvrcContent(w io.Writer) error
3837
Pull(ctx context.Context, overwrite bool, path string) error
3938
Push(url string) error
4039
// Remove removes Nix packages from the config so that it no longer exists in
@@ -58,7 +57,11 @@ type Devbox interface {
5857

5958
// Open opens a devbox by reading the config file in dir.
6059
func Open(dir string, writer io.Writer) (Devbox, error) {
61-
return impl.Open(dir, writer)
60+
return impl.Open(dir, writer, true)
61+
}
62+
63+
func OpenWithoutWarnings(dir string, writer io.Writer) (Devbox, error) {
64+
return impl.Open(dir, writer, false)
6265
}
6366

6467
// InitConfig creates a default devbox config file if one doesn't already exist.
@@ -69,3 +72,7 @@ func InitConfig(dir string, writer io.Writer) (bool, error) {
6972
func GlobalDataPath() (string, error) {
7073
return impl.GlobalDataPath()
7174
}
75+
76+
func PrintEnvrcContent(w io.Writer) error {
77+
return impl.PrintEnvrcContent(w)
78+
}

internal/boxcli/featureflag/autolatest.go

Lines changed: 0 additions & 3 deletions
This file was deleted.

internal/boxcli/generate.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func direnvCmd() *cobra.Command {
9292
"Requires direnv to be installed.",
9393
Args: cobra.MaximumNArgs(0),
9494
RunE: func(cmd *cobra.Command, args []string) error {
95-
return runGenerateCmd(cmd, flags)
95+
return runGenerateDirenvCmd(cmd, flags)
9696
},
9797
}
9898
command.Flags().BoolVarP(
@@ -140,11 +140,19 @@ func runGenerateCmd(cmd *cobra.Command, flags *generateCmdFlags) error {
140140
return box.GenerateDevcontainer(flags.force)
141141
case "dockerfile":
142142
return box.GenerateDockerfile(flags.force)
143-
case "direnv":
144-
if flags.printEnvrcContent {
145-
return box.PrintEnvrcContent(cmd.OutOrStdout())
146-
}
147-
return box.GenerateEnvrcFile(flags.force)
148143
}
149144
return nil
150145
}
146+
147+
func runGenerateDirenvCmd(cmd *cobra.Command, flags *generateCmdFlags) error {
148+
if flags.printEnvrcContent {
149+
return devbox.PrintEnvrcContent(cmd.OutOrStdout())
150+
}
151+
152+
box, err := devbox.Open(flags.config.path, cmd.ErrOrStderr())
153+
if err != nil {
154+
return errors.WithStack(err)
155+
}
156+
157+
return box.GenerateEnvrcFile(flags.force)
158+
}

internal/boxcli/midcobra/telemetry.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ func getPackagesAndCommitHash(c *cobra.Command) ([]string, string) {
222222
path = configFlag.Value.String()
223223
}
224224

225-
box, err := devbox.Open(path, os.Stdout)
225+
box, err := devbox.OpenWithoutWarnings(path, os.Stdout)
226226
if err != nil {
227227
return []string{}, ""
228228
}

internal/boxcli/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func runCmd() *cobra.Command {
4444
}
4545

4646
func listScripts(cmd *cobra.Command, flags runCmdFlags) []string {
47-
box, err := devbox.Open(flags.config.path, cmd.ErrOrStderr())
47+
box, err := devbox.OpenWithoutWarnings(flags.config.path, cmd.ErrOrStderr())
4848
if err != nil {
4949
debug.Log("failed to open devbox: %v", err)
5050
return nil

internal/boxcli/shellenv.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
type shellEnvCmdFlags struct {
1414
config configFlags
1515
runInitHook bool
16+
install bool
1617
useCachedPrintDevEnv bool
1718
}
1819

@@ -36,6 +37,8 @@ func shellEnvCmd() *cobra.Command {
3637

3738
command.Flags().BoolVar(
3839
&flags.runInitHook, "init-hook", false, "runs init hook after exporting shell environment")
40+
command.Flags().BoolVar(
41+
&flags.install, "install", false, "install packages before exporting shell environment")
3942

4043
// This is no longer used. Remove after 0.4.8 is released.
4144
command.Flags().BoolVar(
@@ -56,6 +59,12 @@ func shellEnvFunc(cmd *cobra.Command, flags shellEnvCmdFlags) (string, error) {
5659
return "", err
5760
}
5861

62+
if flags.install {
63+
if err := box.Install(cmd.Context()); err != nil {
64+
return "", err
65+
}
66+
}
67+
5968
envStr, err := box.PrintEnv(cmd.Context(), flags.runInitHook)
6069
if err != nil {
6170
return "", err

internal/boxcli/update.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ func updateCmd() *cobra.Command {
2222
Short: "Update packages in your devbox",
2323
Long: "Update one, many, or all packages in your devbox. " +
2424
"If no packages are specified, all packages will be updated. " +
25-
"Only update versioned packages (e.g. `python@3.11`), not packages that are pinned to a nix channel (e.g. `python3`)",
25+
"Legacy non-versioned packages will be converted to @latest versioned " +
26+
"packages resolved to their current version.",
2627
PreRunE: ensureNixInstalled,
2728
RunE: func(cmd *cobra.Command, args []string) error {
2829
return updateCmdFunc(cmd, args, flags)

internal/impl/devbox.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ type Devbox struct {
7070
writer io.Writer
7171
}
7272

73-
func Open(path string, writer io.Writer) (*Devbox, error) {
73+
var legacyPackagesWarningHasBeenShown = false
74+
75+
func Open(path string, writer io.Writer, showWarnings bool) (*Devbox, error) {
7476
projectDir, err := findProjectDir(path)
7577
if err != nil {
7678
return nil, err
@@ -98,6 +100,18 @@ func Open(path string, writer io.Writer) (*Devbox, error) {
98100
plugin.WithLockfile(lock),
99101
)
100102
box.lockfile = lock
103+
104+
if showWarnings &&
105+
!legacyPackagesWarningHasBeenShown &&
106+
box.HasDeprecatedPackages() {
107+
legacyPackagesWarningHasBeenShown = true
108+
ux.Fwarning(
109+
os.Stderr, // Always stderr. box.writer should probably always be err.
110+
"Your devbox.json contains packages in legacy format. "+
111+
"Please run `devbox update` to update your devbox.json.\n",
112+
)
113+
}
114+
101115
return box, nil
102116
}
103117

@@ -395,7 +409,7 @@ func (d *Devbox) GenerateDockerfile(force bool) error {
395409
return errors.WithStack(generate.CreateDockerfile(tmplFS, d.projectDir, false /* isDevcontainer */))
396410
}
397411

398-
func (d *Devbox) PrintEnvrcContent(w io.Writer) error {
412+
func PrintEnvrcContent(w io.Writer) error {
399413
tmplName := "envrcContent.tmpl"
400414
t := template.Must(template.ParseFS(tmplFS, "tmpl/"+tmplName))
401415
// write content into file
@@ -977,6 +991,15 @@ func (d *Devbox) packagesAsInputs() []*nix.Input {
977991
return nix.InputsFromStrings(d.Packages(), d.lockfile)
978992
}
979993

994+
func (d *Devbox) HasDeprecatedPackages() bool {
995+
for _, pkg := range d.packagesAsInputs() {
996+
if pkg.IsLegacy() {
997+
return true
998+
}
999+
}
1000+
return false
1001+
}
1002+
9801003
func (d *Devbox) findPackageByName(name string) (string, error) {
9811004
results := map[string]bool{}
9821005
for _, pkg := range d.cfg.Packages {

internal/impl/devbox_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func testShellPlan(t *testing.T, testPath string) {
4141
t.Setenv(envir.XDGDataHome, "/tmp/devbox")
4242
assert := assert.New(t)
4343

44-
_, err := Open(baseDir, os.Stdout)
44+
_, err := Open(baseDir, os.Stdout, true)
4545
assert.NoErrorf(err, "%s should be a valid devbox project", baseDir)
4646
})
4747
}
@@ -65,7 +65,7 @@ func TestComputeNixEnv(t *testing.T) {
6565
path := t.TempDir()
6666
_, err := devconfig.Init(path, os.Stdout)
6767
require.NoError(t, err, "InitConfig should not fail")
68-
d, err := Open(path, os.Stdout)
68+
d, err := Open(path, os.Stdout, true)
6969
require.NoError(t, err, "Open should not fail")
7070
d.nix = &testNix{}
7171
ctx := context.Background()
@@ -78,7 +78,7 @@ func TestComputeNixPathIsIdempotent(t *testing.T) {
7878
dir := t.TempDir()
7979
_, err := devconfig.Init(dir, os.Stdout)
8080
require.NoError(t, err, "InitConfig should not fail")
81-
devbox, err := Open(dir, os.Stdout)
81+
devbox, err := Open(dir, os.Stdout, true)
8282
require.NoError(t, err, "Open should not fail")
8383
devbox.nix = &testNix{"/tmp/my/path"}
8484
ctx := context.Background()
@@ -104,7 +104,7 @@ func TestComputeNixPathWhenRemoving(t *testing.T) {
104104
dir := t.TempDir()
105105
_, err := devconfig.Init(dir, os.Stdout)
106106
require.NoError(t, err, "InitConfig should not fail")
107-
devbox, err := Open(dir, os.Stdout)
107+
devbox, err := Open(dir, os.Stdout, true)
108108
require.NoError(t, err, "Open should not fail")
109109
devbox.nix = &testNix{"/tmp/my/path"}
110110
ctx := context.Background()

internal/impl/tmpl/envrcContent.tmpl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use_devbox() {
22
watch_file devbox.json
3-
eval "$(devbox shellenv --init-hook)"
4-
devbox install
3+
eval "$(devbox shellenv --init-hook --install)"
54
}
65
use devbox

0 commit comments

Comments
 (0)