1
0
forked from wrenn/wrenn
Files
wrenn-releases/internal/recipe/context_test.go
pptx704 948db13bed Add skip_pre_post build option, cancel endpoint, and recipe package
- skip_pre_post flag on builds bypasses apt update/clean pre/post steps for
  faster iteration when the recipe handles its own environment setup
- POST /v1/admin/builds/{id}/cancel endpoint marks an in-progress build as
  cancelled; UpdateBuildStatus now also sets completed_at for 'cancelled'
- internal/recipe: typed recipe parser and executor (RUN/ENV/COPY steps)
  replacing the raw string slice approach in the build worker
- pre/post build commands prefixed with RUN to match recipe step format
2026-03-30 21:24:52 +06:00

115 lines
2.6 KiB
Go

package recipe
import "testing"
func TestExecContext_WrappedCommand(t *testing.T) {
tests := []struct {
name string
ctx ExecContext
cmd string
want string
}{
{
name: "no context",
ctx: ExecContext{},
cmd: "apt install -y curl",
want: "apt install -y curl",
},
{
name: "workdir only",
ctx: ExecContext{WorkDir: "/app"},
cmd: "npm install",
want: "cd '/app' && /bin/sh -c 'npm install'",
},
{
name: "env only",
ctx: ExecContext{EnvVars: map[string]string{"PORT": "8080"}},
cmd: "node server.js",
want: "PORT='8080' /bin/sh -c 'node server.js'",
},
{
name: "workdir with space",
ctx: ExecContext{WorkDir: "/my project"},
cmd: "make build",
want: "cd '/my project' && /bin/sh -c 'make build'",
},
{
name: "command with single quotes",
ctx: ExecContext{WorkDir: "/app"},
cmd: "echo 'hello'",
want: "cd '/app' && /bin/sh -c 'echo '\\''hello'\\'''",
},
{
name: "env value with single quotes",
ctx: ExecContext{EnvVars: map[string]string{"MSG": "it's fine"}},
cmd: "echo $MSG",
want: "MSG='it'\\''s fine' /bin/sh -c 'echo $MSG'",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := tc.ctx.WrappedCommand(tc.cmd)
if got != tc.want {
t.Errorf("WrappedCommand(%q)\n got %q\n want %q", tc.cmd, got, tc.want)
}
})
}
}
func TestExecContext_StartCommand(t *testing.T) {
tests := []struct {
name string
ctx ExecContext
cmd string
want string
}{
{
name: "no context",
ctx: ExecContext{},
cmd: "python3 app.py",
want: "nohup /bin/sh -c 'python3 app.py' >/dev/null 2>&1 &",
},
{
name: "with workdir",
ctx: ExecContext{WorkDir: "/app"},
cmd: "python3 server.py",
want: "cd '/app' && nohup /bin/sh -c 'python3 server.py' >/dev/null 2>&1 &",
},
{
name: "with env",
ctx: ExecContext{EnvVars: map[string]string{"PORT": "9000"}},
cmd: "node index.js",
want: "PORT='9000' nohup /bin/sh -c 'node index.js' >/dev/null 2>&1 &",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := tc.ctx.StartCommand(tc.cmd)
if got != tc.want {
t.Errorf("StartCommand(%q)\n got %q\n want %q", tc.cmd, got, tc.want)
}
})
}
}
func TestShellescape(t *testing.T) {
tests := []struct {
input string
want string
}{
{"simple", "'simple'"},
{"/path/to/dir", "'/path/to/dir'"},
{"it's fine", "'it'\\''s fine'"},
{"", "''"},
{"a'b'c", "'a'\\''b'\\''c'"},
}
for _, tc := range tests {
got := shellescape(tc.input)
if got != tc.want {
t.Errorf("shellescape(%q) = %q, want %q", tc.input, got, tc.want)
}
}
}