From 27c770e097ff01cd653b287cb1ab00482e348977 Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Tue, 29 Apr 2014 19:48:45 +0700 Subject: [PATCH 1/8] Fix RepoHandler --- pkg/database/testing/testing.go | 10 +++++ pkg/handler/handler.go | 2 +- pkg/handler/testing/handler_test.go | 68 +++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 pkg/handler/testing/handler_test.go diff --git a/pkg/database/testing/testing.go b/pkg/database/testing/testing.go index 59bd3263a..3cca73927 100644 --- a/pkg/database/testing/testing.go +++ b/pkg/database/testing/testing.go @@ -115,10 +115,20 @@ func Setup() { Token: "789", GitlabToken: "789", Admin: false} + user4 := User{ + Password: "$2a$10$b8d63QsTL38vx7lj0HEHfOdbu1PCAg6Gfca74UavkXooIBx9YxopS", + Name: "Rick El Toro", + Email: "rick@el.to.ro", + Gravatar: "c2180a539620d90d68eaeb848364f1c2", + Token: "987", + GitlabToken: "987", + Admin: false} + database.SaveUser(&user1) database.SaveUser(&user2) database.SaveUser(&user3) + database.SaveUser(&user4) // create dummy team data team1 := Team{ diff --git a/pkg/handler/handler.go b/pkg/handler/handler.go index 7adc6ab58..2af9150c9 100644 --- a/pkg/handler/handler.go +++ b/pkg/handler/handler.go @@ -102,7 +102,7 @@ func (h RepoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // The User must own the repository OR be a member // of the Team that owns the repository OR the repo // must not be private. - if repo.Private == false && user.ID != repo.UserID { + if repo.Private && user.ID != repo.UserID { if member, _ := database.IsMember(user.ID, repo.TeamID); !member { RenderNotFound(w) return diff --git a/pkg/handler/testing/handler_test.go b/pkg/handler/testing/handler_test.go new file mode 100644 index 000000000..9ea71824d --- /dev/null +++ b/pkg/handler/testing/handler_test.go @@ -0,0 +1,68 @@ +package testing + +import ( + "net/http" + "net/http/httptest" + "testing" + + . "github.com/drone/drone/pkg/database/testing" + "github.com/drone/drone/pkg/handler" + . "github.com/drone/drone/pkg/model" + + "github.com/bmizerany/pat" + . "github.com/smartystreets/goconvey/convey" +) + +func TestRepoHandler(t *testing.T) { + Setup() + defer Teardown() + + m := pat.New() + + Convey("Repo Handler", t, func() { + m.Get("/:host/:owner/:name", handler.RepoHandler(dummyUserRepo)) + Convey("Public repo can be viewed without login", func() { + req, err := http.NewRequest("GET", "/bitbucket.org/drone/test", nil) + So(err, ShouldBeNil) + rec := httptest.NewRecorder() + m.ServeHTTP(rec, req) + So(rec.Code, ShouldEqual, 200) + }) + Convey("Public repo can be viewed by another user", func() { + req, err := http.NewRequest("GET", "/bitbucket.org/drone/test", nil) + So(err, ShouldBeNil) + rec := httptest.NewRecorder() + setUserSession(rec, req, "cavepig@gmail.com") + m.ServeHTTP(rec, req) + So(rec.Code, ShouldEqual, 200) + }) + + Convey("Private repo can not be viewed without login", func() { + req, err := http.NewRequest("GET", "/github.com/drone/drone", nil) + So(err, ShouldBeNil) + rec := httptest.NewRecorder() + m.ServeHTTP(rec, req) + So(rec.Code, ShouldEqual, 303) + }) + Convey("Private repo can not be viewed by a non team member", func() { + req, err := http.NewRequest("GET", "/github.com/drone/drone", nil) + So(err, ShouldBeNil) + rec := httptest.NewRecorder() + setUserSession(rec, req, "rick@el.to.ro") + m.ServeHTTP(rec, req) + So(rec.Code, ShouldEqual, 404) + }) + }) +} + +func dummyUserRepo(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { + return handler.RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) +} + +func setUserSession(w http.ResponseWriter, r *http.Request, username string) { + handler.SetCookie(w, r, "_sess", username) + resp := http.Response{Header: w.Header()} + for _, v := range resp.Cookies() { + r.AddCookie(v) + } +} From 4686cfecccd5e0eb39b5dd074f06a55e6b6043aa Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Tue, 29 Apr 2014 15:07:29 -0500 Subject: [PATCH 2/8] Support custom PyPI repositories --- README.md | 1 + pkg/plugin/publish/pypi.go | 33 ++++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index cf6faef1d..2540c3130 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,7 @@ Drone currently has these `deploy` and `publish` plugins implemented (more to co **publish** - [Amazon s3](#docs) - [OpenStack Swift](#docs) +- [PyPI](#docs) ### Notifications diff --git a/pkg/plugin/publish/pypi.go b/pkg/plugin/publish/pypi.go index faf28c6f6..4b3ee1472 100644 --- a/pkg/plugin/publish/pypi.go +++ b/pkg/plugin/publish/pypi.go @@ -10,17 +10,18 @@ var pypirc = ` cat < $HOME/.pypirc [distutils] index-servers = - pypi + %s -[pypi] +[%s] username:%s password:%s +%s EOF` var deployCmd = ` -if [ -z $_PYPI_SETUP_PY ] +if [ -n "$_PYPI_SETUP_PY" ] then - python $_PYPI_SETUP_PY sdist %s upload + python $_PYPI_SETUP_PY sdist %s upload -r %s if [ $? -ne 0 ] then echo "Deploy to PyPI failed - perhaps due to the version number not being incremented. Continuing..." @@ -31,27 +32,41 @@ fi ` type PyPI struct { - Username string `yaml:"username,omitempty"` - Password string `yaml:"password,omitempty"` - Formats []string `yaml:"formats,omitempty"` + Username string `yaml:"username,omitempty"` + Password string `yaml:"password,omitempty"` + Formats []string `yaml:"formats,omitempty"` + Repository string `yaml:"repository,omitempty"` } func (p *PyPI) Write(f *buildfile.Buildfile) { + var indexServer string + var repository string + if len(p.Username) == 0 || len(p.Password) == 0 { // nothing to do if the config is fundamentally flawed return } + + // Handle the setting a custom pypi server/repository + if len(p.Repository) == 0 { + indexServer = "pypi" + repository = "" + } else { + indexServer = "custom" + repository = fmt.Sprintf("repository:%s", p.Repository) + } + f.WriteCmdSilent("echo 'publishing to PyPI...'") // find the setup.py file f.WriteCmdSilent("_PYPI_SETUP_PY=$(find . -name 'setup.py')") // build the .pypirc file that pypi expects - f.WriteCmdSilent(fmt.Sprintf(pypirc, p.Username, p.Password)) + f.WriteCmdSilent(fmt.Sprintf(pypirc, indexServer, indexServer, p.Username, p.Password, repository)) formatStr := p.BuildFormatStr() // if we found the setup.py file use it to deploy - f.WriteCmdSilent(fmt.Sprintf(deployCmd, formatStr)) + f.WriteCmdSilent(fmt.Sprintf(deployCmd, formatStr, indexServer)) } func (p *PyPI) BuildFormatStr() string { From 509d0ec23ba33c91cfb5714be65111fd5a9aeaef Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Mon, 28 Apr 2014 21:28:07 -0500 Subject: [PATCH 3/8] Add the ability to restrict publish plugins to a specific branch --- README.md | 5 +++++ pkg/build/build.go | 2 +- pkg/build/script/script.go | 5 +++-- pkg/plugin/publish/publish.go | 14 ++++++++++---- pkg/plugin/publish/pypi.go | 2 ++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2540c3130..ca66f554a 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,7 @@ publish: container: drone source: /tmp/drone.deb target: latest/drone.deb + branch: master ``` @@ -248,6 +249,10 @@ Drone currently has these `deploy` and `publish` plugins implemented (more to co - [OpenStack Swift](#docs) - [PyPI](#docs) +Publish plugins can be limited to a specific branch using the `branch` configuration +as seen above in the `swift` example. If you do not specify a `branch` all branches +will be published, with the exception of Pull Requests. + ### Notifications Drone can trigger email, hipchat and web hook notification at the beginning and diff --git a/pkg/build/build.go b/pkg/build/build.go index d87c82c99..3a4a6ff55 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -517,7 +517,7 @@ func (b *Builder) writeBuildScript(dir string) error { // we should only execute the build commands, // and omit the deploy and publish commands. if len(b.Repo.PR) == 0 { - b.Build.Write(f) + b.Build.Write(f, b.Repo) } else { // only write the build commands b.Build.WriteBuild(f) diff --git a/pkg/build/script/script.go b/pkg/build/script/script.go index d2ca5dfb3..394f0a9bc 100644 --- a/pkg/build/script/script.go +++ b/pkg/build/script/script.go @@ -10,6 +10,7 @@ import ( "github.com/drone/drone/pkg/build/buildfile" "github.com/drone/drone/pkg/build/git" + "github.com/drone/drone/pkg/build/repo" "github.com/drone/drone/pkg/plugin/deploy" "github.com/drone/drone/pkg/plugin/notify" "github.com/drone/drone/pkg/plugin/publish" @@ -81,13 +82,13 @@ type Build struct { // Write adds all the steps to the build script, including // build commands, deploy and publish commands. -func (b *Build) Write(f *buildfile.Buildfile) { +func (b *Build) Write(f *buildfile.Buildfile, r *repo.Repo) { // append build commands b.WriteBuild(f) // write publish commands if b.Publish != nil { - b.Publish.Write(f) + b.Publish.Write(f, r) } // write deployment commands diff --git a/pkg/plugin/publish/publish.go b/pkg/plugin/publish/publish.go index 2cfbf6deb..93dceb184 100644 --- a/pkg/plugin/publish/publish.go +++ b/pkg/plugin/publish/publish.go @@ -2,6 +2,7 @@ package publish import ( "github.com/drone/drone/pkg/build/buildfile" + "github.com/drone/drone/pkg/build/repo" ) // Publish stores the configuration details @@ -13,14 +14,19 @@ type Publish struct { PyPI *PyPI `yaml:"pypi,omitempty"` } -func (p *Publish) Write(f *buildfile.Buildfile) { - if p.S3 != nil { +func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) { + // S3 + if p.S3 != nil && (len(p.S3.Branch) == 0 || (len(p.S3.Branch) > 0 && r.Branch == p.S3.Branch)) { p.S3.Write(f) } - if p.Swift != nil { + + // Swift + if p.Swift != nil && (len(p.Swift.Branch) == 0 || (len(p.Swift.Branch) > 0 && r.Branch == p.Swift.Branch)) { p.Swift.Write(f) } - if p.PyPI != nil { + + // PyPI + if p.PyPI != nil && (len(p.PyPI.Branch) == 0 || (len(p.PyPI.Branch) > 0 && r.Branch == p.PyPI.Branch)) { p.PyPI.Write(f) } } diff --git a/pkg/plugin/publish/pypi.go b/pkg/plugin/publish/pypi.go index 4b3ee1472..998497838 100644 --- a/pkg/plugin/publish/pypi.go +++ b/pkg/plugin/publish/pypi.go @@ -2,6 +2,7 @@ package publish import ( "fmt" + "github.com/drone/drone/pkg/build/buildfile" ) @@ -36,6 +37,7 @@ type PyPI struct { Password string `yaml:"password,omitempty"` Formats []string `yaml:"formats,omitempty"` Repository string `yaml:"repository,omitempty"` + Branch string `yaml:"branch,omitempty"` } func (p *PyPI) Write(f *buildfile.Buildfile) { From d0628bbe7be8c25af7f06b65b357122dee071620 Mon Sep 17 00:00:00 2001 From: Ke Zhu Date: Sun, 4 May 2014 13:29:51 -0400 Subject: [PATCH 4/8] support publishing to npm --- Makefile | 1 + pkg/plugin/publish/npm.go | 72 ++++++++++++++++++++++++++ pkg/plugin/publish/npm_test.go | 95 ++++++++++++++++++++++++++++++++++ pkg/plugin/publish/publish.go | 6 +++ 4 files changed, 174 insertions(+) create mode 100644 pkg/plugin/publish/npm_test.go diff --git a/Makefile b/Makefile index a1e3476ca..93ed269bf 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ database/testing \ mail \ model \ plugin/deploy \ +plugin/publish \ queue PKGS := $(addprefix github.com/drone/drone/pkg/,$(PKGS)) .PHONY := test $(PKGS) diff --git a/pkg/plugin/publish/npm.go b/pkg/plugin/publish/npm.go index 30b1a5b2a..865e70d8a 100644 --- a/pkg/plugin/publish/npm.go +++ b/pkg/plugin/publish/npm.go @@ -1 +1,73 @@ package publish + +import ( + "fmt" + + "github.com/drone/drone/pkg/build/buildfile" +) + +var npmLoginCmd = ` +npm login < 0 && r.Branch == p.PyPI.Branch)) { p.PyPI.Write(f) } + + // NPM + if p.NPM != nil && (len(p.NPM.Branch) == 0 || (len(p.NPM.Branch) > 0 && r.Branch == p.NPM.Branch)) { + p.NPM.Write(f) + } } From d77b3209b024436cc26ce2d04dc579596e7da69a Mon Sep 17 00:00:00 2001 From: Ke Zhu Date: Sun, 4 May 2014 21:48:03 -0400 Subject: [PATCH 5/8] update npm login method --- pkg/plugin/publish/npm.go | 8 ++++---- pkg/plugin/publish/npm_test.go | 4 ---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/pkg/plugin/publish/npm.go b/pkg/plugin/publish/npm.go index 865e70d8a..42b26165a 100644 --- a/pkg/plugin/publish/npm.go +++ b/pkg/plugin/publish/npm.go @@ -6,11 +6,11 @@ import ( "github.com/drone/drone/pkg/build/buildfile" ) +// use npm trick instead of running npm adduser that requires stdin var npmLoginCmd = ` -npm login < ~/.npmrc +_auth = $(echo "%s:%s" | tr -d "\r\n" | base64) +email = %s EOF ` diff --git a/pkg/plugin/publish/npm_test.go b/pkg/plugin/publish/npm_test.go index d94d7bac6..96c52581d 100644 --- a/pkg/plugin/publish/npm_test.go +++ b/pkg/plugin/publish/npm_test.go @@ -59,10 +59,6 @@ func TestNPMPublish(t *testing.T) { t.Fatalf("Can't unmarshal publish script: %s", err) } - if !strings.Contains(bscr, "npm login") { - t.Error("Expect script to contain login command") - } - if !strings.Contains(bscr, "npm publish") { t.Error("Expect script to contain install command") } From 0ee9b163b9747a7d911d795f4653476425e293a1 Mon Sep 17 00:00:00 2001 From: Ke Zhu Date: Sun, 4 May 2014 22:05:24 -0400 Subject: [PATCH 6/8] correct npm publish logic --- pkg/plugin/publish/npm.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/plugin/publish/npm.go b/pkg/plugin/publish/npm.go index 42b26165a..d31879ed6 100644 --- a/pkg/plugin/publish/npm.go +++ b/pkg/plugin/publish/npm.go @@ -51,11 +51,6 @@ func (n *NPM) Write(f *buildfile.Buildfile) { npmPublishCmd := "npm publish %s" - // Setup custom npm registry - if n.Registry != "" { - f.WriteCmdSilent(fmt.Sprintf("npm config set registry %s", n.Registry)) - } - if n.Tag != "" { npmPublishCmd += fmt.Sprintf(" --tag %s", n.Tag) } @@ -69,5 +64,10 @@ func (n *NPM) Write(f *buildfile.Buildfile) { // Login to registry f.WriteCmdSilent(fmt.Sprintf(npmLoginCmd, n.Username, n.Password, n.Email)) + // Setup custom npm registry + if n.Registry != "" { + f.WriteCmdSilent(fmt.Sprintf("npm config set registry %s", n.Registry)) + } + f.WriteCmd(fmt.Sprintf(npmPublishCmd, n.Folder)) } \ No newline at end of file From 113f4917ff9174945388d86395f902cd154074cb Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Wed, 7 May 2014 00:59:21 +0700 Subject: [PATCH 7/8] Increase fixtures number assertion for user test --- pkg/database/testing/users_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/database/testing/users_test.go b/pkg/database/testing/users_test.go index 988e4aeb5..7d2385734 100644 --- a/pkg/database/testing/users_test.go +++ b/pkg/database/testing/users_test.go @@ -146,8 +146,8 @@ func TestListUsers(t *testing.T) { } // verify user count - if len(users) != 3 { - t.Errorf("Exepected %d users in database, got %d", 3, len(users)) + if len(users) != 4 { + t.Errorf("Exepected %d users in database, got %d", 4, len(users)) return } From 87c762f222279dbf0339318dfb42a158fa2bcaff Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Wed, 7 May 2014 03:25:42 +0700 Subject: [PATCH 8/8] Add -r flag to enable recursive scp --- pkg/plugin/deploy/ssh.go | 2 +- pkg/plugin/deploy/ssh_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/plugin/deploy/ssh.go b/pkg/plugin/deploy/ssh.go index 59ab7d6d6..216e1fab5 100644 --- a/pkg/plugin/deploy/ssh.go +++ b/pkg/plugin/deploy/ssh.go @@ -73,7 +73,7 @@ func (s *SSH) Write(f *buildfile.Buildfile) { } if artifact { - scpCmd := "scp -o StrictHostKeyChecking=no -P %s ${ARTIFACT} %s" + scpCmd := "scp -o StrictHostKeyChecking=no -P %s -r ${ARTIFACT} %s" f.WriteCmd(fmt.Sprintf(scpCmd, host[1], host[0])) } diff --git a/pkg/plugin/deploy/ssh_test.go b/pkg/plugin/deploy/ssh_test.go index 53e25a29b..c2b82d492 100644 --- a/pkg/plugin/deploy/ssh_test.go +++ b/pkg/plugin/deploy/ssh_test.go @@ -85,7 +85,7 @@ func TestSSHOneArtifact(t *testing.T) { t.Errorf("Expect script to contains artifact") } - if !strings.Contains(bscr, "scp -o StrictHostKeyChecking=no -P 2212 ${ARTIFACT} user@test.example.com:/srv/app/location") { + if !strings.Contains(bscr, "scp -o StrictHostKeyChecking=no -P 2212 -r ${ARTIFACT} user@test.example.com:/srv/app/location") { t.Errorf("Expect script to contains scp command, got:\n%s", bscr) } }