mirror of
https://github.com/drone/drone-cli.git
synced 2024-11-23 09:21:56 +01:00
104 lines
2.4 KiB
Go
104 lines
2.4 KiB
Go
package lint
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"strings"
|
|
|
|
"github.com/drone-runners/drone-runner-docker/engine/linter"
|
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
|
"github.com/drone/drone-go/drone"
|
|
"github.com/drone/envsubst"
|
|
"github.com/drone/runner-go/manifest"
|
|
"github.com/urfave/cli"
|
|
)
|
|
|
|
// Command exports the linter command.
|
|
var Command = cli.Command{
|
|
Name: "lint",
|
|
Usage: "lint the yaml file, checks for yaml errors",
|
|
ArgsUsage: "<source>",
|
|
Action: lint,
|
|
Flags: []cli.Flag{
|
|
cli.BoolFlag{
|
|
Name: "trusted",
|
|
Usage: "is the yaml trustable",
|
|
},
|
|
},
|
|
}
|
|
|
|
type Flags struct {
|
|
Build drone.Build
|
|
Netrc drone.Netrc
|
|
Repo drone.Repo
|
|
Stage drone.Stage
|
|
System drone.System
|
|
}
|
|
|
|
func lint(c *cli.Context) error {
|
|
f := new(Flags)
|
|
f.Repo.Trusted = c.Bool("trusted")
|
|
var envs map[string]string
|
|
|
|
path := c.Args().First()
|
|
if path == "" {
|
|
path = ".drone.yml"
|
|
}
|
|
|
|
rawSource, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// string substitution function ensures that string replacement variables are escaped and quoted if they contain newlines.
|
|
subf := func(k string) string {
|
|
v := envs[k]
|
|
if strings.Contains(v, "\n") {
|
|
v = fmt.Sprintf("%q", v)
|
|
}
|
|
return v
|
|
}
|
|
// evaluates string replacement expressions and returns an update configuration.
|
|
config, err := envsubst.Eval(string(rawSource), subf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// parse into manifests
|
|
inputManifests, err := manifest.ParseString(config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, iter := range inputManifests.Resources {
|
|
if iter.GetType() == "docker" {
|
|
resource, err := resource.Lookup(iter.GetName(), inputManifests)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// lint the resource and return an error if any linting rules are broken
|
|
lint := linter.New()
|
|
err = lint.Lint(resource, &f.Repo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
// now we can check the pipeline dependencies
|
|
// get a list of all the pipelines
|
|
allStages := map[string]struct{}{}
|
|
for _, iter := range inputManifests.Resources {
|
|
allStages[iter.GetName()] = struct{}{}
|
|
}
|
|
// we need to parse the file again into raw resources to access the dependencies
|
|
inputRawResources, err := manifest.ParseRawFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, iter := range inputRawResources {
|
|
for _, dep := range iter.Deps {
|
|
if _, ok := allStages[dep]; !ok {
|
|
return fmt.Errorf("Pipeline stage '%s' declares invalid dependency '%s'", iter.Name, dep)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|