2015-04-16 07:10:17 +00:00
|
|
|
package parser
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2015-05-20 06:19:59 +00:00
|
|
|
"path/filepath"
|
2015-04-16 07:10:17 +00:00
|
|
|
"strings"
|
|
|
|
|
2015-05-17 20:51:42 +00:00
|
|
|
common "github.com/drone/drone/pkg/types"
|
2015-04-16 07:10:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// lintRule defines a function that runs lint
|
|
|
|
// checks against a Yaml Config file. If the rule
|
|
|
|
// fails it should return an error message.
|
|
|
|
type lintRule func(*common.Config) error
|
|
|
|
|
|
|
|
var lintRules = [...]lintRule{
|
|
|
|
expectBuild,
|
|
|
|
expectImage,
|
|
|
|
expectCommand,
|
|
|
|
expectTrustedSetup,
|
|
|
|
expectTrustedClone,
|
|
|
|
expectTrustedPublish,
|
|
|
|
expectTrustedDeploy,
|
|
|
|
expectTrustedNotify,
|
2015-08-07 22:21:39 +00:00
|
|
|
expectCacheInWorkspace,
|
2015-04-16 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Lint runs all lint rules against the Yaml Config.
|
|
|
|
func Lint(c *common.Config) error {
|
|
|
|
for _, rule := range lintRules {
|
|
|
|
err := rule(c)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when no build is defined
|
|
|
|
func expectBuild(c *common.Config) error {
|
|
|
|
if c.Build == nil {
|
|
|
|
return fmt.Errorf("Yaml must define a build section")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when no build image is defined
|
|
|
|
func expectImage(c *common.Config) error {
|
|
|
|
if len(c.Build.Image) == 0 {
|
|
|
|
return fmt.Errorf("Yaml must define a build image")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when no build commands are defined
|
|
|
|
func expectCommand(c *common.Config) error {
|
|
|
|
if c.Build.Config == nil || c.Build.Config["commands"] == nil {
|
|
|
|
return fmt.Errorf("Yaml must define build commands")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when a non-trusted clone plugin is used.
|
|
|
|
func expectTrustedClone(c *common.Config) error {
|
|
|
|
if c.Clone != nil && strings.Contains(c.Clone.Image, "/") {
|
|
|
|
return fmt.Errorf("Yaml must use trusted clone plugins")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when a non-trusted setup plugin is used.
|
|
|
|
func expectTrustedSetup(c *common.Config) error {
|
|
|
|
if c.Setup != nil && strings.Contains(c.Setup.Image, "/") {
|
|
|
|
return fmt.Errorf("Yaml must use trusted setup plugins")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when a non-trusted publish plugin is used.
|
|
|
|
func expectTrustedPublish(c *common.Config) error {
|
|
|
|
for _, step := range c.Publish {
|
|
|
|
if strings.Contains(step.Image, "/") {
|
|
|
|
return fmt.Errorf("Yaml must use trusted publish plugins")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when a non-trusted deploy plugin is used.
|
|
|
|
func expectTrustedDeploy(c *common.Config) error {
|
|
|
|
for _, step := range c.Deploy {
|
|
|
|
if strings.Contains(step.Image, "/") {
|
|
|
|
return fmt.Errorf("Yaml must use trusted deploy plugins")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// lint rule that fails when a non-trusted notify plugin is used.
|
|
|
|
func expectTrustedNotify(c *common.Config) error {
|
|
|
|
for _, step := range c.Notify {
|
|
|
|
if strings.Contains(step.Image, "/") {
|
|
|
|
return fmt.Errorf("Yaml must use trusted notify plugins")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2015-05-20 06:19:59 +00:00
|
|
|
|
2015-08-07 22:21:39 +00:00
|
|
|
// lint rule that fails if the cache directories are not contained
|
|
|
|
// in the workspace.
|
|
|
|
func expectCacheInWorkspace(c *common.Config) error {
|
|
|
|
for _, step := range c.Build.Cache {
|
2015-08-07 23:18:11 +00:00
|
|
|
if strings.Index(step, ":") != -1 {
|
|
|
|
return fmt.Errorf("Cache cannot contain : in the path")
|
|
|
|
}
|
|
|
|
|
2015-08-07 22:21:39 +00:00
|
|
|
cleaned := filepath.Clean(step)
|
|
|
|
|
|
|
|
if strings.Index(cleaned, "../") != -1 {
|
|
|
|
return fmt.Errorf("Cache must point to a path in the workspace")
|
|
|
|
} else if cleaned == "." {
|
|
|
|
return fmt.Errorf("Cannot cache the workspace")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-05-20 06:19:59 +00:00
|
|
|
func LintPlugins(c *common.Config, opts *Opts) error {
|
|
|
|
if len(opts.Whitelist) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var images []string
|
|
|
|
images = append(images, c.Setup.Image)
|
|
|
|
images = append(images, c.Clone.Image)
|
|
|
|
for _, step := range c.Publish {
|
|
|
|
images = append(images, step.Image)
|
|
|
|
}
|
|
|
|
for _, step := range c.Deploy {
|
|
|
|
images = append(images, step.Image)
|
|
|
|
}
|
|
|
|
for _, step := range c.Notify {
|
|
|
|
images = append(images, step.Image)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, image := range images {
|
|
|
|
match := false
|
|
|
|
for _, pattern := range opts.Whitelist {
|
|
|
|
if pattern == image {
|
|
|
|
match = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
ok, err := filepath.Match(pattern, image)
|
|
|
|
if ok && err == nil {
|
|
|
|
match = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !match {
|
|
|
|
return fmt.Errorf("Cannot use un-trusted image %s", image)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|