forked from wrenn/wrenn
feat: add env expansion, sandbox env fetching, and configurable
healthchecks Fix ENV instructions to expand $VAR references at set time using the current env state, preventing self-referencing values like PATH=/opt/venv/bin:$PATH from producing recursive expansions. Remove expandEnv from shellPrefix to avoid double expansion. Fetch sandbox environment variables via `env` before recipe execution so ENV steps resolve against actual runtime values from the base template image. Replace hardcoded healthcheck timing with a Dockerfile-like flag parser supporting --interval, --timeout, --start-period, and --retries. Add start-period grace window and bounded retry counting to waitForHealthcheck. Add python-interpreter-v0-beta recipe and healthcheck files.
This commit is contained in:
@ -45,6 +45,14 @@ func TestExecContext_WrappedCommand(t *testing.T) {
|
||||
cmd: "echo $MSG",
|
||||
want: "MSG='it'\\''s fine' /bin/sh -c 'echo $MSG'",
|
||||
},
|
||||
{
|
||||
name: "env expansion with dollar sign PATH",
|
||||
ctx: ExecContext{
|
||||
EnvVars: map[string]string{"PATH": "/usr/bin", "FOO": "/opt/venv/bin:$PATH"},
|
||||
},
|
||||
cmd: "make build",
|
||||
want: "FOO='/opt/venv/bin:/usr/bin' PATH='/usr/bin' /bin/sh -c 'make build'",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
@ -94,6 +102,109 @@ func TestExecContext_StartCommand(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandEnv(t *testing.T) {
|
||||
tests := []struct {
|
||||
s string
|
||||
vars map[string]string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
s: "hello",
|
||||
vars: nil,
|
||||
want: "hello",
|
||||
},
|
||||
{
|
||||
s: "$PATH",
|
||||
vars: map[string]string{"PATH": "/usr/bin"},
|
||||
want: "/usr/bin",
|
||||
},
|
||||
{
|
||||
s: "${PATH}",
|
||||
vars: map[string]string{"PATH": "/usr/bin"},
|
||||
want: "/usr/bin",
|
||||
},
|
||||
{
|
||||
s: "/opt/venv/bin:$PATH",
|
||||
vars: map[string]string{"PATH": "/usr/bin"},
|
||||
want: "/opt/venv/bin:/usr/bin",
|
||||
},
|
||||
{
|
||||
s: "${HOME}/code",
|
||||
vars: map[string]string{"HOME": "/root"},
|
||||
want: "/root/code",
|
||||
},
|
||||
{
|
||||
s: "hello $USER",
|
||||
vars: map[string]string{"USER": "admin"},
|
||||
want: "hello admin",
|
||||
},
|
||||
{
|
||||
s: "$UNSET",
|
||||
vars: map[string]string{"PATH": "/usr/bin"},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
s: "${UNSET}",
|
||||
vars: map[string]string{"PATH": "/usr/bin"},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
s: "$$",
|
||||
vars: map[string]string{"PATH": "/usr/bin"},
|
||||
want: "$",
|
||||
},
|
||||
{
|
||||
s: "price is $$100",
|
||||
vars: nil,
|
||||
want: "price is $100",
|
||||
},
|
||||
{
|
||||
s: "$FOO:$BAR",
|
||||
vars: map[string]string{"FOO": "a", "BAR": "b"},
|
||||
want: "a:b",
|
||||
},
|
||||
{
|
||||
s: "${FOO}_${BAR}",
|
||||
vars: map[string]string{"FOO": "hello", "BAR": "world"},
|
||||
want: "hello_world",
|
||||
},
|
||||
{
|
||||
s: "no vars here",
|
||||
vars: nil,
|
||||
want: "no vars here",
|
||||
},
|
||||
{
|
||||
s: "$",
|
||||
vars: nil,
|
||||
want: "$",
|
||||
},
|
||||
{
|
||||
s: "${",
|
||||
vars: nil,
|
||||
want: "${",
|
||||
},
|
||||
{
|
||||
s: "${}",
|
||||
vars: nil,
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
s: "$VAR1$VAR2",
|
||||
vars: map[string]string{"VAR1": "a", "VAR2": "b"},
|
||||
want: "ab",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.s, func(t *testing.T) {
|
||||
got := expandEnv(tc.s, tc.vars)
|
||||
if got != tc.want {
|
||||
t.Errorf("expandEnv(%q, %v)\n got %q\n want %q", tc.s, tc.vars, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellescape(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
|
||||
Reference in New Issue
Block a user