From 5699d22a553021610414c07934b1018adbc40caa Mon Sep 17 00:00:00 2001 From: Lauris BH Date: Thu, 14 Nov 2024 23:23:42 +0200 Subject: [PATCH] Add server configuration option to add default set of labels for workflows that has no labels specified (#4326) --- cmd/server/flags.go | 5 ++++ cmd/server/setup.go | 11 +++++++ .../30-administration/10-server-config.md | 8 +++++ server/config.go | 1 + server/pipeline/items.go | 21 ++++++------- server/pipeline/stepbuilder/stepBuilder.go | 30 +++++++++++-------- 6 files changed, 53 insertions(+), 23 deletions(-) diff --git a/cmd/server/flags.go b/cmd/server/flags.go index 2ad82b9ac..6ef1f37f0 100644 --- a/cmd/server/flags.go +++ b/cmd/server/flags.go @@ -173,6 +173,11 @@ var flags = append([]cli.Flag{ Usage: "The maximum time in minutes you can set in the repo settings before a pipeline gets killed", Value: 120, }, + &cli.StringSliceFlag{ + Sources: cli.EnvVars("WOODPECKER_DEFAULT_WORKFLOW_LABELS"), + Name: "default-workflow-labels", + Usage: "The default label filter to set for workflows that has no label filter set. By default workflows will be allowed to run on any agent, if not specified in the workflow.", + }, &cli.DurationFlag{ Sources: cli.EnvVars("WOODPECKER_SESSION_EXPIRES"), Name: "session-expires", diff --git a/cmd/server/setup.go b/cmd/server/setup.go index 608a5ba14..d682e31cf 100644 --- a/cmd/server/setup.go +++ b/cmd/server/setup.go @@ -188,6 +188,17 @@ func setupEvilGlobals(ctx context.Context, c *cli.Command, s store.Store) (err e server.Config.Pipeline.DefaultTimeout = c.Int("default-pipeline-timeout") server.Config.Pipeline.MaxTimeout = c.Int("max-pipeline-timeout") + _labels := c.StringSlice("default-workflow-labels") + labels := make(map[string]string, len(_labels)) + for _, v := range _labels { + name, value, ok := strings.Cut(v, "=") + if !ok { + return fmt.Errorf("invalid label filter: %s", v) + } + labels[name] = value + } + server.Config.Pipeline.DefaultWorkflowLabels = labels + // backend options for pipeline compiler server.Config.Pipeline.Proxy.No = c.String("backend-no-proxy") server.Config.Pipeline.Proxy.HTTP = c.String("backend-http-proxy") diff --git a/docs/docs/30-administration/10-server-config.md b/docs/docs/30-administration/10-server-config.md index 6b9297f6a..2556ef664 100644 --- a/docs/docs/30-administration/10-server-config.md +++ b/docs/docs/30-administration/10-server-config.md @@ -357,6 +357,14 @@ The default docker image to be used when cloning the repo. It is also added to the trusted clone plugin list. +### `WOODPECKER_DEFAULT_WORKFLOW_LABELS` + +> By default run workflows on any agent if no label conditions are set in workflow definition. + +You can specify default label/platform conditions that will be used for agent selection for workflows that does not have labels conditions set. + +Example: `platform=linux/amd64,backend=docker` + ### `WOODPECKER_DEFAULT_PIPELINE_TIMEOUT` > 60 (minutes) diff --git a/server/config.go b/server/config.go index 3349e535b..d9c8bee30 100644 --- a/server/config.go +++ b/server/config.go @@ -67,6 +67,7 @@ var Config = struct { Pipeline struct { AuthenticatePublicRepos bool DefaultCancelPreviousPipelineEvents []model.WebhookEvent + DefaultWorkflowLabels map[string]string DefaultClonePlugin string TrustedClonePlugins []string Volumes []string diff --git a/server/pipeline/items.go b/server/pipeline/items.go index 70e31f348..c34ffa96e 100644 --- a/server/pipeline/items.go +++ b/server/pipeline/items.go @@ -72,16 +72,17 @@ func parsePipeline(forge forge.Forge, store store.Store, currentPipeline *model. } b := stepbuilder.StepBuilder{ - Repo: repo, - Curr: currentPipeline, - Prev: prev, - Netrc: netrc, - Secs: secs, - Regs: regs, - Envs: envs, - Host: server.Config.Server.Host, - Yamls: yamls, - Forge: forge, + Repo: repo, + Curr: currentPipeline, + Prev: prev, + Netrc: netrc, + Secs: secs, + Regs: regs, + Envs: envs, + Host: server.Config.Server.Host, + Yamls: yamls, + Forge: forge, + DefaultLabels: server.Config.Pipeline.DefaultWorkflowLabels, ProxyOpts: compiler.ProxyOptions{ NoProxy: server.Config.Pipeline.Proxy.No, HTTPProxy: server.Config.Pipeline.Proxy.HTTP, diff --git a/server/pipeline/stepbuilder/stepBuilder.go b/server/pipeline/stepbuilder/stepBuilder.go index 8adc1d71b..c628fe83c 100644 --- a/server/pipeline/stepbuilder/stepBuilder.go +++ b/server/pipeline/stepbuilder/stepBuilder.go @@ -17,6 +17,7 @@ package stepbuilder import ( "fmt" + "maps" "path/filepath" "strings" @@ -40,17 +41,18 @@ import ( // StepBuilder Takes the hook data and the yaml and returns in internal data model. type StepBuilder struct { - Repo *model.Repo - Curr *model.Pipeline - Prev *model.Pipeline - Netrc *model.Netrc - Secs []*model.Secret - Regs []*model.Registry - Host string - Yamls []*forge_types.FileMeta - Envs map[string]string - Forge metadata.ServerForge - ProxyOpts compiler.ProxyOptions + Repo *model.Repo + Curr *model.Pipeline + Prev *model.Pipeline + Netrc *model.Netrc + Secs []*model.Secret + Regs []*model.Registry + Host string + Yamls []*forge_types.FileMeta + Envs map[string]string + Forge metadata.ServerForge + DefaultLabels map[string]string + ProxyOpts compiler.ProxyOptions } type Item struct { @@ -186,8 +188,10 @@ func (b *StepBuilder) genItemForWorkflow(workflow *model.Workflow, axis matrix.A DependsOn: parsed.DependsOn, RunsOn: parsed.RunsOn, } - if item.Labels == nil { - item.Labels = map[string]string{} + if len(item.Labels) == 0 { + item.Labels = make(map[string]string, len(b.DefaultLabels)) + // Set default labels if no labels are defined in the pipeline + maps.Copy(item.Labels, b.DefaultLabels) } return item, errorsAndWarnings