You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02:00 
			
		
		
		
	Rework entrypoints (#3269)
Co-authored-by: Thomas Anderson <127358482+zc-devs@users.noreply.github.com> Co-authored-by: 6543 <m.huber@kithara.com>
This commit is contained in:
		| @@ -161,6 +161,9 @@ Only build steps can define commands. You cannot use commands with plugins or se | ||||
|  | ||||
| Allows you to specify the entrypoint for containers. Note that this must be a list of the command and its arguments (e.g. `["/bin/sh", "-c"]`). | ||||
|  | ||||
| If you define [`commands`](#commands), the default entrypoint will be `["/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"]`. | ||||
| You can also use a custom shell with `CI_SCRIPT` (Base64-encoded) if you set `commands`. | ||||
|  | ||||
| ### `environment` | ||||
|  | ||||
| Woodpecker provides the ability to pass environment variables to individual steps. | ||||
|   | ||||
| @@ -18,21 +18,19 @@ import ( | ||||
| 	"encoding/base64" | ||||
| ) | ||||
|  | ||||
| func GenerateContainerConf(commands []string, goos string) (env map[string]string, entry []string, cmd string) { | ||||
| func GenerateContainerConf(commands []string, goos string) (env map[string]string, entry []string) { | ||||
| 	env = make(map[string]string) | ||||
| 	if goos == "windows" { | ||||
| 		env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptWindows(commands))) | ||||
| 		env["HOME"] = "c:\\root" | ||||
| 		env["SHELL"] = "powershell.exe" | ||||
| 		entry = []string{"powershell", "-noprofile", "-noninteractive", "-command"} | ||||
| 		cmd = "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex" | ||||
| 		entry = []string{"powershell", "-noprofile", "-noninteractive", "-command", "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"} | ||||
| 	} else { | ||||
| 		env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptPosix(commands))) | ||||
| 		env["HOME"] = "/root" | ||||
| 		env["SHELL"] = "/bin/sh" | ||||
| 		entry = []string{"/bin/sh", "-c"} | ||||
| 		cmd = "echo $CI_SCRIPT | base64 -d | /bin/sh -e" | ||||
| 		entry = []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"} | ||||
| 	} | ||||
|  | ||||
| 	return env, entry, cmd | ||||
| 	return env, entry | ||||
| } | ||||
|   | ||||
| @@ -12,16 +12,14 @@ const ( | ||||
| ) | ||||
|  | ||||
| func TestGenerateContainerConf(t *testing.T) { | ||||
| 	gotEnv, gotEntry, gotCmd := GenerateContainerConf([]string{"echo hello world"}, "windows") | ||||
| 	gotEnv, gotEntry := GenerateContainerConf([]string{"echo hello world"}, "windows") | ||||
| 	assert.Equal(t, windowsScriptBase64, gotEnv["CI_SCRIPT"]) | ||||
| 	assert.Equal(t, "c:\\root", gotEnv["HOME"]) | ||||
| 	assert.Equal(t, "powershell.exe", gotEnv["SHELL"]) | ||||
| 	assert.Equal(t, []string{"powershell", "-noprofile", "-noninteractive", "-command"}, gotEntry) | ||||
| 	assert.Equal(t, "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex", gotCmd) | ||||
| 	gotEnv, gotEntry, gotCmd = GenerateContainerConf([]string{"echo hello world"}, "linux") | ||||
| 	assert.Equal(t, []string{"powershell", "-noprofile", "-noninteractive", "-command", "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}, gotEntry) | ||||
| 	gotEnv, gotEntry = GenerateContainerConf([]string{"echo hello world"}, "linux") | ||||
| 	assert.Equal(t, posixScriptBase64, gotEnv["CI_SCRIPT"]) | ||||
| 	assert.Equal(t, "/root", gotEnv["HOME"]) | ||||
| 	assert.Equal(t, "/bin/sh", gotEnv["SHELL"]) | ||||
| 	assert.Equal(t, []string{"/bin/sh", "-c"}, gotEntry) | ||||
| 	assert.Equal(t, "echo $CI_SCRIPT | base64 -d | /bin/sh -e", gotCmd) | ||||
| 	assert.Equal(t, []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, gotEntry) | ||||
| } | ||||
|   | ||||
| @@ -45,16 +45,15 @@ func (e *docker) toConfig(step *types.Step) *container.Config { | ||||
| 	configEnv := make(map[string]string) | ||||
| 	maps.Copy(configEnv, step.Environment) | ||||
|  | ||||
| 	if len(step.Commands) != 0 { | ||||
| 		env, entry, cmd := common.GenerateContainerConf(step.Commands, e.info.OSType) | ||||
| 	if len(step.Commands) > 0 { | ||||
| 		env, entry := common.GenerateContainerConf(step.Commands, e.info.OSType) | ||||
| 		for k, v := range env { | ||||
| 			configEnv[k] = v | ||||
| 		} | ||||
| 		if len(step.Entrypoint) > 0 { | ||||
| 			entry = step.Entrypoint | ||||
| 		} | ||||
| 		config.Entrypoint = entry | ||||
| 		config.Cmd = []string{cmd} | ||||
| 	} | ||||
| 	if len(step.Entrypoint) > 0 { | ||||
| 		config.Entrypoint = step.Entrypoint | ||||
| 	} | ||||
|  | ||||
| 	if len(configEnv) != 0 { | ||||
|   | ||||
| @@ -105,8 +105,7 @@ func TestToConfigSmall(t *testing.T) { | ||||
| 	assert.EqualValues(t, &container.Config{ | ||||
| 		AttachStdout: true, | ||||
| 		AttachStderr: true, | ||||
| 		Cmd:          []string{"echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, | ||||
| 		Entrypoint:   []string{"/bin/sh", "-c"}, | ||||
| 		Entrypoint:   []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, | ||||
| 		Labels: map[string]string{ | ||||
| 			"wp_step": "test", | ||||
| 			"wp_uuid": "09238932", | ||||
| @@ -163,8 +162,7 @@ func TestToConfigFull(t *testing.T) { | ||||
| 		WorkingDir:   "/src/abc", | ||||
| 		AttachStdout: true, | ||||
| 		AttachStderr: true, | ||||
| 		Cmd:          []string{"echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, | ||||
| 		Entrypoint:   []string{"/bin/sh", "-c"}, | ||||
| 		Entrypoint:   []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, | ||||
| 		Labels: map[string]string{ | ||||
| 			"wp_step": "test", | ||||
| 			"wp_uuid": "09238932", | ||||
|   | ||||
| @@ -147,15 +147,14 @@ func podContainer(step *types.Step, podName, goos string, options BackendOptions | ||||
| 		container.ImagePullPolicy = v1.PullAlways | ||||
| 	} | ||||
|  | ||||
| 	if len(step.Commands) != 0 { | ||||
| 		scriptEnv, command, args := common.GenerateContainerConf(step.Commands, goos) | ||||
| 		if len(step.Entrypoint) > 0 { | ||||
| 			command = step.Entrypoint | ||||
| 		} | ||||
| 	if len(step.Commands) > 0 { | ||||
| 		scriptEnv, command := common.GenerateContainerConf(step.Commands, goos) | ||||
| 		container.Command = command | ||||
| 		container.Args = []string{args} | ||||
| 		maps.Copy(step.Environment, scriptEnv) | ||||
| 	} | ||||
| 	if len(step.Entrypoint) > 0 { | ||||
| 		container.Command = step.Entrypoint | ||||
| 	} | ||||
|  | ||||
| 	container.Env = mapToEnvVars(step.Environment) | ||||
|  | ||||
|   | ||||
| @@ -90,9 +90,7 @@ func TestTinyPod(t *testing.T) { | ||||
| 					"image": "gradle:8.4.0-jdk21", | ||||
| 					"command": [ | ||||
| 						"/bin/sh", | ||||
| 						"-c" | ||||
| 					], | ||||
| 					"args": [ | ||||
| 						"-c", | ||||
| 						"echo $CI_SCRIPT | base64 -d | /bin/sh -e" | ||||
| 					], | ||||
| 					"workingDir": "/woodpecker/src", | ||||
| @@ -183,9 +181,6 @@ func TestFullPod(t *testing.T) { | ||||
| 						"/bin/sh", | ||||
| 						"-c" | ||||
| 					], | ||||
| 					"args": [ | ||||
| 						"echo $CI_SCRIPT | base64 -d | /bin/sh -e" | ||||
| 					], | ||||
| 					"workingDir": "/woodpecker/src", | ||||
| 					"ports": [ | ||||
| 						{ | ||||
| @@ -415,3 +410,49 @@ func TestPodPrivilege(t *testing.T) { | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Equal(t, true, *pod.Spec.SecurityContext.RunAsNonRoot) | ||||
| } | ||||
|  | ||||
| func TestScratchPod(t *testing.T) { | ||||
| 	expected := ` | ||||
| 	{ | ||||
| 		"metadata": { | ||||
| 			"name": "wp-01he8bebctabr3kgk0qj36d2me-0", | ||||
| 			"namespace": "woodpecker", | ||||
| 			"creationTimestamp": null, | ||||
| 			"labels": { | ||||
| 				"step": "curl-google" | ||||
| 			} | ||||
| 		}, | ||||
| 		"spec": { | ||||
| 			"containers": [ | ||||
| 				{ | ||||
| 					"name": "wp-01he8bebctabr3kgk0qj36d2me-0", | ||||
| 					"image": "quay.io/curl/curl", | ||||
| 					"command": [ | ||||
| 						"/usr/bin/curl", | ||||
| 						"-v", | ||||
| 						"google.com" | ||||
| 					], | ||||
| 					"resources": {} | ||||
| 				} | ||||
| 			], | ||||
| 			"restartPolicy": "Never" | ||||
| 		}, | ||||
| 		"status": {} | ||||
| 	}` | ||||
|  | ||||
| 	pod, err := mkPod(&types.Step{ | ||||
| 		Name:       "curl-google", | ||||
| 		Image:      "quay.io/curl/curl", | ||||
| 		Entrypoint: []string{"/usr/bin/curl", "-v", "google.com"}, | ||||
| 	}, &config{ | ||||
| 		Namespace: "woodpecker", | ||||
| 	}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}) | ||||
| 	assert.NoError(t, err) | ||||
|  | ||||
| 	podJSON, err := json.Marshal(pod) | ||||
| 	assert.NoError(t, err) | ||||
|  | ||||
| 	ja := jsonassert.New(t) | ||||
| 	t.Log(string(podJSON)) | ||||
| 	ja.Assertf(string(podJSON), expected) | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,14 @@ steps: | ||||
|     image: golang | ||||
|     commands: go test | ||||
|  | ||||
|   entrypoint: | ||||
|     image: alpine | ||||
|     entrypoint: ['some_entry', '--some-flag'] | ||||
|  | ||||
|   singla-entrypoint: | ||||
|     image: alpine | ||||
|     entrypoint: some_entry | ||||
|  | ||||
|   commands: | ||||
|     privileged: true | ||||
|     image: golang | ||||
|   | ||||
| @@ -371,6 +371,21 @@ | ||||
|         }, | ||||
|         "backend_options": { | ||||
|           "$ref": "#/definitions/step_backend_options" | ||||
|         }, | ||||
|         "entrypoint": { | ||||
|           "description": "Defines container entrypoint.", | ||||
|           "oneOf": [ | ||||
|             { | ||||
|               "type": "array", | ||||
|               "minLength": 1, | ||||
|               "items": { | ||||
|                 "type": "string" | ||||
|               } | ||||
|             }, | ||||
|             { | ||||
|               "type": "string" | ||||
|             } | ||||
|           ] | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user