From 43922d55b069b159b0324efad869657c3f3c22e3 Mon Sep 17 00:00:00 2001 From: Yohta Kimura <38206553+rajyan@users.noreply.github.com> Date: Tue, 23 Jun 2026 10:29:09 +0900 Subject: [PATCH] Fix rawsetenv nil-pointer guard for inherit-from-shell env vars When a service declares an env var without a value (e.g. `- KEY` or `KEY:`), MappingWithEquals stores it as a nil *string. The previous condition `existing != nil && ...` skipped the warning for this case, allowing silent overwrites. Change to `existing == nil || ...` so the warning fires for both nil (shell-inherit) and value-mismatch cases. Add e2e tests for both list-style (`- KEY`) and map-style (`KEY:`) YAML forms to lock in the behavior. Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: Yohta Kimura <38206553+rajyan@users.noreply.github.com> --- pkg/compose/plugins.go | 2 +- .../providers/rawsetenv-inherit-map.yaml | 15 ++++++++ .../fixtures/providers/rawsetenv-inherit.yaml | 15 ++++++++ pkg/e2e/providers_test.go | 36 +++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 pkg/e2e/fixtures/providers/rawsetenv-inherit-map.yaml create mode 100644 pkg/e2e/fixtures/providers/rawsetenv-inherit.yaml diff --git a/pkg/compose/plugins.go b/pkg/compose/plugins.go index 504c31f62..ba75d0d56 100644 --- a/pkg/compose/plugins.go +++ b/pkg/compose/plugins.go @@ -94,7 +94,7 @@ func (s *composeService) runPlugin(ctx context.Context, project *types.Project, s.Environment[prefix+key] = &val } for key, val := range variables.raw { - if existing, ok := s.Environment[key]; ok && existing != nil && *existing != val { + if existing, ok := s.Environment[key]; ok && (existing == nil || *existing != val) { logrus.Warnf("provider %q overrides environment variable %q in service %q", service.Name, key, name) } s.Environment[key] = &val diff --git a/pkg/e2e/fixtures/providers/rawsetenv-inherit-map.yaml b/pkg/e2e/fixtures/providers/rawsetenv-inherit-map.yaml new file mode 100644 index 000000000..355dee17d --- /dev/null +++ b/pkg/e2e/fixtures/providers/rawsetenv-inherit-map.yaml @@ -0,0 +1,15 @@ +services: + test: + image: alpine + command: env + environment: + CLOUD_REGION: + depends_on: + - secrets + secrets: + provider: + type: example-provider + options: + name: secrets + type: test1 + size: 1 diff --git a/pkg/e2e/fixtures/providers/rawsetenv-inherit.yaml b/pkg/e2e/fixtures/providers/rawsetenv-inherit.yaml new file mode 100644 index 000000000..b8f729a4b --- /dev/null +++ b/pkg/e2e/fixtures/providers/rawsetenv-inherit.yaml @@ -0,0 +1,15 @@ +services: + test: + image: alpine + command: env + environment: + - CLOUD_REGION + depends_on: + - secrets + secrets: + provider: + type: example-provider + options: + name: secrets + type: test1 + size: 1 diff --git a/pkg/e2e/providers_test.go b/pkg/e2e/providers_test.go index 8b11720ce..b08139217 100644 --- a/pkg/e2e/providers_test.go +++ b/pkg/e2e/providers_test.go @@ -119,6 +119,42 @@ func TestProviderRawSetEnvOverridesUserEnv(t *testing.T) { assert.Check(t, strings.Contains(res.Combined(), "overrides environment variable"), res.Combined()) } +func TestProviderRawSetEnvOverridesInheritedEnv(t *testing.T) { + provider, err := findExecutable("example-provider") + assert.NilError(t, err) + + path := fmt.Sprintf("%s%s%s", os.Getenv("PATH"), string(os.PathListSeparator), filepath.Dir(provider)) + c := NewParallelCLI(t, WithEnv("PATH="+path)) + const projectName = "rawsetenv-inherit" + t.Cleanup(func() { + c.cleanupWithDown(t, projectName) + }) + + res := c.RunDockerComposeCmd(t, "-f", "fixtures/providers/rawsetenv-inherit.yaml", "--project-name", projectName, "up") + res.Assert(t, icmd.Success) + env := getEnv(res.Combined()) + assert.Check(t, slices.Contains(env, "CLOUD_REGION=us-east-1"), env) + assert.Check(t, strings.Contains(res.Combined(), "overrides environment variable"), res.Combined()) +} + +func TestProviderRawSetEnvOverridesInheritedEnvMapForm(t *testing.T) { + provider, err := findExecutable("example-provider") + assert.NilError(t, err) + + path := fmt.Sprintf("%s%s%s", os.Getenv("PATH"), string(os.PathListSeparator), filepath.Dir(provider)) + c := NewParallelCLI(t, WithEnv("PATH="+path)) + const projectName = "rawsetenv-inherit-map" + t.Cleanup(func() { + c.cleanupWithDown(t, projectName) + }) + + res := c.RunDockerComposeCmd(t, "-f", "fixtures/providers/rawsetenv-inherit-map.yaml", "--project-name", projectName, "up") + res.Assert(t, icmd.Success) + env := getEnv(res.Combined()) + assert.Check(t, slices.Contains(env, "CLOUD_REGION=us-east-1"), env) + assert.Check(t, strings.Contains(res.Combined(), "overrides environment variable"), res.Combined()) +} + func getEnv(out string) []string { var env []string scanner := bufio.NewScanner(strings.NewReader(out))