gitmote / internal / runner / act_test.go · history · branches
3580 bytes · raw
package runner
import (
"slices"
"strings"
"testing"
)
func TestActArgsForwardsSecrets(t *testing.T) {
args, extra := actArgs(".gitmote/workflows", []string{
"PATH=/usr/bin",
"GITMOTE_CI_SECRET_API_TOKEN=s3cr3t",
"GITMOTE_URL=http://x", // not a secret; must be ignored
})
if !slices.Contains(extra, "API_TOKEN=s3cr3t") {
t.Errorf("extraEnv = %v, want the bare-named secret re-exported", extra)
}
if !hasFlag(args, "-s", "API_TOKEN") {
t.Errorf("args = %v, want -s API_TOKEN", args)
}
// The secret value must not appear on the argv.
if slices.ContainsFunc(args, func(s string) bool { return strings.Contains(s, "s3cr3t") }) {
t.Errorf("secret value leaked onto argv: %v", args)
}
}
func TestActArgsPlatforms(t *testing.T) {
args, _ := actArgs(".gitmote/workflows", []string{
"GITMOTE_ACT_PLATFORMS=ubuntu-latest=-self-hosted, ubuntu-22.04=-self-hosted",
})
if !hasFlag(args, "-P", "ubuntu-latest=-self-hosted") ||
!hasFlag(args, "-P", "ubuntu-22.04=-self-hosted") {
t.Errorf("args = %v, want a -P per platform mapping (trimmed)", args)
}
}
func TestActArgsDefaultsNoOverrides(t *testing.T) {
args, extra := actArgs(".gitmote/workflows", []string{"HOME=/root"})
if len(extra) != 0 {
t.Errorf("extraEnv = %v, want none", extra)
}
// No -s, no -P (local dev: act's default nesting).
if hasFlag(args, "-P", "") || slices.Contains(args, "-s") {
t.Errorf("args = %v, want no secret/platform overrides", args)
}
// Safe default: nested mode without an opt-in suppresses the daemon-socket
// mount so untrusted workflow code can't reach the host daemon.
if !hasFlag(args, "--container-daemon-socket", "-") {
t.Errorf("args = %v, want --container-daemon-socket - by default", args)
}
}
func TestActArgsAllowBuildsMountsDaemonSocket(t *testing.T) {
args, _ := actArgs(".gitmote/workflows", []string{"GITMOTE_CI_ALLOW_BUILDS=1"})
// Opted in: mount the daemon's own socket path (not act's DOCKER_HOST-derived
// default, which breaks for a VM-backed daemon) so `docker build` reaches it.
if !hasFlag(args, "--container-daemon-socket", "/var/run/docker.sock") {
t.Errorf("args = %v, want --container-daemon-socket /var/run/docker.sock when builds are allowed", args)
}
}
func TestActArgsDaemonSocketOverride(t *testing.T) {
args, _ := actArgs(".gitmote/workflows", []string{
"GITMOTE_CI_ALLOW_BUILDS=1",
"GITMOTE_ACT_DAEMON_SOCKET=/run/user/1000/docker.sock",
})
if !hasFlag(args, "--container-daemon-socket", "/run/user/1000/docker.sock") {
t.Errorf("args = %v, want the overridden daemon socket path", args)
}
}
func TestActArgsAllowBuildsFalseSuppressesSocket(t *testing.T) {
args, _ := actArgs(".gitmote/workflows", []string{"GITMOTE_CI_ALLOW_BUILDS=false"})
if !hasFlag(args, "--container-daemon-socket", "-") {
t.Errorf("args = %v, want the socket suppressed when builds are explicitly false", args)
}
}
func TestActArgsSelfHostedOmitsSocketFlag(t *testing.T) {
// Self-hosted has no job container to mount into, so the socket flag is moot
// and must not be emitted (it would be meaningless / could error).
args, _ := actArgs(".gitmote/workflows", []string{
"GITMOTE_ACT_PLATFORMS=ubuntu-latest=-self-hosted",
})
if slices.Contains(args, "--container-daemon-socket") {
t.Errorf("args = %v, want no socket flag in self-hosted mode", args)
}
}
// hasFlag reports whether args contains flag immediately followed by value.
func hasFlag(args []string, flag, value string) bool {
for i := 0; i+1 < len(args); i++ {
if args[i] == flag && args[i+1] == value {
return true
}
}
return false
}