diff --git a/cli/azd/cmd/container.go b/cli/azd/cmd/container.go index 2641e20898d..135109cca12 100644 --- a/cli/azd/cmd/container.go +++ b/cli/azd/cmd/container.go @@ -167,6 +167,7 @@ func registerCommonDependencies(container *ioc.NestedContainer) { container.RegisterSingleton( func(ctx context.Context, azdContext *azdcontext.AzdContext, + lazyEnv *lazy.Lazy[*environment.Environment], envFlags envFlag, console input.Console, ) (*environment.Environment, error) { @@ -182,6 +183,10 @@ func registerCommonDependencies(container *ioc.NestedContainer) { return nil, fmt.Errorf("loading environment: %w", err) } + // Reset lazy env value after loading or creating environment + // This allows any previous lazy instances (such as hooks) to now point to the same instance + lazyEnv.SetValue(env) + return env, nil }, ) diff --git a/cli/azd/pkg/environment/environment_test.go b/cli/azd/pkg/environment/environment_test.go index 5e1fe3ae5cb..bfb15bd445c 100644 --- a/cli/azd/pkg/environment/environment_test.go +++ b/cli/azd/pkg/environment/environment_test.go @@ -114,17 +114,16 @@ func Test_SaveAndReload(t *testing.T) { tempDir := t.TempDir() ostest.Chdir(t, tempDir) - env, err := FromRoot(tempDir) + env := EmptyWithRoot(tempDir) require.NotNil(t, env) - require.NoError(t, err) env.SetLocation("eastus2") env.SetSubscriptionId("SUBSCRIPTION_ID") - err = env.Save() + err := env.Save() require.NoError(t, err) - // Simulate another process updating the .env file + // Simulate another process writing to .env file envPath := filepath.Join(tempDir, azdcontext.DotEnvFileName) envMap, err := godotenv.Read(envPath) require.NotNil(t, envMap) @@ -135,6 +134,9 @@ func Test_SaveAndReload(t *testing.T) { err = godotenv.Write(envMap, envPath) require.NoError(t, err) + err = env.Reload() + require.NoError(t, err) + // Set a new property in the env env.SetServiceProperty("web", "ENDPOINT_URL", "http://web.example.com") err = env.Save() diff --git a/cli/azd/pkg/ext/hooks_runner.go b/cli/azd/pkg/ext/hooks_runner.go index 1d0702d065f..fdbc1c26478 100644 --- a/cli/azd/pkg/ext/hooks_runner.go +++ b/cli/azd/pkg/ext/hooks_runner.go @@ -83,16 +83,19 @@ func (h *HooksRunner) RunHooks(ctx context.Context, hookType HookType, commands return fmt.Errorf("failed running scripts for hooks '%s', %w", strings.Join(commands, ","), err) } - // Reload env vars before execution to enable support for hooks to generate new env vars between commands - if err := h.env.Reload(); err != nil { - return fmt.Errorf("failed reloading env values, %w", err) - } - for _, hookConfig := range hooks { + if err := h.env.Reload(); err != nil { + return fmt.Errorf("reloading environment before running hook: %w", err) + } + err := h.execHook(ctx, hookConfig) if err != nil { return err } + + if err := h.env.Reload(); err != nil { + return fmt.Errorf("reloading environment after running hook: %w", err) + } } return nil diff --git a/cli/azd/pkg/ext/hooks_runner_test.go b/cli/azd/pkg/ext/hooks_runner_test.go index 1d3afe42043..c815985bb93 100644 --- a/cli/azd/pkg/ext/hooks_runner_test.go +++ b/cli/azd/pkg/ext/hooks_runner_test.go @@ -60,7 +60,7 @@ func Test_Hooks_Execute(t *testing.T) { ranPreHook = true require.Equal(t, "scripts/precommand.sh", args.Args[0]) require.Equal(t, cwd, args.Cwd) - require.Equal(t, env.Environ(), args.Env) + require.ElementsMatch(t, env.Environ(), args.Env) require.Equal(t, false, args.Interactive) return exec.NewRunResult(0, "", ""), nil @@ -86,7 +86,7 @@ func Test_Hooks_Execute(t *testing.T) { ranPostHook = true require.Equal(t, "scripts/postcommand.sh", args.Args[0]) require.Equal(t, cwd, args.Cwd) - require.Equal(t, env.Environ(), args.Env) + require.ElementsMatch(t, env.Environ(), args.Env) require.Equal(t, false, args.Interactive) return exec.NewRunResult(0, "", ""), nil @@ -112,7 +112,7 @@ func Test_Hooks_Execute(t *testing.T) { ranPostHook = true require.Equal(t, "scripts/preinteractive.sh", args.Args[0]) require.Equal(t, cwd, args.Cwd) - require.Equal(t, env.Environ(), args.Env) + require.ElementsMatch(t, env.Environ(), args.Env) require.Equal(t, true, args.Interactive) return exec.NewRunResult(0, "", ""), nil