mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-22 16:36:30 +00:00
Support custom steps entrypoint (#2985)
Closes https://github.com/woodpecker-ci/woodpecker/issues/278 --------- Co-authored-by: Anbraten <anton@ju60.de> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
parent
9f215ab932
commit
d1d2e9723d
11 changed files with 32 additions and 10 deletions
|
@ -156,6 +156,10 @@ docker run --entrypoint=build.sh golang
|
|||
Only build steps can define commands. You cannot use commands with plugins or services.
|
||||
:::
|
||||
|
||||
### `entrypoint`
|
||||
|
||||
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"]`).
|
||||
|
||||
### `environment`
|
||||
|
||||
Woodpecker provides the ability to pass environment variables to individual steps.
|
||||
|
|
|
@ -18,20 +18,20 @@ import (
|
|||
"encoding/base64"
|
||||
)
|
||||
|
||||
func GenerateContainerConf(commands []string, goos string) (env map[string]string, entry, cmd []string) {
|
||||
func GenerateContainerConf(commands []string, goos string) (env map[string]string, entry []string, cmd 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 = []string{"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}
|
||||
cmd = "[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 = []string{"echo $CI_SCRIPT | base64 -d | /bin/sh -e"}
|
||||
cmd = "echo $CI_SCRIPT | base64 -d | /bin/sh -e"
|
||||
}
|
||||
|
||||
return env, entry, cmd
|
||||
|
|
|
@ -17,11 +17,11 @@ func TestGenerateContainerConf(t *testing.T) {
|
|||
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, []string{"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}, gotCmd)
|
||||
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, 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, []string{"echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, gotCmd)
|
||||
assert.Equal(t, "echo $CI_SCRIPT | base64 -d | /bin/sh -e", gotCmd)
|
||||
}
|
||||
|
|
|
@ -47,8 +47,11 @@ func (e *docker) toConfig(step *types.Step) *container.Config {
|
|||
for k, v := range env {
|
||||
configEnv[k] = v
|
||||
}
|
||||
if len(step.Entrypoint) > 0 {
|
||||
entry = step.Entrypoint
|
||||
}
|
||||
config.Entrypoint = entry
|
||||
config.Cmd = cmd
|
||||
config.Cmd = []string{cmd}
|
||||
}
|
||||
|
||||
if len(configEnv) != 0 {
|
||||
|
|
|
@ -129,8 +129,11 @@ func podContainer(step *types.Step, podName, goos string) (v1.Container, error)
|
|||
|
||||
if len(step.Commands) != 0 {
|
||||
scriptEnv, command, args := common.GenerateContainerConf(step.Commands, goos)
|
||||
if len(step.Entrypoint) > 0 {
|
||||
command = step.Entrypoint
|
||||
}
|
||||
container.Command = command
|
||||
container.Args = args
|
||||
container.Args = []string{args}
|
||||
maps.Copy(step.Environment, scriptEnv)
|
||||
}
|
||||
|
||||
|
|
|
@ -310,6 +310,7 @@ func TestFullPod(t *testing.T) {
|
|||
Pull: true,
|
||||
Privileged: true,
|
||||
Commands: []string{"go get", "go test"},
|
||||
Entrypoint: []string{"/bin/sh", "-c"},
|
||||
Volumes: []string{"woodpecker-cache:/woodpecker/src/cache"},
|
||||
Environment: map[string]string{"CGO": "0"},
|
||||
ExtraHosts: hostAliases,
|
||||
|
|
|
@ -146,6 +146,7 @@ func (e *local) StartStep(ctx context.Context, step *types.Step, taskUUID string
|
|||
// execCommands use step.Image as shell and run the commands in it
|
||||
func (e *local) execCommands(ctx context.Context, step *types.Step, state *workflowState, env []string) error {
|
||||
// Prepare commands
|
||||
// TODO support `entrypoint` from pipeline config
|
||||
args, err := e.genCmdByShell(step.Image, step.Commands)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert commands into args: %w", err)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
package metadata
|
||||
|
||||
// Event types corresponding to scm hooks.
|
||||
// Event types corresponding to forge hooks.
|
||||
const (
|
||||
EventPush = "push"
|
||||
EventPull = "pull_request"
|
||||
|
|
|
@ -185,6 +185,7 @@ func (c *Compiler) createProcess(container *yaml_types.Container, stepType backe
|
|||
WorkingDir: workingdir,
|
||||
Environment: environment,
|
||||
Commands: container.Commands,
|
||||
Entrypoint: container.Entrypoint,
|
||||
ExtraHosts: extraHosts,
|
||||
Volumes: volumes,
|
||||
Tmpfs: container.Tmpfs,
|
||||
|
|
|
@ -35,6 +35,7 @@ type (
|
|||
Container struct {
|
||||
BackendOptions BackendOptions `yaml:"backend_options,omitempty"`
|
||||
Commands base.StringOrSlice `yaml:"commands,omitempty"`
|
||||
Entrypoint base.StringOrSlice `yaml:"entrypoint,omitempty"`
|
||||
Detached bool `yaml:"detach,omitempty"`
|
||||
Directory string `yaml:"directory,omitempty"`
|
||||
Environment base.SliceOrMap `yaml:"environment,omitempty"`
|
||||
|
@ -50,7 +51,7 @@ type (
|
|||
Ports []string `yaml:"ports,omitempty"`
|
||||
DependsOn base.StringOrSlice `yaml:"depends_on,omitempty"`
|
||||
|
||||
// Docker Specific
|
||||
// Docker and Kubernetes Specific
|
||||
Privileged bool `yaml:"privileged,omitempty"`
|
||||
|
||||
// Undocumented
|
||||
|
@ -119,7 +120,7 @@ func (c *ContainerList) UnmarshalYAML(value *yaml.Node) error {
|
|||
}
|
||||
|
||||
func (c *Container) IsPlugin() bool {
|
||||
return len(c.Commands) == 0
|
||||
return len(c.Commands) == 0 && len(c.Entrypoint) == 0
|
||||
}
|
||||
|
||||
func (c *Container) IsTrustedCloneImage() bool {
|
||||
|
|
|
@ -39,6 +39,7 @@ devices:
|
|||
directory: example/
|
||||
dns: 8.8.8.8
|
||||
dns_search: example.com
|
||||
entrypoint: [/bin/sh, -c]
|
||||
environment:
|
||||
- RACK_ENV=development
|
||||
- SHOW=true
|
||||
|
@ -86,6 +87,7 @@ func TestUnmarshalContainer(t *testing.T) {
|
|||
Directory: "example/",
|
||||
DNS: base.StringOrSlice{"8.8.8.8"},
|
||||
DNSSearch: base.StringOrSlice{"example.com"},
|
||||
Entrypoint: []string{"/bin/sh", "-c"},
|
||||
Environment: base.SliceOrMap{"RACK_ENV": "development", "SHOW": "true"},
|
||||
ExtraHosts: []string{"somehost:162.242.195.82", "otherhost:50.31.209.229", "ipv6:2001:db8::10"},
|
||||
Image: "golang:latest",
|
||||
|
@ -308,4 +310,10 @@ func TestIsPlugin(t *testing.T) {
|
|||
assert.False(t, (&Container{
|
||||
Commands: base.StringOrSlice(strslice.StrSlice{"echo 'this is not a plugin'"}),
|
||||
}).IsPlugin())
|
||||
assert.True(t, (&Container{
|
||||
Entrypoint: base.StringOrSlice(strslice.StrSlice{}),
|
||||
}).IsPlugin())
|
||||
assert.False(t, (&Container{
|
||||
Entrypoint: base.StringOrSlice(strslice.StrSlice{"echo 'this is not a plugin'"}),
|
||||
}).IsPlugin())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue