diff --git a/core/integration/container_test.go b/core/integration/container_test.go index 36ef300efb..36a9f12531 100644 --- a/core/integration/container_test.go +++ b/core/integration/container_test.go @@ -1090,7 +1090,16 @@ func TestContainerWithEnvVariableExpand(t *testing.T) { t.Run("add env var without expansion", func(t *testing.T) { out, err := c.Container(). From(alpineImage). - WithEnvVariable("FOO", "foo:$PATH"). + WithEnvVariable("FOO", "foo:$PATH", dagger.ContainerWithEnvVariableOpts{Expand: false, NoExpand: true}). + WithExec([]string{"printenv", "FOO"}). + Stdout(ctx) + + require.NoError(t, err) + require.Equal(t, "foo:$PATH\n", out) + + out, err = c.Container(). + From(alpineImage). + WithEnvVariable("FOO", "foo:$PATH", dagger.ContainerWithEnvVariableOpts{NoExpand: true}). WithExec([]string{"printenv", "FOO"}). Stdout(ctx) @@ -1099,24 +1108,63 @@ func TestContainerWithEnvVariableExpand(t *testing.T) { }) t.Run("add env var with expansion", func(t *testing.T) { - out, err := c.Container(). + expected := "/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n" + + ctr := c.Container(). From(alpineImage). - WithEnvVariable("USER_PATH", "/opt"). + WithEnvVariable("USER_PATH", "/opt") + + out, err := ctr. + WithEnvVariable( + "PATH", + "${USER_PATH}/bin:$PATH", + dagger.ContainerWithEnvVariableOpts{ + Expand: true, + NoExpand: true, + }, + ). + WithExec([]string{"printenv", "PATH"}). + Stdout(ctx) + + require.NoError(t, err) + require.Equal(t, expected, out) + + out, err = ctr. + WithEnvVariable( + "PATH", + "${USER_PATH}/bin:$PATH", + dagger.ContainerWithEnvVariableOpts{ + NoExpand: false, + }, + ). + WithExec([]string{"printenv", "PATH"}). + Stdout(ctx) + + require.NoError(t, err) + require.Equal(t, expected, out) + + out, err = ctr. + WithEnvVariable("PATH", "${USER_PATH}/bin:$PATH"). + WithExec([]string{"printenv", "PATH"}). + Stdout(ctx) + + require.NoError(t, err) + require.Equal(t, expected, out) + + out, err = ctr. WithEnvVariable( "PATH", "${USER_PATH}/bin:$PATH", dagger.ContainerWithEnvVariableOpts{ - Expand: true, + Expand: true, + NoExpand: true, }, ). WithExec([]string{"printenv", "PATH"}). Stdout(ctx) require.NoError(t, err) - require.Equal(t, - "/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n", - out, - ) + require.Equal(t, expected, out) }) } diff --git a/core/schema/container.go b/core/schema/container.go index e43a829c33..f5b35763a3 100644 --- a/core/schema/container.go +++ b/core/schema/container.go @@ -117,10 +117,11 @@ func (s *containerSchema) Install() { Doc(`Retrieves this container plus the given environment variable.`). ArgDoc("name", `The name of the environment variable (e.g., "HOST").`). ArgDoc("value", `The value of the environment variable. (e.g., "localhost").`). - ArgDoc("expand", - "Replace `${VAR}` or `$VAR` in the value according to the current "+ + ArgDoc("noExpand", + "Do not replace `${VAR}` or `$VAR` in the value according to the current "+ `environment variables defined in the container (e.g., - "/opt/bin:$PATH").`), + "/opt/bin:$PATH").`). + ArgDeprecated("expand", "The environment variable will be expand by default."), dagql.Func("withSecretVariable", s.withSecretVariable). Doc(`Retrieves this container plus an env variable containing the given secret.`). @@ -725,16 +726,17 @@ func (s *containerSchema) workdir(ctx context.Context, parent *core.Container, a } type containerWithVariableArgs struct { - Name string - Value string - Expand bool `default:"false"` + Name string + Value string + Expand bool `default:"false"` + NoExpand bool `default:"false"` } func (s *containerSchema) withEnvVariable(ctx context.Context, parent *core.Container, args containerWithVariableArgs) (*core.Container, error) { return parent.UpdateImageConfig(ctx, func(cfg specs.ImageConfig) specs.ImageConfig { value := args.Value - if args.Expand { + if !args.NoExpand || args.Expand { value = os.Expand(value, func(k string) string { v, _ := core.LookupEnv(cfg.Env, k) return v diff --git a/docs/docs-graphql/schema.graphqls b/docs/docs-graphql/schema.graphqls index d9297fff63..ba69f41a79 100644 --- a/docs/docs-graphql/schema.graphqls +++ b/docs/docs-graphql/schema.graphqls @@ -441,15 +441,18 @@ type Container { """Retrieves this container plus the given environment variable.""" withEnvVariable( - """ - Replace `${VAR}` or `$VAR` in the value according to the current environment - variables defined in the container (e.g., "/opt/bin:$PATH"). - """ + """DEPRECATED: The environment variable will be expand by default.""" expand: Boolean = false """The name of the environment variable (e.g., "HOST").""" name: String! + """ + Do not replace `${VAR}` or `$VAR` in the value according to the current + environment variables defined in the container (e.g., "/opt/bin:$PATH"). + """ + noExpand: Boolean = false + """The value of the environment variable. (e.g., "localhost").""" value: String! ): Container! diff --git a/sdk/elixir/lib/dagger/gen/container.ex b/sdk/elixir/lib/dagger/gen/container.ex index 25ae50708d..2ca413b0b6 100644 --- a/sdk/elixir/lib/dagger/gen/container.ex +++ b/sdk/elixir/lib/dagger/gen/container.ex @@ -547,8 +547,10 @@ defmodule Dagger.Container do end @doc "Retrieves this container plus the given environment variable." - @spec with_env_variable(t(), String.t(), String.t(), [{:expand, boolean() | nil}]) :: - Dagger.Container.t() + @spec with_env_variable(t(), String.t(), String.t(), [ + {:expand, boolean() | nil}, + {:no_expand, boolean() | nil} + ]) :: Dagger.Container.t() def with_env_variable(%__MODULE__{} = container, name, value, optional_args \\ []) do selection = container.selection @@ -556,6 +558,7 @@ defmodule Dagger.Container do |> put_arg("name", name) |> put_arg("value", value) |> maybe_put_arg("expand", optional_args[:expand]) + |> maybe_put_arg("noExpand", optional_args[:no_expand]) %Dagger.Container{ selection: selection, diff --git a/sdk/go/dagger.gen.go b/sdk/go/dagger.gen.go index 3dcc03fa2c..795457624f 100644 --- a/sdk/go/dagger.gen.go +++ b/sdk/go/dagger.gen.go @@ -1064,8 +1064,10 @@ func (r *Container) WithEntrypoint(args []string, opts ...ContainerWithEntrypoin // ContainerWithEnvVariableOpts contains options for Container.WithEnvVariable type ContainerWithEnvVariableOpts struct { - // Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). + // DEPRECATED: The environment variable will be expand by default. Expand bool + // Do not replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). + NoExpand bool } // Retrieves this container plus the given environment variable. @@ -1076,6 +1078,10 @@ func (r *Container) WithEnvVariable(name string, value string, opts ...Container if !querybuilder.IsZeroValue(opts[i].Expand) { q = q.Arg("expand", opts[i].Expand) } + // `noExpand` optional argument + if !querybuilder.IsZeroValue(opts[i].NoExpand) { + q = q.Arg("noExpand", opts[i].NoExpand) + } } q = q.Arg("name", name) q = q.Arg("value", value) diff --git a/sdk/php/generated/Container.php b/sdk/php/generated/Container.php index e45032d603..b668706559 100644 --- a/sdk/php/generated/Container.php +++ b/sdk/php/generated/Container.php @@ -468,7 +468,12 @@ public function withEntrypoint(array $args, ?bool $keepDefaultArgs = false): Con /** * Retrieves this container plus the given environment variable. */ - public function withEnvVariable(string $name, string $value, ?bool $expand = false): Container + public function withEnvVariable( + string $name, + string $value, + ?bool $expand = false, + ?bool $noExpand = false, + ): Container { $innerQueryBuilder = new \Dagger\Client\QueryBuilder('withEnvVariable'); $innerQueryBuilder->setArgument('name', $name); @@ -476,6 +481,9 @@ public function withEnvVariable(string $name, string $value, ?bool $expand = fal if (null !== $expand) { $innerQueryBuilder->setArgument('expand', $expand); } + if (null !== $noExpand) { + $innerQueryBuilder->setArgument('noExpand', $noExpand); + } return new \Dagger\Container($this->client, $this->queryBuilderChain->chain($innerQueryBuilder)); } diff --git a/sdk/python/src/dagger/client/gen.py b/sdk/python/src/dagger/client/gen.py index 5586af6b11..80508dfaaf 100644 --- a/sdk/python/src/dagger/client/gen.py +++ b/sdk/python/src/dagger/client/gen.py @@ -1203,6 +1203,7 @@ def with_env_variable( value: str, *, expand: bool | None = False, + no_expand: bool | None = False, ) -> Self: """Retrieves this container plus the given environment variable. @@ -1213,14 +1214,17 @@ def with_env_variable( value: The value of the environment variable. (e.g., "localhost"). expand: - Replace `${VAR}` or `$VAR` in the value according to the current - environment variables defined in the container (e.g., + DEPRECATED: The environment variable will be expand by default. + no_expand: + Do not replace `${VAR}` or `$VAR` in the value according to the + current environment variables defined in the container (e.g., "/opt/bin:$PATH"). """ _args = [ Arg("name", name), Arg("value", value), Arg("expand", expand, False), + Arg("noExpand", no_expand, False), ] _ctx = self._select("withEnvVariable", _args) return Container(_ctx) diff --git a/sdk/rust/crates/dagger-sdk/src/gen.rs b/sdk/rust/crates/dagger-sdk/src/gen.rs index 78e17d9257..6c5bf4561b 100644 --- a/sdk/rust/crates/dagger-sdk/src/gen.rs +++ b/sdk/rust/crates/dagger-sdk/src/gen.rs @@ -1346,9 +1346,12 @@ pub struct ContainerWithEntrypointOpts { } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithEnvVariableOpts { - /// Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). + /// DEPRECATED: The environment variable will be expand by default. #[builder(setter(into, strip_option), default)] pub expand: Option, + /// Do not replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). + #[builder(setter(into, strip_option), default)] + pub no_expand: Option, } #[derive(Builder, Debug, PartialEq)] pub struct ContainerWithExecOpts<'a> { @@ -2202,6 +2205,9 @@ impl Container { if let Some(expand) = opts.expand { query = query.arg("expand", expand); } + if let Some(no_expand) = opts.no_expand { + query = query.arg("noExpand", no_expand); + } Container { proc: self.proc.clone(), selection: query, diff --git a/sdk/typescript/api/client.gen.ts b/sdk/typescript/api/client.gen.ts index 2cf9f95553..f0232eca1c 100644 --- a/sdk/typescript/api/client.gen.ts +++ b/sdk/typescript/api/client.gen.ts @@ -260,9 +260,14 @@ export type ContainerWithEntrypointOpts = { export type ContainerWithEnvVariableOpts = { /** - * Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). + * DEPRECATED: The environment variable will be expand by default. */ expand?: boolean + + /** + * Do not replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). + */ + noExpand?: boolean } export type ContainerWithExecOpts = { @@ -1978,7 +1983,8 @@ export class Container extends BaseClient { * Retrieves this container plus the given environment variable. * @param name The name of the environment variable (e.g., "HOST"). * @param value The value of the environment variable. (e.g., "localhost"). - * @param opts.expand Replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). + * @param opts.expand DEPRECATED: The environment variable will be expand by default. + * @param opts.noExpand Do not replace `${VAR}` or `$VAR` in the value according to the current environment variables defined in the container (e.g., "/opt/bin:$PATH"). */ withEnvVariable = ( name: string,