Repository: nektos/act (language: go)

Issue:
fix: make sure socket path is used in bind mount
Docker cannot receive socket uri parameters in a bind mount.
This change makes sure a possible uri preifx is stripped from
the path.

Fixes #1756 


Discussion / hints:
## [🦙 MegaLinter](https://megalinter.io/6.22.2) status: ✅ [SUCCESS](https://github.com/nektos/act/actions/runs/4784255630)

|  Descriptor   |                                              Linter                                              |Files|Fixed|Errors|Elapsed time|
|---------------|--------------------------------------------------------------------------------------------------|-----|-----|------|------------|
|✅ EDITORCONFIG|[editorconfig-checker](https://megalinter.io/6.22.2/descriptors/editorconfig_editorconfig_checker)|    1|     |     0|0.02s       |
|✅ REPOSITORY  |[gitleaks](https://megalinter.io/6.22.2/descriptors/repository_gitleaks)                          |yes  |     |no    |2.5s        |
|✅ REPOSITORY  |[git_diff](https://megalinter.io/6.22.2/descriptors/repository_git_diff)                          |yes  |     |no    |0.0s        |
|✅ REPOSITORY  |[secretlint](https://megalinter.io/6.22.2/descriptors/repository_secretlint)                      |yes  |     |no    |1.39s       |

See detailed report in [MegaLinter reports](https://github.com/nektos/act/actions/runs/4784255630)
_Set `VALIDATE_ALL_CODEBASE: true` in mega-linter.yml to validate all sources, not only the diff_

_MegaLinter is graciously provided by [![OX Security](https://www.ox.security/wp-content/uploads/2022/06/logo.svg?ref=megalinter_comment)](https://www.ox.security/?ref=megalinter)_

<!-- megalinter: github-comment-reporter workflow='checks' jobid='lint' -->

Here is a related test case for this: https://github.com/nektos/act/pull/1758

Based on this, I didn't notice a breaking change in ContainerDaemonSocket.

I think `--container-daemon-socket` no longer works if you pass `/var/run/docker.sock`.

And if this is would be a ssh uri it get's really bad.
## [Codecov](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos) Report
> Merging [#1757](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos) (a914c4a) into [master](https://codecov.io/gh/nektos/act/commit/4989f444f1085ac0ec6b9bc35de92dc22f3c9f5d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos) (4989f44) will **increase** coverage by `1.10%`.
> The diff coverage is `66.16%`.

```diff
@@            Coverage Diff             @@
##           master    #1757      +/-   ##
==========================================
+ Coverage   61.22%   62.32%   +1.10%     
==========================================
  Files          46       48       +2     
  Lines        7141     7576     +435     
==========================================
+ Hits         4372     4722     +350     
- Misses       2462     2525      +63     
- Partials      307      329      +22     
```


| [Impacted Files](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos) | Coverage Δ | |
|---|---|---|
| [pkg/common/outbound\_ip.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbW1vbi9vdXRib3VuZF9pcC5nbw==) | `0.00% <0.00%> (ø)` | |
| [pkg/container/docker\_cli.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9kb2NrZXJfY2xpLmdv) | `82.23% <ø> (ø)` | |
| [pkg/container/docker\_logger.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9kb2NrZXJfbG9nZ2VyLmdv) | `52.08% <ø> (ø)` | |
| [pkg/container/docker\_pull.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9kb2NrZXJfcHVsbC5nbw==) | `33.33% <ø> (ø)` | |
| [pkg/container/docker\_run.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9kb2NrZXJfcnVuLmdv) | `13.58% <0.00%> (-0.01%)` | :arrow_down: |
| [pkg/container/docker\_volume.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9kb2NrZXJfdm9sdW1lLmdv) | `0.00% <ø> (ø)` | |
| [pkg/container/file\_collector.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9maWxlX2NvbGxlY3Rvci5nbw==) | `39.68% <0.00%> (+2.38%)` | :arrow_up: |
| [pkg/container/host\_environment.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9ob3N0X2Vudmlyb25tZW50Lmdv) | `0.00% <0.00%> (ø)` | |
| [...ontainer/linux\_container\_environment\_extensions.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2NvbnRhaW5lci9saW51eF9jb250YWluZXJfZW52aXJvbm1lbnRfZXh0ZW5zaW9ucy5nbw==) | `23.07% <0.00%> (-1.25%)` | :arrow_down: |
| [pkg/exprparser/functions.go](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos#diff-cGtnL2V4cHJwYXJzZXIvZnVuY3Rpb25zLmdv) | `66.32% <0.00%> (-1.04%)` | :arrow_down: |
| ... and [22 more](https://codecov.io/gh/nektos/act/pull/1757?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos) | |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=nektos)

> And if this is would be a ssh uri it get's really bad

Based on the current implementation act is not able to use any protocol but a socket.


Fix patch:
diff --git a/cmd/root.go b/cmd/root.go
index 55b55bb27ee..548d90cc009 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -80,7 +80,7 @@ func Execute(ctx context.Context, version string) {
 	rootCmd.PersistentFlags().StringVarP(&input.envfile, "env-file", "", ".env", "environment file to read and use as env in the containers")
 	rootCmd.PersistentFlags().StringVarP(&input.inputfile, "input-file", "", ".input", "input file to read and use as action input")
 	rootCmd.PersistentFlags().StringVarP(&input.containerArchitecture, "container-architecture", "", "", "Architecture which should be used to run containers, e.g.: linux/amd64. If not specified, will use host default architecture. Requires Docker server API Version 1.41+. Ignored on earlier Docker server platforms.")
-	rootCmd.PersistentFlags().StringVarP(&input.containerDaemonSocket, "container-daemon-socket", "", "", "URI to Docker Engine socket (e.g.: unix://~/.docker/run/docker.sock)")
+	rootCmd.PersistentFlags().StringVarP(&input.containerDaemonSocket, "container-daemon-socket", "", "", "URI to Docker Engine socket (e.g.: unix://~/.docker/run/docker.sock or - to disable bind mounting the socket)")
 	rootCmd.PersistentFlags().StringVarP(&input.containerOptions, "container-options", "", "", "Custom docker container options for the job container without an options property in the job definition")
 	rootCmd.PersistentFlags().StringVarP(&input.githubInstance, "github-instance", "", "github.com", "GitHub instance to use. Don't use this if you are not using GitHub Enterprise Server.")
 	rootCmd.PersistentFlags().StringVarP(&input.artifactServerPath, "artifact-server-path", "", "", "Defines the path where the artifact server stores uploads and retrieves downloads from. If not specified the artifact server will not start.")
@@ -136,9 +136,9 @@ func socketLocation() (string, bool) {
 	for _, p := range commonSocketPaths {
 		if _, err := os.Lstat(os.ExpandEnv(p)); err == nil {
 			if strings.HasPrefix(p, `\\.\`) {
-				return "npipe://" + os.ExpandEnv(p), true
+				return "npipe://" + filepath.ToSlash(os.ExpandEnv(p)), true
 			}
-			return "unix://" + os.ExpandEnv(p), true
+			return "unix://" + filepath.ToSlash(os.ExpandEnv(p)), true
 		}
 	}
 
@@ -350,6 +350,18 @@ func parseMatrix(matrix []string) map[string]map[string]bool {
 	return matrixes
 }
 
+func isDockerHostURI(daemonPath string) bool {
+	if protoIndex := strings.Index(daemonPath, "://"); protoIndex != -1 {
+		scheme := daemonPath[:protoIndex]
+		if strings.IndexFunc(scheme, func(r rune) bool {
+			return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z')
+		}) == -1 {
+			return true
+		}
+	}
+	return false
+}
+
 //nolint:gocyclo
 func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []string) error {
 	return func(cmd *cobra.Command, args []string) error {
@@ -361,18 +373,27 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
 			return bugReport(ctx, cmd.Version)
 		}
 
-		var socketPath string
-		if input.containerDaemonSocket != "" {
-			socketPath = input.containerDaemonSocket
-		} else {
-			socket, found := socketLocation()
-			if !found && input.containerDaemonSocket == "" {
-				log.Errorln("daemon Docker Engine socket not found and containerDaemonSocket option was not set")
+		// Prefer DOCKER_HOST, don't override it
+		socketPath, hasDockerHost := os.LookupEnv("DOCKER_HOST")
+		if !hasDockerHost {
+			// a - in containerDaemonSocket means don't mount, preserve this value
+			// otherwise if input.containerDaemonSocket is a filepath don't use it as socketPath
+			skipMount := input.containerDaemonSocket == "-" || !isDockerHostURI(input.containerDaemonSocket)
+			if input.containerDaemonSocket != "" && !skipMount {
+				socketPath = input.containerDaemonSocket
 			} else {
-				socketPath = socket
+				socket, found := socketLocation()
+				if !found {
+					log.Errorln("daemon Docker Engine socket not found and containerDaemonSocket option was not set")
+				} else {
+					socketPath = socket
+				}
+				if !skipMount {
+					input.containerDaemonSocket = socketPath
+				}
 			}
+			os.Setenv("DOCKER_HOST", socketPath)
 		}
-		os.Setenv("DOCKER_HOST", socketPath)
 
 		if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" && input.containerArchitecture == "" {
 			l := log.New()
@@ -565,7 +586,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
 			Privileged:                         input.privileged,
 			UsernsMode:                         input.usernsMode,
 			ContainerArchitecture:              input.containerArchitecture,
-			ContainerDaemonSocket:              socketPath,
+			ContainerDaemonSocket:              input.containerDaemonSocket,
 			ContainerOptions:                   input.containerOptions,
 			UseGitIgnore:                       input.useGitIgnore,
 			GitHubInstance:                     input.githubInstance,
diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go
index fb04f89cbc0..e6f5dfc749b 100644
--- a/pkg/runner/run_context.go
+++ b/pkg/runner/run_context.go
@@ -87,6 +87,24 @@ func (rc *RunContext) jobContainerName() string {
 	return createContainerName("act", rc.String())
 }
 
+func getDockerDaemonSocketMountPath(daemonPath string) string {
+	if protoIndex := strings.Index(daemonPath, "://"); protoIndex != -1 {
+		scheme := daemonPath[:protoIndex]
+		if strings.EqualFold(scheme, "npipe") {
+			// linux container mount on windows, use the default socket path of the VM / wsl2
+			return "/var/run/docker.sock"
+		} else if strings.EqualFold(scheme, "unix") {
+			return daemonPath[protoIndex+3:]
+		} else if strings.IndexFunc(scheme, func(r rune) bool {
+			return (r < 'a' || r > 'z') && (r < 'A' || r > 'Z')
+		}) == -1 {
+			// unknown protocol use default
+			return "/var/run/docker.sock"
+		}
+	}
+	return daemonPath
+}
+
 // Returns the binds and mounts for the container, resolving paths as appopriate
 func (rc *RunContext) GetBindsAndMounts() ([]string, map[string]string) {
 	name := rc.jobContainerName()
@@ -95,8 +113,10 @@ func (rc *RunContext) GetBindsAndMounts() ([]string, map[string]string) {
 		rc.Config.ContainerDaemonSocket = "/var/run/docker.sock"
 	}
 
-	binds := []string{
-		fmt.Sprintf("%s:%s", 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"))
 	}
 
 	ext := container.LinuxContainerEnvironmentExtensions{}


Test patch: