diff --git a/.github/workflows/CI.md b/.github/workflows/CI.md index 5612d3b7b..ba6df33e4 100644 --- a/.github/workflows/CI.md +++ b/.github/workflows/CI.md @@ -14,7 +14,6 @@ Run all tests with coverage reports. ```sh {"id":"01J5XTG2WKVR4WG7B2FNPF6VZT","name":"ci-coverage","promptEnv":"no"} unset RUNME_SESSION_STRATEGY RUNME_TLS_DIR RUNME_SERVER_ADDR -export SHELL="/bin/bash" export TZ="UTC" export TAGS="docker_enabled" make test/coverage @@ -25,7 +24,6 @@ Run txtar-based CLI e2e tests without coverage reports (Go's warnings are gettin ```sh {"id":"01JAJYWF198MWQXJBADFJVJGXM","name":"ci-txtar"} unset RUNME_SESSION_STRATEGY RUNME_TLS_DIR RUNME_SERVER_ADDR -export SHELL="/bin/bash" export TZ="UTC" export TAGS="test_with_txtar" export RUN="^TestRunme\w*" diff --git a/Makefile b/Makefile index da7c7b74d..6f4805eda 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,3 @@ -SHELL := /bin/bash - GO_ROOT := $(shell go env GOROOT) GIT_SHA := $(shell git rev-parse HEAD) GIT_SHA_SHORT := $(shell git rev-parse --short HEAD) diff --git a/command/command_file_test.go b/command/command_file_test.go index d59cd364e..8a125cd4f 100644 --- a/command/command_file_test.go +++ b/command/command_file_test.go @@ -105,9 +105,9 @@ print("important message") // Rust is like Python. Envs are user-local and need to be sourced. cargoEnvCfg := &ProgramConfig{ - ProgramName: "bash", + ProgramName: "sh", Source: &runnerv2.ProgramConfig_Script{ - Script: `source "$HOME/.cargo/env"`, + Script: `[ ! -e "$HOME/.cargo/env" ] || . "$HOME/.cargo/env"`, }, Mode: runnerv2.CommandMode_COMMAND_MODE_INLINE, } diff --git a/command/command_inline_shell_test.go b/command/command_inline_shell_test.go index 733191d7f..e7c718278 100644 --- a/command/command_inline_shell_test.go +++ b/command/command_inline_shell_test.go @@ -64,7 +64,7 @@ func TestInlineShellCommand_CollectEnv(t *testing.T) { Commands: &runnerv2.ProgramConfig_CommandList{ Items: []string{ "export TEST_ENV=1", - "sleep 5", + "/usr/bin/env sleep infinity", }, }, }, diff --git a/command/command_unix_test.go b/command/command_unix_test.go index b3b7b3b5a..08bfe89fd 100644 --- a/command/command_unix_test.go +++ b/command/command_unix_test.go @@ -55,21 +55,21 @@ func TestCommand(t *testing.T) { { name: "ShellScript", cfg: &ProgramConfig{ - ProgramName: "bash", + ProgramName: "sh", Source: &runnerv2.ProgramConfig_Script{ - Script: "#!/usr/local/bin/bash\n\nset -x -e -o pipefail\n\necho -n test\n", + Script: "#!/usr/bin/env sh\n\nset -x -e\n\necho -n test\n", }, Mode: runnerv2.CommandMode_COMMAND_MODE_INLINE, }, expectedStdout: "test", - expectedStderr: "+ echo -n test\n+ __cleanup\n+ rv=0\n+ env -0\n+ exit 0\n", + expectedStderr: "+ echo -n test\n+ __cleanup\n+ rv=0\n+ " + envDumpCommand + "\n+ exit 0\n", }, { name: "Input", cfg: &ProgramConfig{ - ProgramName: "bash", + ProgramName: "sh", Source: &runnerv2.ProgramConfig_Script{ - Script: "read line; echo $line | tr a-z A-Z", + Script: "read line; echo $line | /usr/bin/env tr a-z A-Z", }, Mode: runnerv2.CommandMode_COMMAND_MODE_INLINE, }, @@ -79,9 +79,9 @@ func TestCommand(t *testing.T) { { name: "InputInteractive", cfg: &ProgramConfig{ - ProgramName: "bash", + ProgramName: "sh", Source: &runnerv2.ProgramConfig_Script{ - Script: "read line; echo $line | tr a-z A-Z", + Script: "read line; echo $line | /usr/bin/env tr a-z A-Z", }, Interactive: true, Mode: runnerv2.CommandMode_COMMAND_MODE_INLINE, @@ -92,11 +92,11 @@ func TestCommand(t *testing.T) { { name: "StdoutStderr", cfg: &runnerv2.ProgramConfig{ - ProgramName: "bash", + ProgramName: "sh", Source: &runnerv2.ProgramConfig_Commands{ Commands: &runnerv2.ProgramConfig_CommandList{ Items: []string{ - "echo test | tee >(cat >&2)", + "echo test && echo test >&2", }, }, }, @@ -152,13 +152,13 @@ func TestCommand_FromCodeBlocks(t *testing.T) { }, { name: "ShellScript", - source: "```shellscript\n#!/usr/local/bin/bash\n\nset -x -e -o pipefail\n\necho -n test\n```", + source: "```shellscript\n#!/usr/bin/env sh\n\nset -x -e\n\necho -n test\n```", expectedStdout: "test", expectedStderr: "+ echo -n test\n", // due to -x }, { name: "ShellScriptInteractive", - source: "```shellscript {\"interactive\": true}\n#!/usr/local/bin/bash\n\nset -x -e -o pipefail\n\necho -n test\n```", + source: "```shellscript {\"interactive\": true}\n#!/bin/sh -i\n\nset -x -e\n\necho -n test\n```", expectedStdout: "+ echo -n test\r\ntest", // due to -x }, { @@ -182,13 +182,13 @@ func TestCommand_FromCodeBlocks(t *testing.T) { }, { name: "WithInput", - source: "```bash\nread line; echo $line | tr a-z A-Z\n```", + source: "```sh\nread line; echo $line | /usr/bin/env tr a-z A-Z\n```", input: []byte("test\n"), expectedStdout: "TEST\n", }, { name: "WithInputInteractive", - source: "```bash {\"interactive\": true}\nread line; echo $line | tr a-z A-Z\n```", + source: "```sh {\"interactive\": true}\nread line; echo $line | /usr/bin/env tr a-z A-Z\n```", input: []byte("test\n"), expectedStdout: "TEST\r\n", }, @@ -205,8 +205,8 @@ func TestCommand_FromCodeBlocks(t *testing.T) { }, { name: "FrontmatterShell", - source: "---\nshell: bash\n---\n```sh\necho -n $0 | xargs basename\n```", - expectedStdout: "bash\n", + source: "---\nshell: sh\n---\n```sh\necho -n \"${0##*/}\"\n```", + expectedStdout: "sh", }, { name: "DefaultToCat", @@ -334,10 +334,14 @@ func TestCommand_SetWinsize(t *testing.T) { cmd, err := factory.Build( &ProgramConfig{ - ProgramName: "bash", + ProgramName: "sh", Source: &runnerv2.ProgramConfig_Commands{ Commands: &runnerv2.ProgramConfig_CommandList{ - Items: []string{"sleep 1", "tput cols -T linux", "tput lines -T linux"}, + Items: []string{ + "/usr/bin/env sleep 1", + "/usr/bin/env tput cols -T linux", + "/usr/bin/env tput lines -T linux", + }, }, }, Interactive: true, @@ -458,7 +462,7 @@ func TestCommand_Session(t *testing.T) { func TestCommand_SimulateCtrlC(t *testing.T) { idResolver := identity.NewResolver(identity.AllLifecycleIdentity) - doc := document.New([]byte("```sh {\"interactive\": true}\nbash\n```"), idResolver) + doc := document.New([]byte("```sh {\"interactive\": true}\n/bin/sh -i\n```"), idResolver) node, err := doc.Root() require.NoError(t, err) blocks := document.CollectCodeBlocks(node) @@ -484,7 +488,7 @@ func TestCommand_SimulateCtrlC(t *testing.T) { defer close(errc) time.Sleep(time.Millisecond * 500) - _, err = stdinW.Write([]byte("sleep 30\n")) + _, err = stdinW.Write([]byte("sleep infinity\n")) errc <- err // cancel sleep diff --git a/command/env_collector.go b/command/env_collector.go index bfbe4463d..029283792 100644 --- a/command/env_collector.go +++ b/command/env_collector.go @@ -6,6 +6,7 @@ import ( "context" "io" "os" + "os/exec" "path/filepath" "strings" @@ -35,7 +36,13 @@ var envDumpCommand = func() string { // TODO(adamb): this can be made obsolete. runme must be built // in the test environment and put into the PATH. func SetEnvDumpCommandForTesting() { - envDumpCommand = "env -0" + env, err := exec.LookPath("env") + if err != nil { + panic(err) + } + + envDumpCommand = env + " -0" + // When overriding [envDumpCommand], we disable the encryption. // There is no reliable way at the moment to have encryption and // not control the dump command. diff --git a/command/env_collector_fifo_unix_test.go b/command/env_collector_fifo_unix_test.go index 05cb1d182..f7d117ddd 100644 --- a/command/env_collector_fifo_unix_test.go +++ b/command/env_collector_fifo_unix_test.go @@ -30,8 +30,8 @@ func Test_envCollectorFifo(t *testing.T) { buf := new(bytes.Buffer) err := collector.SetOnShell(buf) require.NoError(t, err) - expected := " env -0 > " + collector.prePath() + "\n" + - " __cleanup() {\nrv=$?\nenv -0 > " + collector.postPath() + "\nexit $rv\n}\n" + + expected := " " + envDumpCommand + " > " + collector.prePath() + "\n" + + " __cleanup() {\nrv=$?\n" + envDumpCommand + " > " + collector.postPath() + "\nexit $rv\n}\n" + " trap -- \"__cleanup\" EXIT\n" require.Equal(t, expected, buf.String()) }) diff --git a/command/env_collector_file_test.go b/command/env_collector_file_test.go index 739783ab9..134bb7d51 100644 --- a/command/env_collector_file_test.go +++ b/command/env_collector_file_test.go @@ -27,8 +27,8 @@ func Test_envCollectorFile(t *testing.T) { buf := new(bytes.Buffer) err := collector.SetOnShell(buf) require.NoError(t, err) - expected := " env -0 > " + collector.prePath() + "\n" + - " __cleanup() {\nrv=$?\nenv -0 > " + collector.postPath() + "\nexit $rv\n}\n" + + expected := " " + envDumpCommand + " > " + collector.prePath() + "\n" + + " __cleanup() {\nrv=$?\n" + envDumpCommand + " > " + collector.postPath() + "\nexit $rv\n}\n" + " trap -- \"__cleanup\" EXIT\n" require.Equal(t, expected, buf.String()) }) diff --git a/command/env_shell_test.go b/command/env_shell_test.go index 3fa06b5be..bef6bcbb9 100644 --- a/command/env_shell_test.go +++ b/command/env_shell_test.go @@ -25,8 +25,8 @@ func TestScriptEnvSetter(t *testing.T) { expected := "#!/bin/sh\n" + "set -euxo pipefail\n" + - "env -0 > /tmp/pre-path\n" + - "__cleanup() {\nrv=$?\nenv -0 > /tmp/post-path\nexit $rv\n}\n" + + envDumpCommand + " > /tmp/pre-path\n" + + "__cleanup() {\nrv=$?\n" + envDumpCommand + " > /tmp/post-path\nexit $rv\n}\n" + "trap -- \"__cleanup\" EXIT\n" + "set +euxo pipefail\n" require.EqualValues(t, expected, buf.String()) @@ -40,8 +40,8 @@ func TestScriptEnvSetter(t *testing.T) { require.NoError(t, err) expected := "#!/bin/sh\n" + - "env -0 > /tmp/pre-path\n" + - "__cleanup() {\nrv=$?\nenv -0 > /tmp/post-path\nexit $rv\n}\n" + + envDumpCommand + " > /tmp/pre-path\n" + + "__cleanup() {\nrv=$?\n" + envDumpCommand + " > /tmp/post-path\nexit $rv\n}\n" + "trap -- \"__cleanup\" EXIT\n" require.EqualValues(t, expected, buf.String()) }) diff --git a/docker/runme-build-env.Dockerfile b/docker/runme-build-env.Dockerfile index e84ac6ce8..6367324cd 100644 --- a/docker/runme-build-env.Dockerfile +++ b/docker/runme-build-env.Dockerfile @@ -7,7 +7,6 @@ LABEL org.opencontainers.image.title="Runme build environment" LABEL org.opencontainers.image.description="An image to build and test runme." ENV HOME=/root -ENV SHELL=/bin/bash RUN apt-get update && apt-get install -y \ "bash" \ diff --git a/examples/goexec/main.go b/examples/goexec/main.go index 2459a81a7..57af95bf5 100644 --- a/examples/goexec/main.go +++ b/examples/goexec/main.go @@ -8,7 +8,7 @@ import ( func main() { cmd := exec.Cmd{ - Path: "/usr/local/bin/bash", + Path: "/bin/sh", Args: []string{"-l", "-c", "python"}, Stdin: os.Stdin, Stdout: os.Stdout, diff --git a/runner/command_test.go b/runner/command_test.go index 0d31e6375..538d314e2 100644 --- a/runner/command_test.go +++ b/runner/command_test.go @@ -19,7 +19,12 @@ import ( ) func init() { - dumpCmd = "env -0" + envPath, err := exec.LookPath("env") + if err != nil { + panic(err) + } + + dumpCmd = envPath + " -0" } func Test_command(t *testing.T) { @@ -246,7 +251,7 @@ func Test_command(t *testing.T) { Stdout: io.Discard, Stderr: io.Discard, CommandMode: CommandModeInlineShell, - Script: `source "$HOME/.cargo/env"`, + Script: `[ ! -e "$HOME/.cargo/env" ] || . "$HOME/.cargo/env"`, Logger: logger, }, ) diff --git a/testdata/flags/fmt.txtar b/testdata/flags/fmt.txtar index f985e4e9e..f2c5fb2aa 100644 --- a/testdata/flags/fmt.txtar +++ b/testdata/flags/fmt.txtar @@ -1,9 +1,7 @@ -env SHELL=/bin/bash exec runme fmt --write cmp README-FORMATTED.md README.md ! stderr . -env SHELL=/bin/bash exec runme fmt reset --write cmp LCID-all.md LCID-none.md ! stderr . diff --git a/testdata/prompts/basic.txtar b/testdata/prompts/basic.txtar index c6c1d6e09..258b36623 100644 --- a/testdata/prompts/basic.txtar +++ b/testdata/prompts/basic.txtar @@ -1,4 +1,3 @@ -env SHELL=/bin/bash exec runme run --all --category=foo --filename=PROMPTS.md cmp stdout foo-bar-list.txt ! stderr . diff --git a/testdata/runall/basic.txtar b/testdata/runall/basic.txtar index 3943e6089..455a30549 100644 --- a/testdata/runall/basic.txtar +++ b/testdata/runall/basic.txtar @@ -1,9 +1,7 @@ -env SHELL=/bin/bash exec runme run --all --filename=README.md cmp stdout all.txt ! stderr . -env SHELL=/bin/bash exec runme run foo-command cmp stdout skip.txt ! stderr . diff --git a/testdata/script/basic.txtar b/testdata/script/basic.txtar index 1e62302ac..2b13ee1b1 100644 --- a/testdata/script/basic.txtar +++ b/testdata/script/basic.txtar @@ -14,22 +14,18 @@ cmp stdout golden-list-allow-unnamed.txt stderr 'failed to open file-based project \".*\/nonexistent.md\": file does not exist' ! stdout . -env SHELL=/bin/bash exec runme run echo stdout 'Hello, runme!' ! stderr . -env SHELL=/bin/bash exec runme run --filename README.md --index 0 stdout 'Hello, runme!' ! stderr . -env SHELL=/bin/bash exec runme run --filename README.md echo-1 stdout '1\n2\n3\n' ! stderr . -env SHELL=/bin/bash exec runme run --allow-unnamed tempdir stdout 'hi!' ! stderr . diff --git a/testdata/tags/categories.txtar b/testdata/tags/categories.txtar index 4cfbe9077..37725b94c 100644 --- a/testdata/tags/categories.txtar +++ b/testdata/tags/categories.txtar @@ -1,24 +1,19 @@ -env SHELL=/bin/bash exec runme run --all --category=foo --filename=CATEGORIES.md cmp stdout foo-bar-list.txt stderr 'Flag --category has been deprecated, use --tag instead' -env SHELL=/bin/bash exec runme run --all --category=bar --filename=CATEGORIES.md cmp stdout bar-list.txt stderr 'Flag --category has been deprecated, use --tag instead' -env SHELL=/bin/bash exec runme run -c buzz -c bar --filename=CATEGORIES.md cmp stdout buzz-bar-list.txt stderr 'Flag --category has been deprecated, use --tag instead' -env SHELL=/bin/bash exec runme run --all --allow-unnamed -y --category solution-2 cmp stdout doc-category-with-unnamed.txt stderr 'Flag --category has been deprecated, use --tag instead' -env SHELL=/bin/bash exec runme run --all --skip-prompts --category solution-2 cmp stdout doc-category.txt stderr 'Flag --category has been deprecated, use --tag instead' diff --git a/testdata/tags/tags.txtar b/testdata/tags/tags.txtar index 1beedb64a..f60b7d058 100644 --- a/testdata/tags/tags.txtar +++ b/testdata/tags/tags.txtar @@ -1,48 +1,38 @@ -env SHELL=/bin/bash exec runme run --all --tag=foo --filename=TAGS.md cmp stdout foo-bar-list.txt ! stderr . -env SHELL=/bin/bash exec runme run --all --tag=bar --filename=TAGS.md cmp stdout bar-list.txt ! stderr . -env SHELL=/bin/bash exec runme run -t buzz -t bar --filename=TAGS.md cmp stdout buzz-bar-list.txt ! stderr . -env SHELL=/bin/bash exec runme run --all --tag=foo --filename=CATEGORIES.md cmp stdout foo-bar-list.txt ! stderr . -env SHELL=/bin/bash exec runme run --all --tag=bar --filename=CATEGORIES.md cmp stdout bar-list.txt ! stderr . -env SHELL=/bin/bash exec runme run -t buzz -t bar --filename=CATEGORIES.md cmp stdout buzz-bar-list.txt ! stderr . -env SHELL=/bin/bash exec runme run --all --allow-unnamed -y --tag solution-2 cmp stdout doc-category-with-unnamed.txt ! stderr . -env SHELL=/bin/bash exec runme run --all --skip-prompts --tag solution-2 cmp stdout doc-category.txt ! stderr . -env SHELL=/bin/bash ! exec runme run --all --skip-prompts --tag solution stderr 'could not execute command: No tasks to execute with the tag provided' -env SHELL=/bin/bash exec runme run --all --skip-prompts -e --tag solution cmp stdout tag-pattern-matches.txt ! stderr .