mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-27 20:31:10 +00:00
removed yaml functions that were pushed down to the build layer
This commit is contained in:
parent
ba47948fc9
commit
cf953f19d3
8 changed files with 62 additions and 1134 deletions
|
@ -1,74 +1,74 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
// import (
|
||||||
"net"
|
// "net"
|
||||||
"net/http"
|
// "net/http"
|
||||||
"net/rpc"
|
// "net/rpc"
|
||||||
|
|
||||||
common "github.com/drone/drone/pkg/types"
|
// common "github.com/drone/drone/pkg/types"
|
||||||
)
|
// )
|
||||||
|
|
||||||
// Client communicates with a Remote plugin using the
|
// // Client communicates with a Remote plugin using the
|
||||||
// net/rpc protocol.
|
// // net/rpc protocol.
|
||||||
type Client struct {
|
// type Client struct {
|
||||||
*rpc.Client
|
// *rpc.Client
|
||||||
}
|
// }
|
||||||
|
|
||||||
// New returns a new, remote datastore backend that connects
|
// // New returns a new, remote datastore backend that connects
|
||||||
// via tcp and exchanges data using Go's RPC mechanism.
|
// // via tcp and exchanges data using Go's RPC mechanism.
|
||||||
func New(conf *config.Config) (*Client, error) {
|
// func New(conf *config.Config) (*Client, error) {
|
||||||
// conn, err := net.Dial("tcp", conf.Server.Addr)
|
// // conn, err := net.Dial("tcp", conf.Server.Addr)
|
||||||
// if err != nil {
|
// // if err != nil {
|
||||||
// return nil, err
|
// // return nil, err
|
||||||
// }
|
// // }
|
||||||
// client := &Client{
|
// // client := &Client{
|
||||||
// rpc.NewClient(conn),
|
// // rpc.NewClient(conn),
|
||||||
// }
|
// // }
|
||||||
// return client, nil
|
// // return client, nil
|
||||||
return nil, nil
|
// return nil, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (c *Client) Login(token, secret string) (*common.User, error) {
|
// func (c *Client) Login(token, secret string) (*common.User, error) {
|
||||||
return nil, nil
|
// return nil, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Repo fetches the named repository from the remote system.
|
// // Repo fetches the named repository from the remote system.
|
||||||
func (c *Client) Repo(u *common.User, owner, repo string) (*common.Repo, error) {
|
// func (c *Client) Repo(u *common.User, owner, repo string) (*common.Repo, error) {
|
||||||
return nil, nil
|
// return nil, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (c *Client) Perm(u *common.User, owner, repo string) (*common.Perm, error) {
|
// func (c *Client) Perm(u *common.User, owner, repo string) (*common.Perm, error) {
|
||||||
return nil, nil
|
// return nil, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (c *Client) Script(u *common.User, r *common.Repo, b *common.Build) ([]byte, error) {
|
// func (c *Client) Script(u *common.User, r *common.Repo, b *common.Build) ([]byte, error) {
|
||||||
return nil, nil
|
// return nil, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (c *Client) Status(u *common.User, r *common.Repo, b *common.Build, link string) error {
|
// func (c *Client) Status(u *common.User, r *common.Repo, b *common.Build, link string) error {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (c *Client) Activate(u *common.User, r *common.Repo, k *common.Keypair, link string) error {
|
// func (c *Client) Activate(u *common.User, r *common.Repo, k *common.Keypair, link string) error {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (c *Client) Deactivate(u *common.User, r *common.Repo, link string) error {
|
// func (c *Client) Deactivate(u *common.User, r *common.Repo, link string) error {
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (c *Client) Hook(r *http.Request) (*common.Hook, error) {
|
// func (c *Client) Hook(r *http.Request) (*common.Hook, error) {
|
||||||
hook := new(common.Hook)
|
// hook := new(common.Hook)
|
||||||
header := make(http.Header)
|
// header := make(http.Header)
|
||||||
copyHeader(r.Header, header)
|
// copyHeader(r.Header, header)
|
||||||
|
|
||||||
return hook, nil
|
// return hook, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func copyHeader(dst, src http.Header) {
|
// func copyHeader(dst, src http.Header) {
|
||||||
for k, vv := range src {
|
// for k, vv := range src {
|
||||||
for _, v := range vv {
|
// for _, v := range vv {
|
||||||
dst.Add(k, v)
|
// dst.Add(k, v)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
package inject
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
|
||||||
"github.com/drone/drone/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Inject injects a map of parameters into a raw string and returns
|
|
||||||
// the resulting string.
|
|
||||||
//
|
|
||||||
// Parameters are represented in the string using $$ notation, similar
|
|
||||||
// to how environment variables are defined in Makefiles.
|
|
||||||
func Inject(raw string, params map[string]string) string {
|
|
||||||
if params == nil {
|
|
||||||
return raw
|
|
||||||
}
|
|
||||||
keys := []string{}
|
|
||||||
for k := range params {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
|
|
||||||
injected := raw
|
|
||||||
for _, k := range keys {
|
|
||||||
v := params[k]
|
|
||||||
injected = strings.Replace(injected, "$$"+k, v, -1)
|
|
||||||
}
|
|
||||||
return injected
|
|
||||||
}
|
|
||||||
|
|
||||||
// InjectSafe attempts to safely inject parameters without leaking
|
|
||||||
// parameters in the Build or Compose section of the yaml file.
|
|
||||||
//
|
|
||||||
// The intended use case for this function are public pull requests.
|
|
||||||
// We want to avoid a malicious pull request that allows someone
|
|
||||||
// to inject and print private variables.
|
|
||||||
func InjectSafe(raw string, params map[string]string) string {
|
|
||||||
before, _ := parse(raw)
|
|
||||||
after, _ := parse(Inject(raw, params))
|
|
||||||
before.Notify = after.Notify
|
|
||||||
before.Publish = after.Publish
|
|
||||||
before.Deploy = after.Deploy
|
|
||||||
result, _ := yaml.Marshal(before)
|
|
||||||
return string(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper funtion to parse a yaml configuration file.
|
|
||||||
func parse(raw string) (*types.Config, error) {
|
|
||||||
cfg := types.Config{}
|
|
||||||
err := yaml.Unmarshal([]byte(raw), &cfg)
|
|
||||||
return &cfg, err
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package inject
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/franela/goblin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Inject(t *testing.T) {
|
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("Inject params", func() {
|
|
||||||
|
|
||||||
g.It("Should replace vars with $$", func() {
|
|
||||||
s := "echo $$FOO $BAR"
|
|
||||||
m := map[string]string{}
|
|
||||||
m["FOO"] = "BAZ"
|
|
||||||
g.Assert("echo BAZ $BAR").Equal(Inject(s, m))
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should not replace vars with single $", func() {
|
|
||||||
s := "echo $FOO $BAR"
|
|
||||||
m := map[string]string{}
|
|
||||||
m["FOO"] = "BAZ"
|
|
||||||
g.Assert(s).Equal(Inject(s, m))
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should not replace vars in nil map", func() {
|
|
||||||
s := "echo $$FOO $BAR"
|
|
||||||
g.Assert(s).Equal(Inject(s, nil))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_InjectSafe(t *testing.T) {
|
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("Safely Inject params", func() {
|
|
||||||
|
|
||||||
m := map[string]string{}
|
|
||||||
m["TOKEN"] = "FOO"
|
|
||||||
m["SECRET"] = "BAR"
|
|
||||||
c, _ := parse(InjectSafe(yml, m))
|
|
||||||
|
|
||||||
g.It("Should replace vars in notify section", func() {
|
|
||||||
g.Assert(c.Deploy["digital_ocean"].Config["token"]).Equal("FOO")
|
|
||||||
g.Assert(c.Deploy["digital_ocean"].Config["secret"]).Equal("BAR")
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should not replace vars in script section", func() {
|
|
||||||
g.Assert(c.Build.Config["commands"].([]interface{})[0]).Equal("echo $$TOKEN")
|
|
||||||
g.Assert(c.Build.Config["commands"].([]interface{})[1]).Equal("echo $$SECRET")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var yml = `
|
|
||||||
build:
|
|
||||||
image: foo
|
|
||||||
commands:
|
|
||||||
- echo $$TOKEN
|
|
||||||
- echo $$SECRET
|
|
||||||
deploy:
|
|
||||||
digital_ocean:
|
|
||||||
token: $$TOKEN
|
|
||||||
secret: $$SECRET
|
|
||||||
`
|
|
142
pkg/yaml/lint.go
142
pkg/yaml/lint.go
|
@ -1,142 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/drone/drone/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
expectCloneInWorkspace,
|
|
||||||
expectCacheInWorkspace,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.Setup.Config == nil || c.Setup.Config["commands"] == nil {
|
|
||||||
return fmt.Errorf("Yaml must define build / setup commands")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// lint rule that fails if the clone directory is not contained
|
|
||||||
// in the root workspace.
|
|
||||||
func expectCloneInWorkspace(c *common.Config) error {
|
|
||||||
pathv, ok := c.Clone.Config["path"]
|
|
||||||
var path string
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
path, _ = pathv.(string)
|
|
||||||
}
|
|
||||||
if len(path) == 0 {
|
|
||||||
// This should only happen if the transformer was not run
|
|
||||||
return fmt.Errorf("No workspace specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
relative, relOk := filepath.Rel("/drone/src", path)
|
|
||||||
if relOk != nil {
|
|
||||||
return fmt.Errorf("Path is not relative to root")
|
|
||||||
}
|
|
||||||
|
|
||||||
cleaned := filepath.Clean(relative)
|
|
||||||
if strings.Index(cleaned, "../") != -1 {
|
|
||||||
return fmt.Errorf("Cannot clone above the root")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
if strings.Index(step, ":") != -1 {
|
|
||||||
return fmt.Errorf("Cache cannot contain : in the path")
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,177 +0,0 @@
|
||||||
package parser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/franela/goblin"
|
|
||||||
common "github.com/drone/drone/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Linter(t *testing.T) {
|
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("Linter", func() {
|
|
||||||
|
|
||||||
g.It("Should fail when nil build", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
g.Assert(expectBuild(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should fail when no image", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Build: &common.Step{},
|
|
||||||
}
|
|
||||||
g.Assert(expectImage(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should fail when no commands", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Setup: &common.Step{},
|
|
||||||
}
|
|
||||||
g.Assert(expectCommand(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should pass when proper Build provided", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Build: &common.Step{
|
|
||||||
Config: map[string]interface{}{
|
|
||||||
"commands": []string{"echo hi"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.Assert(expectImage(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should pass linter when build properly setup", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Build = &common.Step{}
|
|
||||||
c.Build.Image = "golang"
|
|
||||||
c.Setup = &common.Step{}
|
|
||||||
c.Setup.Config = map[string]interface{}{}
|
|
||||||
c.Setup.Config["commands"] = []string{"go build", "go test"}
|
|
||||||
c.Clone = &common.Step{}
|
|
||||||
c.Clone.Config = map[string]interface{}{}
|
|
||||||
c.Clone.Config["path"] = "/drone/src/foo/bar"
|
|
||||||
c.Publish = map[string]*common.Step{}
|
|
||||||
c.Publish["docker"] = &common.Step{Image: "docker"}
|
|
||||||
c.Deploy = map[string]*common.Step{}
|
|
||||||
c.Deploy["kubernetes"] = &common.Step{Image: "kubernetes"}
|
|
||||||
c.Notify = map[string]*common.Step{}
|
|
||||||
c.Notify["email"] = &common.Step{Image: "email"}
|
|
||||||
g.Assert(Lint(c) == nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should pass with clone path inside workspace", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Clone: &common.Step{
|
|
||||||
Config: map[string]interface{}{
|
|
||||||
"path": "/drone/src/foo/bar",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.Assert(expectCloneInWorkspace(c) == nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should fail with clone path outside workspace", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Clone: &common.Step{
|
|
||||||
Config: map[string]interface{}{
|
|
||||||
"path": "/foo/bar",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.Assert(expectCloneInWorkspace(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should pass with cache path inside workspace", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Build: &common.Step{
|
|
||||||
Cache: []string{".git", "/.git", "/.git/../.git/../.git"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.Assert(expectCacheInWorkspace(c) == nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should fail with cache path outside workspace", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Build: &common.Step{
|
|
||||||
Cache: []string{".git", "/.git", "../../.git"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should fail when caching workspace directory", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Build: &common.Step{
|
|
||||||
Cache: []string{".git", ".git/../"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should fail when : is in the cache path", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Build: &common.Step{
|
|
||||||
Cache: []string{".git", ".git:/../"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_LintPlugins(t *testing.T) {
|
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("Plugin Linter", func() {
|
|
||||||
|
|
||||||
g.It("Should fail un-trusted plugin", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Setup: &common.Step{Image: "foo/baz"},
|
|
||||||
Clone: &common.Step{Image: "foo/bar"},
|
|
||||||
Notify: map[string]*common.Step{},
|
|
||||||
Deploy: map[string]*common.Step{},
|
|
||||||
Publish: map[string]*common.Step{},
|
|
||||||
}
|
|
||||||
o := &Opts{Whitelist: []string{"plugins/*"}}
|
|
||||||
g.Assert(LintPlugins(c, o) != nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should pass when empty whitelist", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Setup: &common.Step{Image: "foo/baz"},
|
|
||||||
Clone: &common.Step{Image: "foo/bar"},
|
|
||||||
Notify: map[string]*common.Step{},
|
|
||||||
Deploy: map[string]*common.Step{},
|
|
||||||
Publish: map[string]*common.Step{},
|
|
||||||
}
|
|
||||||
o := &Opts{Whitelist: []string{}}
|
|
||||||
g.Assert(LintPlugins(c, o) == nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should pass wildcard", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Setup: &common.Step{Image: "plugins/drone-setup"},
|
|
||||||
Clone: &common.Step{Image: "plugins/drone-build"},
|
|
||||||
Notify: map[string]*common.Step{},
|
|
||||||
Deploy: map[string]*common.Step{},
|
|
||||||
Publish: map[string]*common.Step{},
|
|
||||||
}
|
|
||||||
o := &Opts{Whitelist: []string{"plugins/*"}}
|
|
||||||
g.Assert(LintPlugins(c, o) == nil).IsTrue()
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should pass itemized", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Setup: &common.Step{Image: "plugins/drone-setup"},
|
|
||||||
Clone: &common.Step{Image: "plugins/drone-build"},
|
|
||||||
Notify: map[string]*common.Step{},
|
|
||||||
Deploy: map[string]*common.Step{},
|
|
||||||
Publish: map[string]*common.Step{},
|
|
||||||
}
|
|
||||||
o := &Opts{Whitelist: []string{"plugins/drone-setup", "plugins/drone-build"}}
|
|
||||||
g.Assert(LintPlugins(c, o) == nil).IsTrue()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,112 +1,14 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
common "github.com/drone/drone/pkg/types"
|
"github.com/drone/drone/pkg/types"
|
||||||
"github.com/drone/drone/pkg/yaml/inject"
|
|
||||||
"github.com/drone/drone/pkg/yaml/matrix"
|
|
||||||
"github.com/drone/drone/pkg/yaml/transform"
|
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
"github.com/drone/drone/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Opts specifies parser options that will permit
|
func ParseCondition(raw string) (*types.Condition, error) {
|
||||||
// or deny certain Yaml settings.
|
|
||||||
type Opts struct {
|
|
||||||
Volumes bool
|
|
||||||
Network bool
|
|
||||||
Privileged bool
|
|
||||||
Caching bool
|
|
||||||
Whitelist []string
|
|
||||||
}
|
|
||||||
|
|
||||||
var DefaultOpts = &Opts{
|
|
||||||
Volumes: false,
|
|
||||||
Network: false,
|
|
||||||
Privileged: false,
|
|
||||||
Caching: true,
|
|
||||||
Whitelist: []string{"plugins/*"},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses a build matrix and returns
|
|
||||||
// a list of build configurations for each axis
|
|
||||||
// using the default parsing options.
|
|
||||||
func Parse(raw string, r *common.Repo) ([]*common.Config, error) {
|
|
||||||
return ParseOpts(raw, DefaultOpts, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseOpts parses a build matrix and returns
|
|
||||||
// a list of build configurations for each axis
|
|
||||||
// using the provided parsing options.
|
|
||||||
func ParseOpts(raw string, opts *Opts, r *common.Repo) ([]*common.Config, error) {
|
|
||||||
axis, err := matrix.Parse(raw)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
confs := []*common.Config{}
|
|
||||||
|
|
||||||
// when no matrix values exist we should return
|
|
||||||
// a single config value with an empty label.
|
|
||||||
if len(axis) == 0 {
|
|
||||||
conf, err := ParseSingle(raw, opts, r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
confs = append(confs, conf)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ax := range axis {
|
|
||||||
// inject the matrix values into the raw script
|
|
||||||
injected := inject.Inject(raw, ax)
|
|
||||||
conf, err := ParseSingle(injected, opts, r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
conf.Axis = common.Axis(ax)
|
|
||||||
confs = append(confs, conf)
|
|
||||||
}
|
|
||||||
|
|
||||||
return confs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper funtion to parse a yaml configuration file.
|
|
||||||
func ParseSingle(raw string, opts *Opts, r *common.Repo) (*common.Config, error) {
|
|
||||||
conf := &common.Config{}
|
|
||||||
err := yaml.Unmarshal([]byte(raw), conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply rules / transforms
|
|
||||||
transform.Defaults(conf)
|
|
||||||
if !opts.Network {
|
|
||||||
transform.RemoveNetwork(conf)
|
|
||||||
}
|
|
||||||
if !opts.Volumes {
|
|
||||||
transform.RemoveVolumes(conf)
|
|
||||||
}
|
|
||||||
if !opts.Privileged {
|
|
||||||
transform.RemovePrivileged(conf)
|
|
||||||
}
|
|
||||||
transform.Repo(conf, r)
|
|
||||||
if !opts.Caching {
|
|
||||||
transform.RemoveVolumes(conf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lint the yaml file
|
|
||||||
err = Lint(conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = LintPlugins(conf, opts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conf, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseCondition(raw string) (*common.Condition, error) {
|
|
||||||
c := struct {
|
c := struct {
|
||||||
Condition *common.Condition `yaml:"when"`
|
Condition *types.Condition `yaml:"when"`
|
||||||
}{}
|
}{}
|
||||||
err := yaml.Unmarshal([]byte(raw), c)
|
err := yaml.Unmarshal([]byte(raw), c)
|
||||||
return c.Condition, err
|
return c.Condition, err
|
||||||
|
|
|
@ -1,314 +0,0 @@
|
||||||
package transform
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/drone/drone/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// buildRoot is the root build directory.
|
|
||||||
//
|
|
||||||
// If this changes then the matching value in lint.go needs
|
|
||||||
// to be modified as well.
|
|
||||||
const buildRoot = "/drone/src"
|
|
||||||
|
|
||||||
// transformRule applies a check or transformation rule
|
|
||||||
// to the build configuration.
|
|
||||||
type transformRule func(*common.Config)
|
|
||||||
|
|
||||||
var transformRules = []transformRule{
|
|
||||||
transformSetup,
|
|
||||||
transformClone,
|
|
||||||
transformBuild,
|
|
||||||
transformImages,
|
|
||||||
transformDockerPlugin,
|
|
||||||
}
|
|
||||||
|
|
||||||
var rmPrivilegedRules = []transformRule{
|
|
||||||
rmPrivileged,
|
|
||||||
rmVolumes,
|
|
||||||
rmNetwork,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default executes the default transformers that
|
|
||||||
// ensure the minimal Yaml configuration is in place
|
|
||||||
// and correctly configured.
|
|
||||||
func Defaults(c *common.Config) {
|
|
||||||
for _, rule := range transformRules {
|
|
||||||
rule(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safe executes all transformers that remove privileged
|
|
||||||
// options from the Yaml.
|
|
||||||
func Safe(c *common.Config) {
|
|
||||||
for _, rule := range rmPrivilegedRules {
|
|
||||||
rule(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveNetwork executes all transformers that remove
|
|
||||||
// network options from the Yaml.
|
|
||||||
func RemoveNetwork(c *common.Config) {
|
|
||||||
rmNetwork(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransformRemoveVolumes executes all transformers that
|
|
||||||
// remove volume options from the Yaml.
|
|
||||||
func RemoveVolumes(c *common.Config) {
|
|
||||||
rmVolumes(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemovePrivileged executes all transformers that remove
|
|
||||||
// privileged options from the Yaml.
|
|
||||||
func RemovePrivileged(c *common.Config) {
|
|
||||||
rmPrivileged(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repo executes all transformers that rely on repository
|
|
||||||
// information.
|
|
||||||
func Repo(c *common.Config, r *common.Repo) {
|
|
||||||
transformWorkspace(c, r)
|
|
||||||
transformCache(c, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformSetup is a transformer that adds a default
|
|
||||||
// setup step if none exists.
|
|
||||||
func transformSetup(c *common.Config) {
|
|
||||||
c.Setup = &common.Step{}
|
|
||||||
c.Setup.Image = "plugins/drone-build"
|
|
||||||
|
|
||||||
// TODO move below code to separate transform
|
|
||||||
if c.Build == nil {
|
|
||||||
c.Build = &common.Step{}
|
|
||||||
}
|
|
||||||
if c.Build.Config == nil {
|
|
||||||
c.Build.Config = map[string]interface{}{}
|
|
||||||
}
|
|
||||||
////
|
|
||||||
|
|
||||||
c.Setup.Config = c.Build.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformClone is a transformer that adds a default
|
|
||||||
// clone step if none exists.
|
|
||||||
func transformClone(c *common.Config) {
|
|
||||||
if c.Clone == nil {
|
|
||||||
c.Clone = &common.Step{}
|
|
||||||
}
|
|
||||||
if len(c.Clone.Image) == 0 {
|
|
||||||
c.Clone.Image = "plugins/drone-git"
|
|
||||||
c.Clone.Volumes = nil
|
|
||||||
c.Clone.NetworkMode = ""
|
|
||||||
}
|
|
||||||
if c.Clone.Config == nil {
|
|
||||||
c.Clone.Config = map[string]interface{}{}
|
|
||||||
c.Clone.Config["depth"] = 50
|
|
||||||
c.Clone.Config["recursive"] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformBuild is a transformer that removes the
|
|
||||||
// build configuration vargs. They should have
|
|
||||||
// already been transferred to the Setup step.
|
|
||||||
func transformBuild(c *common.Config) {
|
|
||||||
c.Build.Config = nil
|
|
||||||
c.Build.Entrypoint = []string{"/bin/bash", "-e"}
|
|
||||||
c.Build.Command = []string{"/drone/bin/build.sh"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformImages is a transformer that ensures every
|
|
||||||
// step has an image and uses a fully-qualified
|
|
||||||
// image name.
|
|
||||||
func transformImages(c *common.Config) {
|
|
||||||
c.Setup.Image = imageName(c.Setup.Image)
|
|
||||||
c.Clone.Image = imageName(c.Clone.Image)
|
|
||||||
for name, step := range c.Publish {
|
|
||||||
step.Image = imageNameDefault(step.Image, name)
|
|
||||||
}
|
|
||||||
for name, step := range c.Deploy {
|
|
||||||
step.Image = imageNameDefault(step.Image, name)
|
|
||||||
}
|
|
||||||
for name, step := range c.Notify {
|
|
||||||
step.Image = imageNameDefault(step.Image, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformDockerPlugin is a transformer that ensures the
|
|
||||||
// official Docker plugin can run in privileged mode. It
|
|
||||||
// will disable volumes and network mode for added protection.
|
|
||||||
func transformDockerPlugin(c *common.Config) {
|
|
||||||
for _, step := range c.Publish {
|
|
||||||
if step.Image == "plugins/drone-docker" {
|
|
||||||
step.Privileged = true
|
|
||||||
step.Volumes = nil
|
|
||||||
step.NetworkMode = ""
|
|
||||||
step.Entrypoint = []string{}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rmPrivileged is a transformer that ensures every
|
|
||||||
// step is executed in non-privileged mode.
|
|
||||||
func rmPrivileged(c *common.Config) {
|
|
||||||
c.Setup.Privileged = false
|
|
||||||
c.Clone.Privileged = false
|
|
||||||
c.Build.Privileged = false
|
|
||||||
for _, step := range c.Publish {
|
|
||||||
if step.Image == "plugins/drone-docker" {
|
|
||||||
continue // the official docker plugin is the only exception here
|
|
||||||
}
|
|
||||||
step.Privileged = false
|
|
||||||
}
|
|
||||||
for _, step := range c.Deploy {
|
|
||||||
step.Privileged = false
|
|
||||||
}
|
|
||||||
for _, step := range c.Notify {
|
|
||||||
step.Privileged = false
|
|
||||||
}
|
|
||||||
for _, step := range c.Compose {
|
|
||||||
step.Privileged = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rmVolumes is a transformer that ensures every
|
|
||||||
// step is executed without volumes.
|
|
||||||
func rmVolumes(c *common.Config) {
|
|
||||||
c.Setup.Volumes = nil
|
|
||||||
c.Clone.Volumes = nil
|
|
||||||
c.Build.Volumes = nil
|
|
||||||
for _, step := range c.Publish {
|
|
||||||
step.Volumes = nil
|
|
||||||
}
|
|
||||||
for _, step := range c.Deploy {
|
|
||||||
step.Volumes = nil
|
|
||||||
}
|
|
||||||
for _, step := range c.Notify {
|
|
||||||
step.Volumes = nil
|
|
||||||
}
|
|
||||||
for _, step := range c.Compose {
|
|
||||||
step.Volumes = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rmNetwork is a transformer that ensures every
|
|
||||||
// step is executed with default bridge networking.
|
|
||||||
func rmNetwork(c *common.Config) {
|
|
||||||
c.Setup.NetworkMode = ""
|
|
||||||
c.Clone.NetworkMode = ""
|
|
||||||
c.Build.NetworkMode = ""
|
|
||||||
for _, step := range c.Publish {
|
|
||||||
step.NetworkMode = ""
|
|
||||||
}
|
|
||||||
for _, step := range c.Deploy {
|
|
||||||
step.NetworkMode = ""
|
|
||||||
}
|
|
||||||
for _, step := range c.Notify {
|
|
||||||
step.NetworkMode = ""
|
|
||||||
}
|
|
||||||
for _, step := range c.Compose {
|
|
||||||
step.NetworkMode = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformWorkspace is a transformer that adds the workspace
|
|
||||||
// directory to the configuration based on the repository
|
|
||||||
// information.
|
|
||||||
func transformWorkspace(c *common.Config, r *common.Repo) {
|
|
||||||
pathv, ok := c.Clone.Config["path"]
|
|
||||||
var path string
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
path, _ = pathv.(string)
|
|
||||||
}
|
|
||||||
if len(path) == 0 {
|
|
||||||
path = repoPath(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Clone.Config["path"] = filepath.Join(buildRoot, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformCache is a transformer that adds volumes
|
|
||||||
// to the configuration based on the cache.
|
|
||||||
func transformCache(c *common.Config, r *common.Repo) {
|
|
||||||
cacheCount := len(c.Build.Cache)
|
|
||||||
|
|
||||||
if cacheCount == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
volumes := make([]string, cacheCount)
|
|
||||||
|
|
||||||
cache := cacheRoot(r)
|
|
||||||
workspace := c.Clone.Config["path"].(string)
|
|
||||||
|
|
||||||
for i, dir := range c.Build.Cache {
|
|
||||||
cacheDir := filepath.Join(cache, dir)
|
|
||||||
workspaceDir := filepath.Join(workspace, dir)
|
|
||||||
|
|
||||||
volumes[i] = fmt.Sprintf("%s:%s", cacheDir, workspaceDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Setup.Volumes = append(c.Setup.Volumes, volumes...)
|
|
||||||
c.Clone.Volumes = append(c.Clone.Volumes, volumes...)
|
|
||||||
c.Build.Volumes = append(c.Build.Volumes, volumes...)
|
|
||||||
|
|
||||||
for _, step := range c.Publish {
|
|
||||||
step.Volumes = append(step.Volumes, volumes...)
|
|
||||||
}
|
|
||||||
for _, step := range c.Deploy {
|
|
||||||
step.Volumes = append(step.Volumes, volumes...)
|
|
||||||
}
|
|
||||||
for _, step := range c.Notify {
|
|
||||||
step.Volumes = append(step.Volumes, volumes...)
|
|
||||||
}
|
|
||||||
for _, step := range c.Compose {
|
|
||||||
step.Volumes = append(step.Volumes, volumes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// imageName is a helper function that resolves the
|
|
||||||
// image name. When using official drone plugins it
|
|
||||||
// is possible to use an alias name. This converts to
|
|
||||||
// the fully qualified name.
|
|
||||||
func imageName(name string) string {
|
|
||||||
if strings.Contains(name, "/") {
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
name = strings.Replace(name, "_", "-", -1)
|
|
||||||
name = "plugins/drone-" + name
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
// imageNameDefault is a helper function that resolves
|
|
||||||
// the image name. If the image name is blank the
|
|
||||||
// default name is used instead.
|
|
||||||
func imageNameDefault(name, defaultName string) string {
|
|
||||||
if len(name) == 0 {
|
|
||||||
name = defaultName
|
|
||||||
}
|
|
||||||
return imageName(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// workspaceRoot is a helper function that determines the
|
|
||||||
// default workspace the build runs in.
|
|
||||||
func workspaceRoot(r *common.Repo) string {
|
|
||||||
return filepath.Join(buildRoot, repoPath(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
// cacheRoot is a helper function that deteremines the
|
|
||||||
// default caching root.
|
|
||||||
func cacheRoot(r *common.Repo) string {
|
|
||||||
return filepath.Join("/tmp/drone/cache", repoPath(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
// repoPath is a helper function that creates a path based
|
|
||||||
// on the host and repository name.
|
|
||||||
func repoPath(r *common.Repo) string {
|
|
||||||
parsed, _ := url.Parse(r.Link)
|
|
||||||
return filepath.Join(parsed.Host, r.FullName)
|
|
||||||
}
|
|
|
@ -1,220 +0,0 @@
|
||||||
package transform
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/franela/goblin"
|
|
||||||
common "github.com/drone/drone/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Transform(t *testing.T) {
|
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("Transform", func() {
|
|
||||||
|
|
||||||
g.It("Should transform setup step", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Build = &common.Step{}
|
|
||||||
c.Build.Config = map[string]interface{}{}
|
|
||||||
transformSetup(c)
|
|
||||||
g.Assert(c.Setup != nil).IsTrue()
|
|
||||||
g.Assert(c.Setup.Image).Equal("plugins/drone-build")
|
|
||||||
g.Assert(c.Setup.Config).Equal(c.Build.Config)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should transform clone step", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
transformClone(c)
|
|
||||||
g.Assert(c.Clone != nil).IsTrue()
|
|
||||||
g.Assert(c.Clone.Image).Equal("plugins/drone-git")
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should transform build", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Build = &common.Step{}
|
|
||||||
c.Build.Config = map[string]interface{}{}
|
|
||||||
c.Build.Config["commands"] = []string{"echo hello"}
|
|
||||||
transformBuild(c)
|
|
||||||
g.Assert(len(c.Build.Config)).Equal(0)
|
|
||||||
g.Assert(c.Build.Entrypoint[0]).Equal("/bin/bash")
|
|
||||||
g.Assert(c.Build.Command[0]).Equal("/drone/bin/build.sh")
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should transform images", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Setup = &common.Step{Image: "foo"}
|
|
||||||
c.Clone = &common.Step{Image: "foo/bar"}
|
|
||||||
c.Build = &common.Step{Image: "golang"}
|
|
||||||
c.Publish = map[string]*common.Step{"google_compute": &common.Step{}}
|
|
||||||
c.Deploy = map[string]*common.Step{"amazon": &common.Step{}}
|
|
||||||
c.Notify = map[string]*common.Step{"slack": &common.Step{}}
|
|
||||||
transformImages(c)
|
|
||||||
|
|
||||||
g.Assert(c.Setup.Image).Equal("plugins/drone-foo")
|
|
||||||
g.Assert(c.Clone.Image).Equal("foo/bar")
|
|
||||||
g.Assert(c.Build.Image).Equal("golang")
|
|
||||||
g.Assert(c.Publish["google_compute"].Image).Equal("plugins/drone-google-compute")
|
|
||||||
g.Assert(c.Deploy["amazon"].Image).Equal("plugins/drone-amazon")
|
|
||||||
g.Assert(c.Notify["slack"].Image).Equal("plugins/drone-slack")
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should transform docker plugin", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Publish = map[string]*common.Step{}
|
|
||||||
c.Publish["docker"] = &common.Step{Image: "plugins/drone-docker"}
|
|
||||||
transformDockerPlugin(c)
|
|
||||||
g.Assert(c.Publish["docker"].Privileged).Equal(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should remove privileged flag", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Setup = &common.Step{Privileged: true}
|
|
||||||
c.Clone = &common.Step{Privileged: true}
|
|
||||||
c.Build = &common.Step{Privileged: true}
|
|
||||||
c.Compose = map[string]*common.Step{"postgres": &common.Step{Privileged: true}}
|
|
||||||
c.Publish = map[string]*common.Step{"google": &common.Step{Privileged: true}}
|
|
||||||
c.Deploy = map[string]*common.Step{"amazon": &common.Step{Privileged: true}}
|
|
||||||
c.Notify = map[string]*common.Step{"slack": &common.Step{Privileged: true}}
|
|
||||||
rmPrivileged(c)
|
|
||||||
|
|
||||||
g.Assert(c.Setup.Privileged).Equal(false)
|
|
||||||
g.Assert(c.Clone.Privileged).Equal(false)
|
|
||||||
g.Assert(c.Build.Privileged).Equal(false)
|
|
||||||
g.Assert(c.Compose["postgres"].Privileged).Equal(false)
|
|
||||||
g.Assert(c.Publish["google"].Privileged).Equal(false)
|
|
||||||
g.Assert(c.Deploy["amazon"].Privileged).Equal(false)
|
|
||||||
g.Assert(c.Notify["slack"].Privileged).Equal(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should not remove docker plugin privileged flag", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Setup = &common.Step{}
|
|
||||||
c.Clone = &common.Step{}
|
|
||||||
c.Build = &common.Step{}
|
|
||||||
c.Publish = map[string]*common.Step{}
|
|
||||||
c.Publish["docker"] = &common.Step{Image: "plugins/drone-docker"}
|
|
||||||
transformDockerPlugin(c)
|
|
||||||
g.Assert(c.Publish["docker"].Privileged).Equal(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should remove volumes", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Setup = &common.Step{Volumes: []string{"/:/tmp"}}
|
|
||||||
c.Clone = &common.Step{Volumes: []string{"/:/tmp"}}
|
|
||||||
c.Build = &common.Step{Volumes: []string{"/:/tmp"}}
|
|
||||||
c.Compose = map[string]*common.Step{"postgres": &common.Step{Volumes: []string{"/:/tmp"}}}
|
|
||||||
c.Publish = map[string]*common.Step{"google": &common.Step{Volumes: []string{"/:/tmp"}}}
|
|
||||||
c.Deploy = map[string]*common.Step{"amazon": &common.Step{Volumes: []string{"/:/tmp"}}}
|
|
||||||
c.Notify = map[string]*common.Step{"slack": &common.Step{Volumes: []string{"/:/tmp"}}}
|
|
||||||
rmVolumes(c)
|
|
||||||
|
|
||||||
g.Assert(len(c.Setup.Volumes)).Equal(0)
|
|
||||||
g.Assert(len(c.Clone.Volumes)).Equal(0)
|
|
||||||
g.Assert(len(c.Build.Volumes)).Equal(0)
|
|
||||||
g.Assert(len(c.Compose["postgres"].Volumes)).Equal(0)
|
|
||||||
g.Assert(len(c.Publish["google"].Volumes)).Equal(0)
|
|
||||||
g.Assert(len(c.Deploy["amazon"].Volumes)).Equal(0)
|
|
||||||
g.Assert(len(c.Notify["slack"].Volumes)).Equal(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should remove network", func() {
|
|
||||||
c := &common.Config{}
|
|
||||||
c.Setup = &common.Step{NetworkMode: "host"}
|
|
||||||
c.Clone = &common.Step{NetworkMode: "host"}
|
|
||||||
c.Build = &common.Step{NetworkMode: "host"}
|
|
||||||
c.Compose = map[string]*common.Step{"postgres": &common.Step{NetworkMode: "host"}}
|
|
||||||
c.Publish = map[string]*common.Step{"google": &common.Step{NetworkMode: "host"}}
|
|
||||||
c.Deploy = map[string]*common.Step{"amazon": &common.Step{NetworkMode: "host"}}
|
|
||||||
c.Notify = map[string]*common.Step{"slack": &common.Step{NetworkMode: "host"}}
|
|
||||||
rmNetwork(c)
|
|
||||||
|
|
||||||
g.Assert(c.Setup.NetworkMode).Equal("")
|
|
||||||
g.Assert(c.Clone.NetworkMode).Equal("")
|
|
||||||
g.Assert(c.Build.NetworkMode).Equal("")
|
|
||||||
g.Assert(c.Compose["postgres"].NetworkMode).Equal("")
|
|
||||||
g.Assert(c.Publish["google"].NetworkMode).Equal("")
|
|
||||||
g.Assert(c.Deploy["amazon"].NetworkMode).Equal("")
|
|
||||||
g.Assert(c.Notify["slack"].NetworkMode).Equal("")
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should return full qualified image name", func() {
|
|
||||||
g.Assert(imageName("microsoft/azure")).Equal("microsoft/azure")
|
|
||||||
g.Assert(imageName("azure")).Equal("plugins/drone-azure")
|
|
||||||
g.Assert(imageName("azure_storage")).Equal("plugins/drone-azure-storage")
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should have cached volumes", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Setup: &common.Step{},
|
|
||||||
Clone: &common.Step{
|
|
||||||
Config: map[string]interface{}{},
|
|
||||||
},
|
|
||||||
Build: &common.Step{
|
|
||||||
Cache: []string{".git", "foo", "bar"},
|
|
||||||
},
|
|
||||||
Notify: map[string]*common.Step{},
|
|
||||||
Deploy: map[string]*common.Step{},
|
|
||||||
Publish: map[string]*common.Step{},
|
|
||||||
}
|
|
||||||
r := &common.Repo{
|
|
||||||
Link: "https://github.com/drone/drone",
|
|
||||||
FullName: "drone/drone",
|
|
||||||
}
|
|
||||||
transformWorkspace(c, r)
|
|
||||||
transformCache(c, r)
|
|
||||||
|
|
||||||
cacheCount := len(c.Build.Cache)
|
|
||||||
|
|
||||||
test := func(s *common.Step) {
|
|
||||||
g.Assert(len(s.Volumes)).Equal(cacheCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
testRange := func(s map[string]*common.Step) {
|
|
||||||
for _, step := range s {
|
|
||||||
test(step)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test(c.Setup)
|
|
||||||
test(c.Clone)
|
|
||||||
test(c.Build)
|
|
||||||
testRange(c.Publish)
|
|
||||||
testRange(c.Deploy)
|
|
||||||
testRange(c.Notify)
|
|
||||||
testRange(c.Compose)
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should have default workspace directory", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Clone: &common.Step{
|
|
||||||
Config: map[string]interface{}{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
r := &common.Repo{
|
|
||||||
Link: "https://github.com/drone/drone",
|
|
||||||
FullName: "drone/drone",
|
|
||||||
}
|
|
||||||
transformWorkspace(c, r)
|
|
||||||
|
|
||||||
g.Assert(c.Clone.Config["path"]).Equal(workspaceRoot(r))
|
|
||||||
})
|
|
||||||
|
|
||||||
g.It("Should use path for working directory", func() {
|
|
||||||
c := &common.Config{
|
|
||||||
Clone: &common.Step{
|
|
||||||
Config: map[string]interface{}{
|
|
||||||
"path": "foo/bar",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
r := &common.Repo{
|
|
||||||
Link: "https://github.com/drone/drone",
|
|
||||||
FullName: "drone/drone",
|
|
||||||
}
|
|
||||||
transformWorkspace(c, r)
|
|
||||||
|
|
||||||
g.Assert(c.Clone.Config["path"]).Equal(filepath.Join(buildRoot, "foo/bar"))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in a new issue