ensure invalid dependecy fails linter with helpful error
This commit is contained in:
@@ -19,15 +19,6 @@ import (
|
|||||||
// have the same name.
|
// have the same name.
|
||||||
var ErrDuplicateStepName = errors.New("linter: duplicate step names")
|
var ErrDuplicateStepName = errors.New("linter: duplicate step names")
|
||||||
|
|
||||||
// ErrMissingDependency is returned when a Pipeline step
|
|
||||||
// defines dependencies that are invlid or unknown.
|
|
||||||
var ErrMissingDependency = errors.New("linter: invalid or unknown step dependency")
|
|
||||||
|
|
||||||
// ErrCyclicalDependency is returned when a Pipeline step
|
|
||||||
// defines a cyclical dependency, which would result in an
|
|
||||||
// infinite execution loop.
|
|
||||||
var ErrCyclicalDependency = errors.New("linter: cyclical step dependency detected")
|
|
||||||
|
|
||||||
// Opts provides linting options.
|
// Opts provides linting options.
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
Trusted bool
|
Trusted bool
|
||||||
@@ -80,13 +71,28 @@ func checkPipeline(pipeline *resource.Pipeline, trusted bool) error {
|
|||||||
|
|
||||||
func checkSteps(pipeline *resource.Pipeline, trusted bool) error {
|
func checkSteps(pipeline *resource.Pipeline, trusted bool) error {
|
||||||
steps := append(pipeline.Services, pipeline.Steps...)
|
steps := append(pipeline.Services, pipeline.Steps...)
|
||||||
|
names := map[string]struct{}{}
|
||||||
|
if !pipeline.Clone.Disable {
|
||||||
|
names["clone"] = struct{}{}
|
||||||
|
}
|
||||||
for _, step := range steps {
|
for _, step := range steps {
|
||||||
if step == nil {
|
if step == nil {
|
||||||
return errors.New("linter: nil step")
|
return errors.New("linter: nil step")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unique list of names
|
||||||
|
_, ok := names[step.Name]
|
||||||
|
if ok {
|
||||||
|
return ErrDuplicateStepName
|
||||||
|
}
|
||||||
|
names[step.Name] = struct{}{}
|
||||||
|
|
||||||
if err := checkStep(step, trusted); err != nil {
|
if err := checkStep(step, trusted); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := checkDeps(step, names); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -171,3 +177,16 @@ func checkEmptyDirVolume(volume *resource.VolumeEmptyDir, trusted bool) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkDeps(step *resource.Step, deps map[string]struct{}) error {
|
||||||
|
for _, dep := range step.DependsOn {
|
||||||
|
_, ok := deps[dep]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("linter: unknown step dependency detected: %s references %s", step.Name, dep)
|
||||||
|
}
|
||||||
|
if step.Name == dep {
|
||||||
|
return fmt.Errorf("linter: cyclical step dependency detected: %s", dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -197,6 +197,12 @@ func TestLint(t *testing.T) {
|
|||||||
// invalid: true,
|
// invalid: true,
|
||||||
// message: "linter: invalid or missing name",
|
// message: "linter: invalid or missing name",
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
path: "testdata/missing_dep.yml",
|
||||||
|
invalid: true,
|
||||||
|
message: "linter: unknown step dependency detected: test references foo",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
name := path.Base(test.path)
|
name := path.Base(test.path)
|
||||||
|
|||||||
33
engine/linter/testdata/missing_dep.yml
vendored
33
engine/linter/testdata/missing_dep.yml
vendored
@@ -1,35 +1,18 @@
|
|||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
name: amd64
|
name: default
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: golang
|
||||||
|
commands:
|
||||||
|
- go build
|
||||||
|
|
||||||
- name: test
|
- name: test
|
||||||
image: golang
|
image: golang
|
||||||
commands:
|
commands:
|
||||||
- go build
|
- go build
|
||||||
- go test
|
- go test
|
||||||
|
depends_on:
|
||||||
services:
|
- foo
|
||||||
- name: database
|
|
||||||
image: redis
|
|
||||||
ports:
|
|
||||||
- 6379
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
name: arm
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: arm
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: test
|
|
||||||
image: golang
|
|
||||||
commands:
|
|
||||||
- go build
|
|
||||||
- go test
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- foo
|
|
||||||
...
|
|
||||||
Reference in New Issue
Block a user