diff --git a/pkg/container/container_types.go b/pkg/container/container_types.go index d9f7d75b7d5..55d16259e58 100644 --- a/pkg/container/container_types.go +++ b/pkg/container/container_types.go @@ -27,6 +27,7 @@ type NewContainerInput struct { Platform string Options string NetworkAliases []string + ValidVolumes []string } // FileEntry is a file to copy to a container diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index c85e8fe47d7..19a0d49ca5f 100644 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -290,21 +290,17 @@ func (rc *RunContext) startJobContainer() common.Executor { if err != nil { return fmt.Errorf("failed to handle service %s credentials: %w", serviceId, err) } + serviceBinds, serviceMounts := rc.GetServiceBindsAndMounts(spec.Volumes) serviceContainerName := createContainerName(rc.jobContainerName(), serviceId) c := container.NewContainer(&container.NewContainerInput{ - Name: serviceContainerName, - WorkingDir: ext.ToContainerPath(rc.Config.Workdir), - Image: spec.Image, - Username: username, - Password: password, - Env: envs, - Mounts: map[string]string{ - // TODO merge volumes - serviceId: ext.ToContainerPath(rc.Config.Workdir), - "act-toolcache": "/toolcache", - "act-actions": "/actions", - }, - Binds: binds, + Name: serviceContainerName, + WorkingDir: ext.ToContainerPath(rc.Config.Workdir), + Image: spec.Image, + Username: username, + Password: password, + Env: envs, + Mounts: serviceMounts, + Binds: serviceBinds, Stdout: logWriter, Stderr: logWriter, Privileged: rc.Config.Privileged, @@ -313,6 +309,7 @@ func (rc *RunContext) startJobContainer() common.Executor { Options: spec.Options, NetworkMode: networkName, NetworkAliases: []string{serviceId}, + ValidVolumes: rc.Config.ValidVolumes, }) rc.ServiceContainers = append(rc.ServiceContainers, c) } @@ -345,6 +342,7 @@ func (rc *RunContext) startJobContainer() common.Executor { UsernsMode: rc.Config.UsernsMode, Platform: rc.Config.ContainerArchitecture, Options: rc.options(ctx), + ValidVolumes: rc.Config.ValidVolumes, }) if rc.JobContainer == nil { return errors.New("Failed to create job container") @@ -983,3 +981,30 @@ func (rc *RunContext) handleServiceCredentials(ctx context.Context, creds map[st return } + +// GetServiceBindsAndMounts returns the binds and mounts for the service container, resolving paths as appopriate +func (rc *RunContext) GetServiceBindsAndMounts(svcVolumes []string) ([]string, map[string]string) { + if rc.Config.ContainerDaemonSocket == "" { + rc.Config.ContainerDaemonSocket = "/var/run/docker.sock" + } + binds := []string{} + if rc.Config.ContainerDaemonSocket != "-" { + daemonPath := getDockerDaemonSocketMountPath(rc.Config.ContainerDaemonSocket) + binds = append(binds, fmt.Sprintf("%s:%s", daemonPath, "/var/run/docker.sock")) + } + + mounts := map[string]string{} + + for _, v := range svcVolumes { + if !strings.Contains(v, ":") || filepath.IsAbs(v) { + // Bind anonymous volume or host file. + binds = append(binds, v) + } else { + // Mount existing volume. + paths := strings.SplitN(v, ":", 2) + mounts[paths[0]] = paths[1] + } + } + + return binds, mounts +} diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index c63f6b866d9..2271ffce2f8 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -62,6 +62,7 @@ type Config struct { Matrix map[string]map[string]bool // Matrix config to run ContainerMaxLifetime time.Duration // the max lifetime of job containers ContainerNetworkMode docker_container.NetworkMode // the network mode of job containers (the value of --network) + ValidVolumes []string // only volumes (and bind mounts) in this slice can be mounted on the job container or service containers } type caller struct {