mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-06-07 09:58:51 +00:00
Remove old pipeline options (#4016)
This commit is contained in:
parent
8251ec198b
commit
aafd217cce
19 changed files with 100 additions and 574 deletions
|
@ -6,15 +6,15 @@ Some versions need some changes to the server configuration or the pipeline conf
|
||||||
|
|
||||||
- Removed `WOODPECKER_DEV_OAUTH_HOST` and `WOODPECKER_DEV_GITEA_OAUTH_URL` use `WOODPECKER_EXPERT_FORGE_OAUTH_HOST`
|
- Removed `WOODPECKER_DEV_OAUTH_HOST` and `WOODPECKER_DEV_GITEA_OAUTH_URL` use `WOODPECKER_EXPERT_FORGE_OAUTH_HOST`
|
||||||
- Compatibility mode of deprecated `pipeline:`, `platform:` and `branches:` pipeline config options are now removed and pipeline will now fail if still in use.
|
- Compatibility mode of deprecated `pipeline:`, `platform:` and `branches:` pipeline config options are now removed and pipeline will now fail if still in use.
|
||||||
- Deprecated `steps.[name].group` in favor of `steps.[name].depends_on` (see [workflow syntax](./20-usage/20-workflow-syntax.md#depends_on) to learn how to set dependencies)
|
- Removed `steps.[name].group` in favor of `steps.[name].depends_on` (see [workflow syntax](./20-usage/20-workflow-syntax.md#depends_on) to learn how to set dependencies)
|
||||||
- Removed `WOODPECKER_ROOT_PATH` and `WOODPECKER_ROOT_URL` config variables. Use `WOODPECKER_HOST` with a path instead
|
- Removed `WOODPECKER_ROOT_PATH` and `WOODPECKER_ROOT_URL` config variables. Use `WOODPECKER_HOST` with a path instead
|
||||||
- Pipelines without a config file will now be skipped instead of failing
|
- Pipelines without a config file will now be skipped instead of failing
|
||||||
- Removed implicitly defined `regcred` image pull secret name. Set it explicitly via `WOODPECKER_BACKEND_K8S_PULL_SECRET_NAMES`
|
- Removed implicitly defined `regcred` image pull secret name. Set it explicitly via `WOODPECKER_BACKEND_K8S_PULL_SECRET_NAMES`
|
||||||
- Deprecated `includes` and `excludes` support from **event** filter
|
- Removed `includes` and `excludes` support from **event** filter
|
||||||
- Deprecated uppercasing all secret env vars, instead, the value of the `secrets` property is used. [Read more](./20-usage/40-secrets.md#use-secrets-in-commands)
|
- Removed uppercasing all secret env vars, instead, the value of the `secrets` property is used. [Read more](./20-usage/40-secrets.md#use-secrets-in-commands)
|
||||||
- Deprecated alternative names for secrets, use `environment` with `from_secret`
|
- Removed alternative names for secrets, use `environment` with `from_secret`
|
||||||
- Deprecated slice definition for env vars
|
- Removed slice definition for env vars
|
||||||
- Deprecated `environment` filter, use `when.evaluate`
|
- Removed `environment` filter, use `when.evaluate`
|
||||||
- Removed `WOODPECKER_WEBHOOK_HOST` in favor of `WOODPECKER_EXPERT_WEBHOOK_HOST`
|
- Removed `WOODPECKER_WEBHOOK_HOST` in favor of `WOODPECKER_EXPERT_WEBHOOK_HOST`
|
||||||
- Migrated to rfc9421 for webhook signatures
|
- Migrated to rfc9421 for webhook signatures
|
||||||
- Renamed `start_time`, `end_time`, `created_at`, `started_at`, `finished_at` and `reviewed_at` JSON fields to `started`, `finished`, `created`, `started`, `finished`, `reviewed`
|
- Renamed `start_time`, `end_time`, `created_at`, `started_at`, `finished_at` and `reviewed_at` JSON fields to `started`, `finished`, `created`, `started`, `finished`, `reviewed`
|
||||||
|
|
|
@ -275,7 +275,6 @@ func (c *Compiler) Compile(conf *yaml_types.Workflow) (*backend_types.Config, er
|
||||||
step: step,
|
step: step,
|
||||||
position: pos,
|
position: pos,
|
||||||
name: container.Name,
|
name: container.Name,
|
||||||
group: container.Group,
|
|
||||||
dependsOn: container.DependsOn,
|
dependsOn: container.DependsOn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,63 +150,65 @@ func TestCompilerCompile(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "workflow with three steps and one group",
|
name: "workflow with three steps",
|
||||||
fronConf: &yaml_types.Workflow{Steps: yaml_types.ContainerList{ContainerList: []*yaml_types.Container{{
|
fronConf: &yaml_types.Workflow{Steps: yaml_types.ContainerList{ContainerList: []*yaml_types.Container{{
|
||||||
Name: "echo env",
|
Name: "echo env",
|
||||||
Image: "bash",
|
Image: "bash",
|
||||||
Commands: []string{"env"},
|
Commands: []string{"env"},
|
||||||
}, {
|
}, {
|
||||||
Name: "parallel echo 1",
|
Name: "parallel echo 1",
|
||||||
Group: "parallel",
|
|
||||||
Image: "bash",
|
Image: "bash",
|
||||||
Commands: []string{"echo 1"},
|
Commands: []string{"echo 1"},
|
||||||
}, {
|
}, {
|
||||||
Name: "parallel echo 2",
|
Name: "parallel echo 2",
|
||||||
Group: "parallel",
|
|
||||||
Image: "bash",
|
Image: "bash",
|
||||||
Commands: []string{"echo 2"},
|
Commands: []string{"echo 2"},
|
||||||
}}}},
|
}}}},
|
||||||
backConf: &backend_types.Config{
|
backConf: &backend_types.Config{
|
||||||
Networks: defaultNetworks,
|
Networks: defaultNetworks,
|
||||||
Volumes: defaultVolumes,
|
Volumes: defaultVolumes,
|
||||||
Stages: []*backend_types.Stage{defaultCloneStage, {
|
Stages: []*backend_types.Stage{
|
||||||
Steps: []*backend_types.Step{{
|
defaultCloneStage, {
|
||||||
Name: "echo env",
|
Steps: []*backend_types.Step{{
|
||||||
Type: backend_types.StepTypeCommands,
|
Name: "echo env",
|
||||||
Image: "bash",
|
Type: backend_types.StepTypeCommands,
|
||||||
Commands: []string{"env"},
|
Image: "bash",
|
||||||
OnSuccess: true,
|
Commands: []string{"env"},
|
||||||
Failure: "fail",
|
OnSuccess: true,
|
||||||
Volumes: []string{defaultVolumes[0].Name + ":/test"},
|
Failure: "fail",
|
||||||
WorkingDir: "/test/src/github.com/octocat/hello-world",
|
Volumes: []string{defaultVolumes[0].Name + ":/test"},
|
||||||
Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo env"}}},
|
WorkingDir: "/test/src/github.com/octocat/hello-world",
|
||||||
ExtraHosts: []backend_types.HostAlias{},
|
Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo env"}}},
|
||||||
}},
|
ExtraHosts: []backend_types.HostAlias{},
|
||||||
}, {
|
}},
|
||||||
Steps: []*backend_types.Step{{
|
|
||||||
Name: "parallel echo 1",
|
|
||||||
Type: backend_types.StepTypeCommands,
|
|
||||||
Image: "bash",
|
|
||||||
Commands: []string{"echo 1"},
|
|
||||||
OnSuccess: true,
|
|
||||||
Failure: "fail",
|
|
||||||
Volumes: []string{defaultVolumes[0].Name + ":/test"},
|
|
||||||
WorkingDir: "/test/src/github.com/octocat/hello-world",
|
|
||||||
Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 1"}}},
|
|
||||||
ExtraHosts: []backend_types.HostAlias{},
|
|
||||||
}, {
|
}, {
|
||||||
Name: "parallel echo 2",
|
Steps: []*backend_types.Step{{
|
||||||
Type: backend_types.StepTypeCommands,
|
Name: "parallel echo 1",
|
||||||
Image: "bash",
|
Type: backend_types.StepTypeCommands,
|
||||||
Commands: []string{"echo 2"},
|
Image: "bash",
|
||||||
OnSuccess: true,
|
Commands: []string{"echo 1"},
|
||||||
Failure: "fail",
|
OnSuccess: true,
|
||||||
Volumes: []string{defaultVolumes[0].Name + ":/test"},
|
Failure: "fail",
|
||||||
WorkingDir: "/test/src/github.com/octocat/hello-world",
|
Volumes: []string{defaultVolumes[0].Name + ":/test"},
|
||||||
Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 2"}}},
|
WorkingDir: "/test/src/github.com/octocat/hello-world",
|
||||||
ExtraHosts: []backend_types.HostAlias{},
|
Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 1"}}},
|
||||||
}},
|
ExtraHosts: []backend_types.HostAlias{},
|
||||||
}},
|
}},
|
||||||
|
}, {
|
||||||
|
Steps: []*backend_types.Step{{
|
||||||
|
Name: "parallel echo 2",
|
||||||
|
Type: backend_types.StepTypeCommands,
|
||||||
|
Image: "bash",
|
||||||
|
Commands: []string{"echo 2"},
|
||||||
|
OnSuccess: true,
|
||||||
|
Failure: "fail",
|
||||||
|
Volumes: []string{defaultVolumes[0].Name + ":/test"},
|
||||||
|
WorkingDir: "/test/src/github.com/octocat/hello-world",
|
||||||
|
Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 2"}}},
|
||||||
|
ExtraHosts: []backend_types.HostAlias{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -274,7 +276,7 @@ func TestCompilerCompile(t *testing.T) {
|
||||||
Name: "step",
|
Name: "step",
|
||||||
Image: "bash",
|
Image: "bash",
|
||||||
Commands: []string{"env"},
|
Commands: []string{"env"},
|
||||||
Secrets: yaml_types.Secrets{Secrets: []*yaml_types.Secret{{Source: "missing", Target: "missing"}}},
|
Secrets: []string{"missing"},
|
||||||
}}}},
|
}}}},
|
||||||
backConf: nil,
|
backConf: nil,
|
||||||
expectedErr: "secret \"missing\" not found",
|
expectedErr: "secret \"missing\" not found",
|
||||||
|
|
|
@ -125,20 +125,17 @@ func (c *Compiler) createProcess(container *yaml_types.Container, stepType backe
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, requested := range container.Secrets.Secrets {
|
for _, requested := range container.Secrets {
|
||||||
secretValue, err := getSecretValue(requested.Source)
|
secretValue, err := getSecretValue(requested)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
toUpperTarget := strings.ToUpper(requested.Target)
|
if !environmentAllowed(requested, stepType) {
|
||||||
if !environmentAllowed(toUpperTarget, stepType) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
environment[requested.Target] = secretValue
|
environment[requested] = secretValue
|
||||||
// TODO: deprecated, remove in 3.x
|
|
||||||
environment[toUpperTarget] = secretValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if utils.MatchImage(container.Image, c.escalated...) && container.IsPlugin() {
|
if utils.MatchImage(container.Image, c.escalated...) && container.IsPlugin() {
|
||||||
|
|
|
@ -24,7 +24,6 @@ type dagCompilerStep struct {
|
||||||
step *backend_types.Step
|
step *backend_types.Step
|
||||||
position int
|
position int
|
||||||
name string
|
name string
|
||||||
group string
|
|
||||||
dependsOn []string
|
dependsOn []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,25 +50,16 @@ func (c dagCompiler) compile() ([]*backend_types.Stage, error) {
|
||||||
if c.isDAG() {
|
if c.isDAG() {
|
||||||
return c.compileByDependsOn()
|
return c.compileByDependsOn()
|
||||||
}
|
}
|
||||||
return c.compileByGroup()
|
return c.compileSequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c dagCompiler) compileByGroup() ([]*backend_types.Stage, error) {
|
func (c dagCompiler) compileSequence() ([]*backend_types.Stage, error) {
|
||||||
stages := make([]*backend_types.Stage, 0, len(c.steps))
|
stages := make([]*backend_types.Stage, 0, len(c.steps))
|
||||||
var currentStage *backend_types.Stage
|
|
||||||
var currentGroup string
|
|
||||||
|
|
||||||
for _, s := range c.steps {
|
for _, s := range c.steps {
|
||||||
// create a new stage if current step is in a new group compared to last one
|
stages = append(stages, &backend_types.Stage{
|
||||||
if currentStage == nil || currentGroup != s.group || s.group == "" {
|
Steps: []*backend_types.Step{s.step},
|
||||||
currentGroup = s.group
|
})
|
||||||
|
|
||||||
currentStage = new(backend_types.Stage)
|
|
||||||
stages = append(stages, currentStage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add step to current stage
|
|
||||||
currentStage.Steps = append(currentStage.Steps, s.step)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stages, nil
|
return stages, nil
|
||||||
|
|
|
@ -85,7 +85,6 @@ func TestConvertDAGToStages(t *testing.T) {
|
||||||
"echo env": {
|
"echo env": {
|
||||||
position: 0,
|
position: 0,
|
||||||
name: "echo env",
|
name: "echo env",
|
||||||
group: "",
|
|
||||||
step: &backend_types.Step{
|
step: &backend_types.Step{
|
||||||
UUID: "01HJDPEW6R7J0JBE3F1T7Q0TYX",
|
UUID: "01HJDPEW6R7J0JBE3F1T7Q0TYX",
|
||||||
Type: "commands",
|
Type: "commands",
|
||||||
|
@ -96,7 +95,6 @@ func TestConvertDAGToStages(t *testing.T) {
|
||||||
"echo 1": {
|
"echo 1": {
|
||||||
position: 1,
|
position: 1,
|
||||||
name: "echo 1",
|
name: "echo 1",
|
||||||
group: "",
|
|
||||||
dependsOn: []string{"echo env", "echo 2"},
|
dependsOn: []string{"echo env", "echo 2"},
|
||||||
step: &backend_types.Step{
|
step: &backend_types.Step{
|
||||||
UUID: "01HJDPF770QGRZER8RF79XVS4M",
|
UUID: "01HJDPF770QGRZER8RF79XVS4M",
|
||||||
|
@ -108,7 +106,6 @@ func TestConvertDAGToStages(t *testing.T) {
|
||||||
"echo 2": {
|
"echo 2": {
|
||||||
position: 2,
|
position: 2,
|
||||||
name: "echo 2",
|
name: "echo 2",
|
||||||
group: "",
|
|
||||||
step: &backend_types.Step{
|
step: &backend_types.Step{
|
||||||
UUID: "01HJDPFF5RMEYZW0YTGR1Y1ZR0",
|
UUID: "01HJDPFF5RMEYZW0YTGR1Y1ZR0",
|
||||||
Type: "commands",
|
Type: "commands",
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"path"
|
"path"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/bmatcuk/doublestar/v4"
|
"github.com/bmatcuk/doublestar/v4"
|
||||||
|
@ -37,20 +38,18 @@ type (
|
||||||
}
|
}
|
||||||
|
|
||||||
Constraint struct {
|
Constraint struct {
|
||||||
Ref List
|
Ref List
|
||||||
Repo List
|
Repo List
|
||||||
Instance List
|
Instance List
|
||||||
Platform List
|
Platform List
|
||||||
Environment List
|
Branch List
|
||||||
Branch List
|
Cron List
|
||||||
Cron List
|
Status List
|
||||||
Status List
|
Matrix Map
|
||||||
Matrix Map
|
Local yamlBaseTypes.BoolTrue
|
||||||
Local yamlBaseTypes.BoolTrue
|
Path Path
|
||||||
Path Path
|
Evaluate string `yaml:"evaluate,omitempty"`
|
||||||
Evaluate string `yaml:"evaluate,omitempty"`
|
Event yamlBaseTypes.StringOrSlice
|
||||||
// TODO: change to StringOrSlice in 3.x
|
|
||||||
Event List
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List defines a runtime constraint for exclude & include string slices.
|
// List defines a runtime constraint for exclude & include string slices.
|
||||||
|
@ -164,8 +163,7 @@ func (c *Constraint) Match(m metadata.Metadata, global bool, env map[string]stri
|
||||||
}
|
}
|
||||||
|
|
||||||
match = match && c.Platform.Match(m.Sys.Platform) &&
|
match = match && c.Platform.Match(m.Sys.Platform) &&
|
||||||
c.Environment.Match(m.Curr.DeployTo) &&
|
(len(c.Event) == 0 || slices.Contains(c.Event, m.Curr.Event)) &&
|
||||||
c.Event.Match(m.Curr.Event) &&
|
|
||||||
c.Repo.Match(path.Join(m.Repo.Owner, m.Repo.Name)) &&
|
c.Repo.Match(path.Join(m.Repo.Owner, m.Repo.Name)) &&
|
||||||
c.Ref.Match(m.Curr.Commit.Ref) &&
|
c.Ref.Match(m.Curr.Commit.Ref) &&
|
||||||
c.Instance.Match(m.Sys.Host)
|
c.Instance.Match(m.Sys.Host)
|
||||||
|
|
|
@ -145,7 +145,7 @@ func (l *Linter) lintSettings(config *WorkflowConfig, c *types.Container, field
|
||||||
if len(c.Environment) != 0 {
|
if len(c.Environment) != 0 {
|
||||||
return newLinterError("Should not configure both environment and settings", config.File, fmt.Sprintf("%s.%s", field, c.Name), true)
|
return newLinterError("Should not configure both environment and settings", config.File, fmt.Sprintf("%s.%s", field, c.Name), true)
|
||||||
}
|
}
|
||||||
if len(c.Secrets.Secrets) != 0 {
|
if len(c.Secrets) != 0 {
|
||||||
return newLinterError("Should not configure both secrets and settings", config.File, fmt.Sprintf("%s.%s", field, c.Name), true)
|
return newLinterError("Should not configure both secrets and settings", config.File, fmt.Sprintf("%s.%s", field, c.Name), true)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -218,102 +218,6 @@ func (l *Linter) lintDeprecations(config *WorkflowConfig) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, step := range parsed.Steps.ContainerList {
|
|
||||||
if step.Group != "" {
|
|
||||||
err = multierr.Append(err, &errorTypes.PipelineError{
|
|
||||||
Type: errorTypes.PipelineErrorTypeDeprecation,
|
|
||||||
Message: "Please use depends_on instead of deprecated 'group' setting",
|
|
||||||
Data: errors.DeprecationErrorData{
|
|
||||||
File: config.File,
|
|
||||||
Field: "steps." + step.Name + ".group",
|
|
||||||
Docs: "https://woodpecker-ci.org/docs/next/usage/workflow-syntax#depends_on",
|
|
||||||
},
|
|
||||||
IsWarning: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, c := range parsed.When.Constraints {
|
|
||||||
if len(c.Event.Exclude) != 0 {
|
|
||||||
err = multierr.Append(err, &errorTypes.PipelineError{
|
|
||||||
Type: errorTypes.PipelineErrorTypeDeprecation,
|
|
||||||
Message: "Please only use allow lists for events",
|
|
||||||
Data: errors.DeprecationErrorData{
|
|
||||||
File: config.File,
|
|
||||||
Field: fmt.Sprintf("when[%d].event", i),
|
|
||||||
Docs: "https://woodpecker-ci.org/docs/usage/workflow-syntax#event-1",
|
|
||||||
},
|
|
||||||
IsWarning: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, step := range parsed.Steps.ContainerList {
|
|
||||||
for i, c := range step.When.Constraints {
|
|
||||||
if len(c.Event.Exclude) != 0 {
|
|
||||||
err = multierr.Append(err, &errorTypes.PipelineError{
|
|
||||||
Type: errorTypes.PipelineErrorTypeDeprecation,
|
|
||||||
Message: "Please only use allow lists for events",
|
|
||||||
Data: errors.DeprecationErrorData{
|
|
||||||
File: config.File,
|
|
||||||
Field: fmt.Sprintf("steps.%s.when[%d].event", step.Name, i),
|
|
||||||
Docs: "https://woodpecker-ci.org/docs/usage/workflow-syntax#event",
|
|
||||||
},
|
|
||||||
IsWarning: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, step := range parsed.Steps.ContainerList {
|
|
||||||
for i, c := range step.Secrets.Secrets {
|
|
||||||
if c.Source != c.Target {
|
|
||||||
err = multierr.Append(err, &errorTypes.PipelineError{
|
|
||||||
Type: errorTypes.PipelineErrorTypeDeprecation,
|
|
||||||
Message: "Secrets alternative names are deprecated, use environment with from_secret",
|
|
||||||
Data: errors.DeprecationErrorData{
|
|
||||||
File: config.File,
|
|
||||||
Field: fmt.Sprintf("steps.%s.secrets[%d]", step.Name, i),
|
|
||||||
Docs: "https://woodpecker-ci.org/docs/usage/secrets#use-secrets-in-settings-and-environment",
|
|
||||||
},
|
|
||||||
IsWarning: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, c := range parsed.When.Constraints {
|
|
||||||
if !c.Environment.IsEmpty() {
|
|
||||||
err = multierr.Append(err, &errorTypes.PipelineError{
|
|
||||||
Type: errorTypes.PipelineErrorTypeDeprecation,
|
|
||||||
Message: "environment filters are deprecated, use evaluate with CI_PIPELINE_DEPLOY_TARGET",
|
|
||||||
Data: errors.DeprecationErrorData{
|
|
||||||
File: config.File,
|
|
||||||
Field: fmt.Sprintf("when[%d].environment", i),
|
|
||||||
Docs: "https://woodpecker-ci.org/docs/usage/workflow-syntax#evaluate",
|
|
||||||
},
|
|
||||||
IsWarning: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, step := range parsed.Steps.ContainerList {
|
|
||||||
for i, c := range step.When.Constraints {
|
|
||||||
if !c.Environment.IsEmpty() {
|
|
||||||
err = multierr.Append(err, &errorTypes.PipelineError{
|
|
||||||
Type: errorTypes.PipelineErrorTypeDeprecation,
|
|
||||||
Message: "environment filters are deprecated, use evaluate with CI_PIPELINE_DEPLOY_TARGET",
|
|
||||||
Data: errors.DeprecationErrorData{
|
|
||||||
File: config.File,
|
|
||||||
Field: fmt.Sprintf("steps.%s.when[%d].environment", step.Name, i),
|
|
||||||
Docs: "https://woodpecker-ci.org/docs/usage/workflow-syntax#evaluate",
|
|
||||||
},
|
|
||||||
IsWarning: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +230,7 @@ func (l *Linter) lintBadHabits(config *WorkflowConfig) (err error) {
|
||||||
|
|
||||||
rootEventFilters := len(parsed.When.Constraints) > 0
|
rootEventFilters := len(parsed.When.Constraints) > 0
|
||||||
for _, c := range parsed.When.Constraints {
|
for _, c := range parsed.When.Constraints {
|
||||||
if len(c.Event.Include) == 0 {
|
if len(c.Event) == 0 {
|
||||||
rootEventFilters = false
|
rootEventFilters = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -340,7 +244,7 @@ func (l *Linter) lintBadHabits(config *WorkflowConfig) (err error) {
|
||||||
} else {
|
} else {
|
||||||
stepEventIndex := -1
|
stepEventIndex := -1
|
||||||
for i, c := range step.When.Constraints {
|
for i, c := range step.When.Constraints {
|
||||||
if len(c.Event.Include) == 0 {
|
if len(c.Event) == 0 {
|
||||||
stepEventIndex = i
|
stepEventIndex = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ func TestLintErrors(t *testing.T) {
|
||||||
want: "Cannot configure both entrypoint and settings",
|
want: "Cannot configure both entrypoint and settings",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: "steps: { build: { image: golang, settings: { test: 'true' }, environment: [ 'TEST=true' ] } }",
|
from: "steps: { build: { image: golang, settings: { test: 'true' }, environment: { 'TEST': 'true' } } }",
|
||||||
want: "Should not configure both environment and settings",
|
want: "Should not configure both environment and settings",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,15 +38,6 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- go test
|
- go test
|
||||||
|
|
||||||
environment-array:
|
|
||||||
image: golang
|
|
||||||
environment:
|
|
||||||
- CGO=0
|
|
||||||
- GOOS=linux
|
|
||||||
- GOARCH=amd64
|
|
||||||
commands:
|
|
||||||
- go test
|
|
||||||
|
|
||||||
secrets:
|
secrets:
|
||||||
image: docker
|
image: docker
|
||||||
commands:
|
commands:
|
||||||
|
@ -54,14 +45,7 @@ steps:
|
||||||
- echo $DOCKER_PASSWORD
|
- echo $DOCKER_PASSWORD
|
||||||
secrets:
|
secrets:
|
||||||
- docker_username
|
- docker_username
|
||||||
- source: docker_prod_password
|
- docker_prod_password
|
||||||
target: docker_password
|
|
||||||
|
|
||||||
group:
|
|
||||||
group: test
|
|
||||||
image: golang
|
|
||||||
commands:
|
|
||||||
- go test
|
|
||||||
|
|
||||||
detached:
|
detached:
|
||||||
image: redis
|
image: redis
|
||||||
|
|
|
@ -37,14 +37,6 @@ steps:
|
||||||
- deployment
|
- deployment
|
||||||
- release
|
- release
|
||||||
|
|
||||||
when-event-exclude-pull_request_closed:
|
|
||||||
image: alpine
|
|
||||||
commands:
|
|
||||||
- echo "test"
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
exclude: pull_request_closed
|
|
||||||
|
|
||||||
when-ref:
|
when-ref:
|
||||||
image: alpine
|
image: alpine
|
||||||
commands:
|
commands:
|
||||||
|
@ -78,7 +70,6 @@ steps:
|
||||||
commands:
|
commands:
|
||||||
- echo "test"
|
- echo "test"
|
||||||
when:
|
when:
|
||||||
environment: production
|
|
||||||
event: deployment
|
event: deployment
|
||||||
|
|
||||||
when-matrix:
|
when-matrix:
|
||||||
|
|
|
@ -163,18 +163,7 @@
|
||||||
"event": {
|
"event": {
|
||||||
"description": "Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#event",
|
"description": "Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#event",
|
||||||
"default": [],
|
"default": [],
|
||||||
"oneOf": [
|
"$ref": "#/definitions/event_constraint_list"
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"minLength": 1,
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/event_enum"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/event_enum"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"ref": {
|
"ref": {
|
||||||
"description": "Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#ref",
|
"description": "Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#ref",
|
||||||
|
@ -188,10 +177,6 @@
|
||||||
"description": "Execute a step only on a specific platform. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#platform",
|
"description": "Execute a step only on a specific platform. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#platform",
|
||||||
"$ref": "#/definitions/constraint_list"
|
"$ref": "#/definitions/constraint_list"
|
||||||
},
|
},
|
||||||
"environment": {
|
|
||||||
"description": "Execute a step only for a specific environment. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#environment",
|
|
||||||
"$ref": "#/definitions/constraint_list"
|
|
||||||
},
|
|
||||||
"instance": {
|
"instance": {
|
||||||
"description": "Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#instance",
|
"description": "Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#instance",
|
||||||
"$ref": "#/definitions/constraint_list"
|
"$ref": "#/definitions/constraint_list"
|
||||||
|
@ -291,10 +276,6 @@
|
||||||
"volumes": {
|
"volumes": {
|
||||||
"$ref": "#/definitions/step_volumes"
|
"$ref": "#/definitions/step_volumes"
|
||||||
},
|
},
|
||||||
"group": {
|
|
||||||
"description": "deprecated, use depends_on",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"description": "Execute a step after another step has finished.",
|
"description": "Execute a step after another step has finished.",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
@ -377,10 +358,6 @@
|
||||||
"volumes": {
|
"volumes": {
|
||||||
"$ref": "#/definitions/step_volumes"
|
"$ref": "#/definitions/step_volumes"
|
||||||
},
|
},
|
||||||
"group": {
|
|
||||||
"description": "deprecated, use depends_on",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"description": "Execute a step after another step has finished.",
|
"description": "Execute a step after another step has finished.",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
@ -457,10 +434,6 @@
|
||||||
"volumes": {
|
"volumes": {
|
||||||
"$ref": "#/definitions/step_volumes"
|
"$ref": "#/definitions/step_volumes"
|
||||||
},
|
},
|
||||||
"group": {
|
|
||||||
"description": "deprecated, use depends_on",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"description": "Execute a step after another step has finished.",
|
"description": "Execute a step after another step has finished.",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
@ -551,10 +524,6 @@
|
||||||
"description": "Execute a step only on a specific platform. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#platform",
|
"description": "Execute a step only on a specific platform. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#platform",
|
||||||
"$ref": "#/definitions/constraint_list"
|
"$ref": "#/definitions/constraint_list"
|
||||||
},
|
},
|
||||||
"environment": {
|
|
||||||
"description": "Execute a step only for a specific environment. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax#environment",
|
|
||||||
"$ref": "#/definitions/constraint_list"
|
|
||||||
},
|
|
||||||
"matrix": {
|
"matrix": {
|
||||||
"description": "Read more: https://woodpecker-ci.org/docs/usage/matrix-workflows",
|
"description": "Read more: https://woodpecker-ci.org/docs/usage/matrix-workflows",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -624,40 +593,6 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/event_enum"
|
"$ref": "#/definitions/event_enum"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"include": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/event_enum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"minLength": 1,
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/event_enum"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"exclude": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/event_enum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"minLength": 1,
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/event_enum"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -739,43 +674,16 @@
|
||||||
},
|
},
|
||||||
"step_environment": {
|
"step_environment": {
|
||||||
"description": "Pass environment variables to a pipeline step. Read more: https://woodpecker-ci.org/docs/usage/environment",
|
"description": "Pass environment variables to a pipeline step. Read more: https://woodpecker-ci.org/docs/usage/environment",
|
||||||
"oneOf": [
|
"type": "object",
|
||||||
{
|
"additionalProperties": {
|
||||||
"type": "array",
|
"type": ["boolean", "string", "number", "array", "object"]
|
||||||
"items": {
|
}
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"minLength": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": {
|
|
||||||
"type": ["boolean", "string", "number", "array", "object"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"step_secrets": {
|
"step_secrets": {
|
||||||
"description": "Pass secrets to a pipeline step at runtime. Read more: https://woodpecker-ci.org/docs/usage/secrets",
|
"description": "Pass secrets to a pipeline step at runtime. Read more: https://woodpecker-ci.org/docs/usage/secrets",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"oneOf": [
|
"type": "string"
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": ["source", "target"],
|
|
||||||
"properties": {
|
|
||||||
"source": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"target": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package yaml
|
package yaml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/franela/goblin"
|
"github.com/franela/goblin"
|
||||||
|
@ -35,7 +36,7 @@ func TestParse(t *testing.T) {
|
||||||
g.Fail(err)
|
g.Fail(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.Assert(out.When.Constraints[0].Event.Match("tester")).Equal(true)
|
g.Assert(slices.Contains(out.When.Constraints[0].Event, "tester")).Equal(true)
|
||||||
|
|
||||||
g.Assert(out.Workspace.Base).Equal("/go")
|
g.Assert(out.Workspace.Base).Equal("/go")
|
||||||
g.Assert(out.Workspace.Path).Equal("src/github.com/octocat/hello-world")
|
g.Assert(out.Workspace.Path).Equal("src/github.com/octocat/hello-world")
|
||||||
|
@ -85,7 +86,7 @@ func TestParse(t *testing.T) {
|
||||||
g.Assert(len(out.Steps.ContainerList[0].When.Constraints)).Equal(0)
|
g.Assert(len(out.Steps.ContainerList[0].When.Constraints)).Equal(0)
|
||||||
g.Assert(out.Steps.ContainerList[1].Name).Equal("notify_success")
|
g.Assert(out.Steps.ContainerList[1].Name).Equal("notify_success")
|
||||||
g.Assert(out.Steps.ContainerList[1].Image).Equal("plugins/slack")
|
g.Assert(out.Steps.ContainerList[1].Image).Equal("plugins/slack")
|
||||||
g.Assert(out.Steps.ContainerList[1].When.Constraints[0].Event.Include).Equal([]string{"success"})
|
g.Assert(out.Steps.ContainerList[1].When.Constraints[0].Event).Equal(yaml_base_types.StringOrSlice{"success"})
|
||||||
})
|
})
|
||||||
|
|
||||||
matchConfig, err := ParseString(sampleYaml)
|
matchConfig, err := ParseString(sampleYaml)
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
// Copyright 2023 Woodpecker Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package base
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SliceOrMap represents a map of strings, string slice are converted into a map.
|
|
||||||
type SliceOrMap map[string]any
|
|
||||||
|
|
||||||
// UnmarshalYAML implements the Unmarshaler interface.
|
|
||||||
func (s *SliceOrMap) UnmarshalYAML(unmarshal func(any) error) error {
|
|
||||||
var sliceType []any
|
|
||||||
if err := unmarshal(&sliceType); err == nil {
|
|
||||||
parts := map[string]any{}
|
|
||||||
for _, s := range sliceType {
|
|
||||||
if str, ok := s.(string); ok {
|
|
||||||
str := strings.TrimSpace(str)
|
|
||||||
key, val, _ := strings.Cut(str, "=")
|
|
||||||
parts[key] = val
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("cannot unmarshal '%v' of type %T into a string value", s, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*s = parts
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapType map[string]any
|
|
||||||
if err := unmarshal(&mapType); err == nil {
|
|
||||||
*s = mapType
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.New("failed to unmarshal SliceOrMap")
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
// Copyright 2024 Woodpecker Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package base
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
type StructSliceOrMap struct {
|
|
||||||
Foos SliceOrMap `yaml:"foos,omitempty"`
|
|
||||||
Bars []string `yaml:"bars"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSliceOrMapYaml(t *testing.T) {
|
|
||||||
str := `{foos: [bar=baz, far=faz]}`
|
|
||||||
|
|
||||||
s := StructSliceOrMap{}
|
|
||||||
assert.NoError(t, yaml.Unmarshal([]byte(str), &s))
|
|
||||||
|
|
||||||
assert.Equal(t, SliceOrMap{"bar": "baz", "far": "faz"}, s.Foos)
|
|
||||||
|
|
||||||
d, err := yaml.Marshal(&s)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
s2 := StructSliceOrMap{}
|
|
||||||
assert.NoError(t, yaml.Unmarshal(d, &s2))
|
|
||||||
|
|
||||||
assert.Equal(t, SliceOrMap{"bar": "baz", "far": "faz"}, s2.Foos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStr2SliceOrMapPtrMap(t *testing.T) {
|
|
||||||
s := map[string]*StructSliceOrMap{"udav": {
|
|
||||||
Foos: SliceOrMap{"io.rancher.os.bar": "baz", "io.rancher.os.far": "true"},
|
|
||||||
Bars: []string{},
|
|
||||||
}}
|
|
||||||
d, err := yaml.Marshal(&s)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
s2 := map[string]*StructSliceOrMap{}
|
|
||||||
assert.NoError(t, yaml.Unmarshal(d, &s2))
|
|
||||||
|
|
||||||
assert.Equal(t, s, s2)
|
|
||||||
}
|
|
|
@ -39,7 +39,6 @@ type (
|
||||||
Detached bool `yaml:"detach,omitempty"`
|
Detached bool `yaml:"detach,omitempty"`
|
||||||
Directory string `yaml:"directory,omitempty"`
|
Directory string `yaml:"directory,omitempty"`
|
||||||
Failure string `yaml:"failure,omitempty"`
|
Failure string `yaml:"failure,omitempty"`
|
||||||
Group string `yaml:"group,omitempty"`
|
|
||||||
Image string `yaml:"image,omitempty"`
|
Image string `yaml:"image,omitempty"`
|
||||||
Name string `yaml:"name,omitempty"`
|
Name string `yaml:"name,omitempty"`
|
||||||
Pull bool `yaml:"pull,omitempty"`
|
Pull bool `yaml:"pull,omitempty"`
|
||||||
|
@ -49,10 +48,8 @@ type (
|
||||||
Ports []string `yaml:"ports,omitempty"`
|
Ports []string `yaml:"ports,omitempty"`
|
||||||
DependsOn base.StringOrSlice `yaml:"depends_on,omitempty"`
|
DependsOn base.StringOrSlice `yaml:"depends_on,omitempty"`
|
||||||
|
|
||||||
// TODO: make []string in 3.x
|
Secrets []string `yaml:"secrets,omitempty"`
|
||||||
Secrets Secrets `yaml:"secrets,omitempty"`
|
Environment map[string]any `yaml:"environment,omitempty"`
|
||||||
// TODO: make map[string]any in 3.x
|
|
||||||
Environment base.SliceOrMap `yaml:"environment,omitempty"`
|
|
||||||
|
|
||||||
// Docker and Kubernetes Specific
|
// Docker and Kubernetes Specific
|
||||||
Privileged bool `yaml:"privileged,omitempty"`
|
Privileged bool `yaml:"privileged,omitempty"`
|
||||||
|
@ -125,7 +122,7 @@ func (c *Container) IsPlugin() bool {
|
||||||
return len(c.Commands) == 0 &&
|
return len(c.Commands) == 0 &&
|
||||||
len(c.Entrypoint) == 0 &&
|
len(c.Entrypoint) == 0 &&
|
||||||
len(c.Environment) == 0 &&
|
len(c.Environment) == 0 &&
|
||||||
len(c.Secrets.Secrets) == 0
|
len(c.Secrets) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) IsTrustedCloneImage() bool {
|
func (c *Container) IsTrustedCloneImage() bool {
|
||||||
|
|
|
@ -41,8 +41,8 @@ dns: 8.8.8.8
|
||||||
dns_search: example.com
|
dns_search: example.com
|
||||||
entrypoint: [/bin/sh, -c]
|
entrypoint: [/bin/sh, -c]
|
||||||
environment:
|
environment:
|
||||||
- RACK_ENV=development
|
RACK_ENV: development
|
||||||
- SHOW=true
|
SHOW: true
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- somehost:162.242.195.82
|
- somehost:162.242.195.82
|
||||||
- otherhost:50.31.209.229
|
- otherhost:50.31.209.229
|
||||||
|
@ -88,7 +88,7 @@ func TestUnmarshalContainer(t *testing.T) {
|
||||||
DNS: base.StringOrSlice{"8.8.8.8"},
|
DNS: base.StringOrSlice{"8.8.8.8"},
|
||||||
DNSSearch: base.StringOrSlice{"example.com"},
|
DNSSearch: base.StringOrSlice{"example.com"},
|
||||||
Entrypoint: []string{"/bin/sh", "-c"},
|
Entrypoint: []string{"/bin/sh", "-c"},
|
||||||
Environment: base.SliceOrMap{"RACK_ENV": "development", "SHOW": "true"},
|
Environment: map[string]any{"RACK_ENV": "development", "SHOW": true},
|
||||||
ExtraHosts: []string{"somehost:162.242.195.82", "otherhost:50.31.209.229", "ipv6:2001:db8::10"},
|
ExtraHosts: []string{"somehost:162.242.195.82", "otherhost:50.31.209.229", "ipv6:2001:db8::10"},
|
||||||
Image: "golang:latest",
|
Image: "golang:latest",
|
||||||
MemLimit: base.MemStringOrInt(1024),
|
MemLimit: base.MemStringOrInt(1024),
|
||||||
|
@ -114,9 +114,7 @@ func TestUnmarshalContainer(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Event: constraint.List{
|
Event: base.StringOrSlice{"cron"},
|
||||||
Include: []string{"cron"},
|
|
||||||
},
|
|
||||||
Cron: constraint.List{
|
Cron: constraint.List{
|
||||||
Include: []string{"job1"},
|
Include: []string{"job1"},
|
||||||
},
|
},
|
||||||
|
@ -166,7 +164,6 @@ func TestUnmarshalContainers(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: `publish-agent:
|
from: `publish-agent:
|
||||||
group: bundle
|
|
||||||
image: print/env
|
image: print/env
|
||||||
settings:
|
settings:
|
||||||
repo: woodpeckerci/woodpecker-agent
|
repo: woodpeckerci/woodpecker-agent
|
||||||
|
@ -179,16 +176,9 @@ func TestUnmarshalContainers(t *testing.T) {
|
||||||
event: push`,
|
event: push`,
|
||||||
want: []*Container{
|
want: []*Container{
|
||||||
{
|
{
|
||||||
Name: "publish-agent",
|
Name: "publish-agent",
|
||||||
Image: "print/env",
|
Image: "print/env",
|
||||||
Group: "bundle",
|
Secrets: []string{"docker_username", "docker_password"},
|
||||||
Secrets: Secrets{Secrets: []*Secret{{
|
|
||||||
Source: "docker_username",
|
|
||||||
Target: "docker_username",
|
|
||||||
}, {
|
|
||||||
Source: "docker_password",
|
|
||||||
Target: "docker_password",
|
|
||||||
}}},
|
|
||||||
Settings: map[string]any{
|
Settings: map[string]any{
|
||||||
"repo": "woodpeckerci/woodpecker-agent",
|
"repo": "woodpeckerci/woodpecker-agent",
|
||||||
"dockerfile": "docker/Dockerfile.agent",
|
"dockerfile": "docker/Dockerfile.agent",
|
||||||
|
@ -198,7 +188,7 @@ func TestUnmarshalContainers(t *testing.T) {
|
||||||
When: constraint.When{
|
When: constraint.When{
|
||||||
Constraints: []constraint.Constraint{
|
Constraints: []constraint.Constraint{
|
||||||
{
|
{
|
||||||
Event: constraint.List{Include: []string{"push"}},
|
Event: base.StringOrSlice{"push"},
|
||||||
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -208,7 +198,6 @@ func TestUnmarshalContainers(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: `publish-cli:
|
from: `publish-cli:
|
||||||
group: docker
|
|
||||||
image: print/env
|
image: print/env
|
||||||
settings:
|
settings:
|
||||||
repo: woodpeckerci/woodpecker-cli
|
repo: woodpeckerci/woodpecker-cli
|
||||||
|
@ -221,7 +210,6 @@ func TestUnmarshalContainers(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "publish-cli",
|
Name: "publish-cli",
|
||||||
Image: "print/env",
|
Image: "print/env",
|
||||||
Group: "docker",
|
|
||||||
Settings: map[string]any{
|
Settings: map[string]any{
|
||||||
"repo": "woodpeckerci/woodpecker-cli",
|
"repo": "woodpeckerci/woodpecker-cli",
|
||||||
"dockerfile": "docker/Dockerfile.cli",
|
"dockerfile": "docker/Dockerfile.cli",
|
||||||
|
@ -230,7 +218,7 @@ func TestUnmarshalContainers(t *testing.T) {
|
||||||
When: constraint.When{
|
When: constraint.When{
|
||||||
Constraints: []constraint.Constraint{
|
Constraints: []constraint.Constraint{
|
||||||
{
|
{
|
||||||
Event: constraint.List{Include: []string{"push"}},
|
Event: base.StringOrSlice{"push"},
|
||||||
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -252,11 +240,11 @@ func TestUnmarshalContainers(t *testing.T) {
|
||||||
When: constraint.When{
|
When: constraint.When{
|
||||||
Constraints: []constraint.Constraint{
|
Constraints: []constraint.Constraint{
|
||||||
{
|
{
|
||||||
Event: constraint.List{Include: []string{"push"}},
|
Event: base.StringOrSlice{"push"},
|
||||||
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
Branch: constraint.List{Include: []string{"${CI_REPO_DEFAULT_BRANCH}"}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Event: constraint.List{Include: []string{"pull_request"}},
|
Event: base.StringOrSlice{"pull_request"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
// Copyright 2023 Woodpecker Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import "gopkg.in/yaml.v3"
|
|
||||||
|
|
||||||
type (
|
|
||||||
// Secrets defines a collection of secrets.
|
|
||||||
Secrets struct {
|
|
||||||
Secrets []*Secret
|
|
||||||
}
|
|
||||||
|
|
||||||
// Secret defines a container secret.
|
|
||||||
Secret struct {
|
|
||||||
Source string `yaml:"source"`
|
|
||||||
Target string `yaml:"target"`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnmarshalYAML implements the Unmarshaler interface.
|
|
||||||
func (s *Secrets) UnmarshalYAML(value *yaml.Node) error {
|
|
||||||
y, _ := yaml.Marshal(value)
|
|
||||||
|
|
||||||
var secrets []string
|
|
||||||
err := yaml.Unmarshal(y, &secrets)
|
|
||||||
if err == nil {
|
|
||||||
for _, str := range secrets {
|
|
||||||
s.Secrets = append(s.Secrets, &Secret{
|
|
||||||
Source: str,
|
|
||||||
Target: str,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return yaml.Unmarshal(y, &s.Secrets)
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
// Copyright 2023 Woodpecker Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUnmarshalSecrets(t *testing.T) {
|
|
||||||
testdata := []struct {
|
|
||||||
from string
|
|
||||||
want []*Secret
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
from: "[ mysql_username, mysql_password]",
|
|
||||||
want: []*Secret{
|
|
||||||
{
|
|
||||||
Source: "mysql_username",
|
|
||||||
Target: "mysql_username",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "mysql_password",
|
|
||||||
Target: "mysql_password",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "[ { source: mysql_prod_username, target: mysql_username } ]",
|
|
||||||
want: []*Secret{
|
|
||||||
{
|
|
||||||
Source: "mysql_prod_username",
|
|
||||||
Target: "mysql_username",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: "[ { source: mysql_prod_username, target: mysql_username }, { source: redis_username, target: redis_username } ]",
|
|
||||||
want: []*Secret{
|
|
||||||
{
|
|
||||||
Source: "mysql_prod_username",
|
|
||||||
Target: "mysql_username",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Source: "redis_username",
|
|
||||||
Target: "redis_username",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range testdata {
|
|
||||||
in := []byte(test.from)
|
|
||||||
got := Secrets{}
|
|
||||||
err := yaml.Unmarshal(in, &got)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, test.want, got.Secrets, "problem parsing secrets %q", test.from)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue