diff --git a/cmd/server/flags.go b/cmd/server/flags.go index e8dd26390..dff3b83cd 100644 --- a/cmd/server/flags.go +++ b/cmd/server/flags.go @@ -206,6 +206,12 @@ var flags = []cli.Flag{ Usage: "status context prefix", Value: "ci/woodpecker", }, + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_STATUS_CONTEXT_FORMAT"}, + Name: "status-context-format", + Usage: "status context format", + Value: "{{ .context }}/{{ .event }}/{{ .pipeline }}", + }, // // resource limit parameters // diff --git a/cmd/server/server.go b/cmd/server/server.go index 466f9ff0c..08759e69c 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -317,6 +317,7 @@ func setupEvilGlobals(c *cli.Context, v store.Store, r remote.Remote) { server.Config.Server.Port = c.String("server-addr") server.Config.Server.Docs = c.String("docs") server.Config.Server.StatusContext = c.String("status-context") + server.Config.Server.StatusContextFormat = c.String("status-context-format") server.Config.Server.SessionExpires = c.Duration("session-expires") server.Config.Pipeline.Networks = c.StringSlice("network") server.Config.Pipeline.Volumes = c.StringSlice("volume") diff --git a/docs/docs/30-administration/10-server-config.md b/docs/docs/30-administration/10-server-config.md index 1044c5ec7..87abbf8e6 100644 --- a/docs/docs/30-administration/10-server-config.md +++ b/docs/docs/30-administration/10-server-config.md @@ -305,6 +305,17 @@ Read the value for `WOODPECKER_PROMETHEUS_AUTH_TOKEN` from the specified filepat Context prefix Woodpecker will use to publish status messages to SCM. You probably will only need to change it if you run multiple Woodpecker instances for a single repository. +### `WOODPECKER_STATUS_CONTEXT_FORMAT` +> Default: `{{ .context }}/{{ .event }}/{{ .pipeline }}` + +Template for the status messages published to forges, uses [Go templates](https://pkg.go.dev/text/template) as template language. +Supported variables: +- `context`: Woodpecker's context (see `WOODPECKER_STATUS_CONTEXT`) +- `event`: the event which started the pipeline +- `pipeline`: the pipeline's name +- `owner`: the repo's owner +- `repo`: the repo's name + --- ### `WOODPECKER_LIMIT_MEM_SWAP` diff --git a/server/config.go b/server/config.go index 314994042..4176fb11a 100644 --- a/server/config.go +++ b/server/config.go @@ -51,15 +51,16 @@ var Config = struct { // Secrets model.SecretStore } Server struct { - Key string - Cert string - OAuthHost string - Host string - Port string - Pass string - Docs string - StatusContext string - SessionExpires time.Duration + Key string + Cert string + OAuthHost string + Host string + Port string + Pass string + Docs string + StatusContext string + StatusContextFormat string + SessionExpires time.Duration // Open bool // Orgs map[string]struct{} // Admins map[string]struct{} diff --git a/server/remote/common/status.go b/server/remote/common/status.go index 106f05489..0e725ed11 100644 --- a/server/remote/common/status.go +++ b/server/remote/common/status.go @@ -1,32 +1,41 @@ package common import ( + "bytes" "fmt" + "text/template" "github.com/woodpecker-ci/woodpecker/server" "github.com/woodpecker-ci/woodpecker/server/model" ) func GetBuildStatusContext(repo *model.Repo, build *model.Build, proc *model.Proc) string { - name := server.Config.Server.StatusContext - + event := string(build.Event) switch build.Event { case model.EventPull: - name += "/pr" - default: - if len(build.Event) > 0 { - name += "/" + string(build.Event) - } + event = "pr" } - if proc != nil { - name += "/" + proc.Name + tmpl, err := template.New("context").Parse(server.Config.Server.StatusContextFormat) + if err != nil { + return "" + } + var ctx bytes.Buffer + err = tmpl.Execute(&ctx, map[string]interface{}{ + "context": server.Config.Server.StatusContext, + "event": event, + "pipeline": proc.Name, + "owner": repo.Owner, + "repo": repo.Name, + }) + if err != nil { + return "" } - return name + return ctx.String() } -// getBuildStatusDescription is a helper function that generates a description +// GetBuildStatusDescription is a helper function that generates a description // message for the current build status. func GetBuildStatusDescription(status model.StatusValue) string { switch status { diff --git a/server/remote/common/status_test.go b/server/remote/common/status_test.go new file mode 100644 index 000000000..c25c2168a --- /dev/null +++ b/server/remote/common/status_test.go @@ -0,0 +1,35 @@ +package common + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/woodpecker-ci/woodpecker/server" + "github.com/woodpecker-ci/woodpecker/server/model" +) + +func TestGetBuildStatusContext(t *testing.T) { + origFormat := server.Config.Server.StatusContextFormat + origCtx := server.Config.Server.StatusContext + defer func() { + server.Config.Server.StatusContextFormat = origFormat + server.Config.Server.StatusContext = origCtx + }() + + repo := &model.Repo{Owner: "user1", Name: "repo1"} + build := &model.Build{Event: model.EventPull} + proc := &model.Proc{Name: "lint"} + + assert.EqualValues(t, "", GetBuildStatusContext(repo, build, proc)) + + server.Config.Server.StatusContext = "ci/woodpecker" + server.Config.Server.StatusContextFormat = "{{ .context }}/{{ .event }}/{{ .pipeline }}" + assert.EqualValues(t, "ci/woodpecker/pr/lint", GetBuildStatusContext(repo, build, proc)) + build.Event = model.EventPush + assert.EqualValues(t, "ci/woodpecker/push/lint", GetBuildStatusContext(repo, build, proc)) + + server.Config.Server.StatusContext = "ci" + server.Config.Server.StatusContextFormat = "{{ .context }}:{{ .owner }}/{{ .repo }}:{{ .event }}:{{ .pipeline }}" + assert.EqualValues(t, "ci:user1/repo1:push:lint", GetBuildStatusContext(repo, build, proc)) +}