diff --git a/act/container/container_types.go b/act/container/container_types.go index 1d0acac0..810d7914 100644 --- a/act/container/container_types.go +++ b/act/container/container_types.go @@ -17,6 +17,7 @@ type NewContainerInput struct { Cmd []string WorkingDir string Env []string + ToolCache string Binds []string Mounts map[string]string Name string diff --git a/act/container/docker_run.go b/act/container/docker_run.go index 64b29909..b195772b 100644 --- a/act/container/docker_run.go +++ b/act/container/docker_run.go @@ -46,6 +46,7 @@ import ( func NewContainer(input *NewContainerInput) ExecutionsEnvironment { cr := new(containerReference) cr.input = input + cr.toolCache = input.ToolCache return cr } diff --git a/act/container/linux_container_environment_extensions.go b/act/container/linux_container_environment_extensions.go index 54f19209..6ba30f1d 100644 --- a/act/container/linux_container_environment_extensions.go +++ b/act/container/linux_container_environment_extensions.go @@ -10,7 +10,9 @@ import ( log "github.com/sirupsen/logrus" ) -type LinuxContainerEnvironmentExtensions struct{} +type LinuxContainerEnvironmentExtensions struct { + toolCache string +} // Resolves the equivalent host path inside the container // This is required for windows and WSL 2 to translate things like C:\Users\Myproject to /mnt/users/Myproject @@ -74,12 +76,12 @@ func (*LinuxContainerEnvironmentExtensions) JoinPathVariable(paths ...string) st return strings.Join(paths, ":") } -func (*LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]interface{} { +func (l *LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]interface{} { return map[string]interface{}{ "os": "Linux", "arch": RunnerArch(ctx), "temp": "/tmp", - "tool_cache": "/opt/hostedtoolcache", + "tool_cache": l.toolCache, } } diff --git a/act/runner/action.go b/act/runner/action.go index e205c0b7..c5ed37ed 100644 --- a/act/runner/action.go +++ b/act/runner/action.go @@ -419,7 +419,7 @@ func newStepContainer(ctx context.Context, step step, image string, cmd []string envList = append(envList, fmt.Sprintf("%s=%s", k, v)) } - envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TOOL_CACHE", "/opt/hostedtoolcache")) + envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TOOL_CACHE", rc.getToolCache(ctx))) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_OS", "Linux")) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_ARCH", container.RunnerArch(ctx))) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp")) @@ -438,6 +438,7 @@ func newStepContainer(ctx context.Context, step step, image string, cmd []string Password: rc.Config.Secrets["DOCKER_PASSWORD"], Name: createSimpleContainerName(rc.jobContainerName(), "STEP-"+stepModel.ID), Env: envList, + ToolCache: rc.getToolCache(ctx), Mounts: mounts, NetworkMode: networkMode, Binds: binds, diff --git a/act/runner/run_context.go b/act/runner/run_context.go index c45e199f..05b7decf 100644 --- a/act/runner/run_context.go +++ b/act/runner/run_context.go @@ -300,13 +300,12 @@ func (rc *RunContext) startHostEnvironment() common.Executor { if err := os.MkdirAll(runnerTmp, 0o777); err != nil { return err } - toolCache := filepath.Join(cacheDir, "tool_cache") rc.JobContainer = &container.HostEnvironment{ Name: randName, Root: miscpath, Path: path, TmpDir: runnerTmp, - ToolCache: toolCache, + ToolCache: rc.getToolCache(ctx), Workdir: rc.Config.Workdir, ActPath: actPath, CleanUp: func() { @@ -419,7 +418,7 @@ func (rc *RunContext) startJobContainer() common.Executor { envList := make([]string, 0) - envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TOOL_CACHE", "/opt/hostedtoolcache")) + envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TOOL_CACHE", rc.getToolCache(ctx))) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_OS", "Linux")) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_ARCH", container.RunnerArch(ctx))) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp")) @@ -481,6 +480,7 @@ func (rc *RunContext) startJobContainer() common.Executor { Password: password, Cmd: interpolatedCmd, Env: envs, + ToolCache: rc.getToolCache(ctx), Mounts: serviceMounts, Binds: serviceBinds, Stdout: logWriter, @@ -542,6 +542,7 @@ func (rc *RunContext) startJobContainer() common.Executor { Password: password, Name: name, Env: envList, + ToolCache: rc.getToolCache(ctx), Mounts: mounts, NetworkMode: networkName, NetworkAliases: []string{rc.Name}, @@ -761,6 +762,16 @@ func (rc *RunContext) interpolateOutputs() common.Executor { } } +func (rc *RunContext) getToolCache(ctx context.Context) string { + if value, ok := rc.Config.Env["RUNNER_TOOL_CACHE"]; ok { + return value + } + if rc.IsHostEnv(ctx) { + return filepath.Join(rc.ActionCacheDir(), "tool_cache") + } + return "/opt/hostedtoolcache" +} + func (rc *RunContext) startContainer() common.Executor { return func(ctx context.Context) error { if rc.IsHostEnv(ctx) { diff --git a/act/runner/runner_test.go b/act/runner/runner_test.go index 4c500172..6be2a9af 100644 --- a/act/runner/runner_test.go +++ b/act/runner/runner_test.go @@ -218,7 +218,8 @@ func (j *TestJobFileInfo) runTest(ctx context.Context, t *testing.T, cfg *Config } type TestConfig struct { - LocalRepositories map[string]string `yaml:"local-repositories"` + LocalRepositories map[string]string `yaml:"local-repositories,omitempty"` + Env map[string]string `yaml:"env,omitempty"` } func TestRunEvent(t *testing.T) { @@ -314,6 +315,7 @@ func TestRunEvent(t *testing.T) { {workdir, "set-env-step-env-override", "push", "", platforms, secrets}, {workdir, "set-env-new-env-file-per-step", "push", "", platforms, secrets}, {workdir, "no-panic-on-invalid-composite-action", "push", "jobs failed due to invalid action", platforms, secrets}, + {workdir, "tool-cache", "push", "", platforms, secrets}, // services {workdir, "services", "push", "", platforms, secrets}, @@ -349,6 +351,7 @@ func TestRunEvent(t *testing.T) { } } } + config.Env = testConfig.Env } table.runTest(ctx, t, config) diff --git a/act/runner/step_docker.go b/act/runner/step_docker.go index 2f239866..bbf46e01 100644 --- a/act/runner/step_docker.go +++ b/act/runner/step_docker.go @@ -107,7 +107,7 @@ func (sd *stepDocker) newStepContainer(ctx context.Context, image string, cmd [] envList = append(envList, fmt.Sprintf("%s=%s", k, v)) } - envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TOOL_CACHE", "/opt/hostedtoolcache")) + envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TOOL_CACHE", rc.getToolCache(ctx))) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_OS", "Linux")) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_ARCH", container.RunnerArch(ctx))) envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp")) @@ -122,6 +122,7 @@ func (sd *stepDocker) newStepContainer(ctx context.Context, image string, cmd [] Password: rc.Config.Secrets["DOCKER_PASSWORD"], Name: createSimpleContainerName(rc.jobContainerName(), "STEP-"+step.ID), Env: envList, + ToolCache: rc.getToolCache(ctx), Mounts: mounts, NetworkMode: fmt.Sprintf("container:%s", rc.jobContainerName()), Binds: binds, diff --git a/act/runner/testdata/tool-cache/config/config.yml b/act/runner/testdata/tool-cache/config/config.yml new file mode 100644 index 00000000..d6b92bcc --- /dev/null +++ b/act/runner/testdata/tool-cache/config/config.yml @@ -0,0 +1,2 @@ +env: + RUNNER_TOOL_CACHE: /srv/otherlocaltion diff --git a/act/runner/testdata/tool-cache/push.yml b/act/runner/testdata/tool-cache/push.yml new file mode 100644 index 00000000..6229b8b8 --- /dev/null +++ b/act/runner/testdata/tool-cache/push.yml @@ -0,0 +1,8 @@ +name: basic +on: push + +jobs: + build: + runs-on: ubuntu-latest + steps: + - run: test "$RUNNER_TOOL_CACHE" = "/srv/otherlocaltion"