Merge pull request #1149 from donny-dont/features/git-checkout-specified
Adding support for setting the workspace directly in the config
This commit is contained in:
commit
aeee201796
7 changed files with 134 additions and 43 deletions
|
@ -5,9 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
log "github.com/drone/drone/Godeps/_workspace/src/github.com/Sirupsen/logrus"
|
log "github.com/drone/drone/Godeps/_workspace/src/github.com/Sirupsen/logrus"
|
||||||
|
@ -37,7 +35,6 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
createClone(ctx)
|
|
||||||
|
|
||||||
// creates the Docker client, connecting to the
|
// creates the Docker client, connecting to the
|
||||||
// linked Docker daemon
|
// linked Docker daemon
|
||||||
|
@ -68,6 +65,7 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
createClone(ctx)
|
||||||
|
|
||||||
var execs []execFunc
|
var execs []execFunc
|
||||||
if *clone {
|
if *clone {
|
||||||
|
@ -130,13 +128,15 @@ func createClone(c *Context) error {
|
||||||
// to the clone object for merge requests from bitbucket, gitlab, et al
|
// to the clone object for merge requests from bitbucket, gitlab, et al
|
||||||
// if len(c.Commit.PullRequest) != 0 {
|
// if len(c.Commit.PullRequest) != 0 {
|
||||||
// }
|
// }
|
||||||
|
pathv, ok := c.Conf.Clone.Config["path"]
|
||||||
url_, err := url.Parse(c.Repo.Link)
|
if ok {
|
||||||
if err != nil {
|
path, ok := pathv.(string)
|
||||||
return err
|
if ok {
|
||||||
|
c.Clone.Dir = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c.Clone.Dir = filepath.Join("/drone/src", url_.Host, c.Repo.FullName)
|
return fmt.Errorf("Workspace path not found")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseContext() (*Context, error) {
|
func parseContext() (*Context, error) {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/samalba/dockerclient"
|
"github.com/drone/drone/Godeps/_workspace/src/github.com/samalba/dockerclient"
|
||||||
common "github.com/drone/drone/pkg/types"
|
common "github.com/drone/drone/pkg/types"
|
||||||
"github.com/drone/drone/pkg/yaml"
|
"github.com/drone/drone/pkg/yaml"
|
||||||
|
@ -64,17 +62,6 @@ func setup(c *Context) error {
|
||||||
c.Conf.Build.Environment = append(c.Conf.Build.Environment, env)
|
c.Conf.Build.Environment = append(c.Conf.Build.Environment, env)
|
||||||
}
|
}
|
||||||
|
|
||||||
// attempt to extract the clone path. i'm not a huge fan of
|
|
||||||
// this, by the way, but for now we'll keep it.
|
|
||||||
// TODO consider moving this to a transform?
|
|
||||||
pathv, ok := c.Conf.Clone.Config["path"]
|
|
||||||
if ok {
|
|
||||||
path, ok := pathv.(string)
|
|
||||||
if ok {
|
|
||||||
c.Clone.Dir = filepath.Join("/drone/src", path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ package builtin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/samalba/dockerclient"
|
"github.com/drone/drone/Godeps/_workspace/src/github.com/samalba/dockerclient"
|
||||||
"github.com/drone/drone/pkg/docker"
|
"github.com/drone/drone/pkg/docker"
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
// fails it should return an error message.
|
// fails it should return an error message.
|
||||||
type lintRule func(*common.Config) error
|
type lintRule func(*common.Config) error
|
||||||
|
|
||||||
var lintRules = [...]lintRule{
|
var lintRules = []lintRule{
|
||||||
expectBuild,
|
expectBuild,
|
||||||
expectImage,
|
expectImage,
|
||||||
expectCommand,
|
expectCommand,
|
||||||
|
@ -22,6 +22,7 @@ var lintRules = [...]lintRule{
|
||||||
expectTrustedPublish,
|
expectTrustedPublish,
|
||||||
expectTrustedDeploy,
|
expectTrustedDeploy,
|
||||||
expectTrustedNotify,
|
expectTrustedNotify,
|
||||||
|
expectCloneInWorkspace,
|
||||||
expectCacheInWorkspace,
|
expectCacheInWorkspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +107,33 @@ func expectTrustedNotify(c *common.Config) error {
|
||||||
return nil
|
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
|
// lint rule that fails if the cache directories are not contained
|
||||||
// in the workspace.
|
// in the workspace.
|
||||||
func expectCacheInWorkspace(c *common.Config) error {
|
func expectCacheInWorkspace(c *common.Config) error {
|
||||||
|
|
|
@ -79,6 +79,9 @@ func Test_Linter(t *testing.T) {
|
||||||
c.Build.Image = "golang"
|
c.Build.Image = "golang"
|
||||||
c.Build.Config = map[string]interface{}{}
|
c.Build.Config = map[string]interface{}{}
|
||||||
c.Build.Config["commands"] = []string{"go build", "go test"}
|
c.Build.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 = map[string]*common.Step{}
|
||||||
c.Publish["docker"] = &common.Step{Image: "docker"}
|
c.Publish["docker"] = &common.Step{Image: "docker"}
|
||||||
c.Deploy = map[string]*common.Step{}
|
c.Deploy = map[string]*common.Step{}
|
||||||
|
@ -88,19 +91,41 @@ func Test_Linter(t *testing.T) {
|
||||||
g.Assert(Lint(c) == nil).IsTrue()
|
g.Assert(Lint(c) == nil).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should pass with path inside workspace", func() {
|
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{
|
c := &common.Config{
|
||||||
Build: &common.Step{
|
Build: &common.Step{
|
||||||
Cache: []string{".git","/.git","/.git/../.git/../.git"},
|
Cache: []string{".git", "/.git", "/.git/../.git/../.git"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
g.Assert(expectCacheInWorkspace(c) == nil).IsTrue()
|
g.Assert(expectCacheInWorkspace(c) == nil).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should fail with path outside workspace", func() {
|
g.It("Should fail with cache path outside workspace", func() {
|
||||||
c := &common.Config{
|
c := &common.Config{
|
||||||
Build: &common.Step{
|
Build: &common.Step{
|
||||||
Cache: []string{".git","/.git","../../.git"},
|
Cache: []string{".git", "/.git", "../../.git"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
||||||
|
@ -109,16 +134,16 @@ func Test_Linter(t *testing.T) {
|
||||||
g.It("Should fail when caching workspace directory", func() {
|
g.It("Should fail when caching workspace directory", func() {
|
||||||
c := &common.Config{
|
c := &common.Config{
|
||||||
Build: &common.Step{
|
Build: &common.Step{
|
||||||
Cache: []string{".git",".git/../"},
|
Cache: []string{".git", ".git/../"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should fail when : is in the path", func() {
|
g.It("Should fail when : is in the cache path", func() {
|
||||||
c := &common.Config{
|
c := &common.Config{
|
||||||
Build: &common.Step{
|
Build: &common.Step{
|
||||||
Cache: []string{".git",".git:/../"},
|
Cache: []string{".git", ".git:/../"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
g.Assert(expectCacheInWorkspace(c) != nil).IsTrue()
|
||||||
|
|
|
@ -9,6 +9,12 @@ import (
|
||||||
common "github.com/drone/drone/pkg/types"
|
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
|
// transformRule applies a check or transformation rule
|
||||||
// to the build configuration.
|
// to the build configuration.
|
||||||
type transformRule func(*common.Config)
|
type transformRule func(*common.Config)
|
||||||
|
@ -65,7 +71,7 @@ func RemovePrivileged(c *common.Config) {
|
||||||
// Repo executes all transformers that rely on repository
|
// Repo executes all transformers that rely on repository
|
||||||
// information.
|
// information.
|
||||||
func Repo(c *common.Config, r *common.Repo) {
|
func Repo(c *common.Config, r *common.Repo) {
|
||||||
transformWorkspace(c, r)
|
transformWorkspace(c, r)
|
||||||
transformCache(c, r)
|
transformCache(c, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +209,17 @@ func rmNetwork(c *common.Config) {
|
||||||
// directory to the configuration based on the repository
|
// directory to the configuration based on the repository
|
||||||
// information.
|
// information.
|
||||||
func transformWorkspace(c *common.Config, r *common.Repo) {
|
func transformWorkspace(c *common.Config, r *common.Repo) {
|
||||||
//c.Clone.Dir = workspaceRoot(r)
|
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
|
// transformCache is a transformer that adds volumes
|
||||||
|
@ -211,21 +227,20 @@ func transformWorkspace(c *common.Config, r *common.Repo) {
|
||||||
func transformCache(c *common.Config, r *common.Repo) {
|
func transformCache(c *common.Config, r *common.Repo) {
|
||||||
cacheCount := len(c.Build.Cache)
|
cacheCount := len(c.Build.Cache)
|
||||||
|
|
||||||
if cacheCount == 0 {
|
if cacheCount == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
volumes := make([]string, cacheCount)
|
volumes := make([]string, cacheCount)
|
||||||
|
|
||||||
cache := cacheRoot(r)
|
cache := cacheRoot(r)
|
||||||
workspace := workspaceRoot(r)
|
workspace := c.Clone.Config["path"].(string)
|
||||||
|
|
||||||
for i, dir := range c.Build.Cache {
|
for i, dir := range c.Build.Cache {
|
||||||
cacheDir := filepath.Join(cache, dir)
|
cacheDir := filepath.Join(cache, dir)
|
||||||
workspaceDir := filepath.Join(workspace, dir)
|
workspaceDir := filepath.Join(workspace, dir)
|
||||||
|
|
||||||
volumes[i] = fmt.Sprintf("%s:%s", cacheDir, workspaceDir)
|
volumes[i] = fmt.Sprintf("%s:%s", cacheDir, workspaceDir)
|
||||||
fmt.Printf("Volume %s", volumes[i])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Setup.Volumes = append(c.Setup.Volumes, volumes...)
|
c.Setup.Volumes = append(c.Setup.Volumes, volumes...)
|
||||||
|
@ -272,7 +287,7 @@ func imageNameDefault(name, defaultName string) string {
|
||||||
// workspaceRoot is a helper function that determines the
|
// workspaceRoot is a helper function that determines the
|
||||||
// default workspace the build runs in.
|
// default workspace the build runs in.
|
||||||
func workspaceRoot(r *common.Repo) string {
|
func workspaceRoot(r *common.Repo) string {
|
||||||
return filepath.Join("/drone/src", repoPath(r))
|
return filepath.Join(buildRoot, repoPath(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
// cacheRoot is a helper function that deteremines the
|
// cacheRoot is a helper function that deteremines the
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package transform
|
package transform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/franela/goblin"
|
"github.com/drone/drone/Godeps/_workspace/src/github.com/franela/goblin"
|
||||||
|
@ -146,21 +147,24 @@ func Test_Transform(t *testing.T) {
|
||||||
g.It("Should have cached volumes", func() {
|
g.It("Should have cached volumes", func() {
|
||||||
c := &common.Config{
|
c := &common.Config{
|
||||||
Setup: &common.Step{},
|
Setup: &common.Step{},
|
||||||
Clone: &common.Step{},
|
Clone: &common.Step{
|
||||||
|
Config: map[string]interface{}{},
|
||||||
|
},
|
||||||
Build: &common.Step{
|
Build: &common.Step{
|
||||||
Cache: []string{".git","foo","bar"},
|
Cache: []string{".git", "foo", "bar"},
|
||||||
},
|
},
|
||||||
Notify: map[string]*common.Step{},
|
Notify: map[string]*common.Step{},
|
||||||
Deploy: map[string]*common.Step{},
|
Deploy: map[string]*common.Step{},
|
||||||
Publish: map[string]*common.Step{},
|
Publish: map[string]*common.Step{},
|
||||||
}
|
}
|
||||||
r := &common.Repo{
|
r := &common.Repo{
|
||||||
Link: "https://github.com/drone/drone",
|
Link: "https://github.com/drone/drone",
|
||||||
FullName: "drone/drone",
|
FullName: "drone/drone",
|
||||||
}
|
}
|
||||||
|
transformWorkspace(c, r)
|
||||||
transformCache(c, r)
|
transformCache(c, r)
|
||||||
|
|
||||||
cacheCount := len(c.Build.Cache)
|
cacheCount := len(c.Build.Cache)
|
||||||
|
|
||||||
test := func(s *common.Step) {
|
test := func(s *common.Step) {
|
||||||
g.Assert(len(s.Volumes)).Equal(cacheCount)
|
g.Assert(len(s.Volumes)).Equal(cacheCount)
|
||||||
|
@ -172,7 +176,7 @@ func Test_Transform(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test(c.Setup)
|
test(c.Setup)
|
||||||
test(c.Clone)
|
test(c.Clone)
|
||||||
test(c.Build)
|
test(c.Build)
|
||||||
testRange(c.Publish)
|
testRange(c.Publish)
|
||||||
|
@ -180,5 +184,37 @@ func Test_Transform(t *testing.T) {
|
||||||
testRange(c.Notify)
|
testRange(c.Notify)
|
||||||
testRange(c.Compose)
|
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