From 0ed7ae7e3ff337bfc7bcbe398bdfc0b473f3390a Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Wed, 4 Feb 2015 14:42:24 +0100 Subject: [PATCH 01/13] impelement a delete of a repository --- cli/delete.go | 30 ++++++++++++++++++++++ cli/main.go | 4 ++- client/repos.go | 6 +++++ plugin/remote/bitbucket/bitbucket.go | 6 +++++ plugin/remote/github/github.go | 17 +++++++++++++ plugin/remote/github/helper.go | 33 +++++++++++++++++++++++-- plugin/remote/gitlab/gitlab.go | 37 ++++++++++++++++++++++++++++ plugin/remote/gogs/gogs.go | 6 +++++ plugin/remote/remote.go | 4 +++ server/handler/repo.go | 31 +++++++++++++++++++++++ 10 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 cli/delete.go diff --git a/cli/delete.go b/cli/delete.go new file mode 100644 index 00000000..df3be638 --- /dev/null +++ b/cli/delete.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/codegangsta/cli" + "github.com/drone/drone/client" +) + +// NewDeleteCommand returns the CLI command for "delete". +func NewDeleteCommand() cli.Command { + return cli.Command{ + Name: "delete", + Usage: "delete a repository", + Flags: []cli.Flag{}, + Action: func(c *cli.Context) { + handle(c, deleteCommandFunc) + }, + } +} + +// deleteCommandFunc executes the "delete" command. +func deleteCommandFunc(c *cli.Context, client *client.Client) error { + var host, owner, name string + var args = c.Args() + + if len(args) != 0 { + host, owner, name = parseRepo(args[0]) + } + + return client.Repos.Delete(host, owner, name) +} diff --git a/cli/main.go b/cli/main.go index 9b440794..78935e82 100644 --- a/cli/main.go +++ b/cli/main.go @@ -1,8 +1,9 @@ package main import ( - "github.com/codegangsta/cli" "os" + + "github.com/codegangsta/cli" ) var ( @@ -40,6 +41,7 @@ func main() { NewRestartCommand(), NewWhoamiCommand(), NewSetKeyCommand(), + NewDeleteCommand(), } app.Run(os.Args) diff --git a/client/repos.go b/client/repos.go index 2cd15a10..0b77c15e 100644 --- a/client/repos.go +++ b/client/repos.go @@ -38,6 +38,12 @@ func (s *RepoService) Disable(host, owner, name string) error { return s.run("DELETE", path, nil, nil) } +// DELETE /api/repos/{host}/{owner}/{name}?remove=true +func (s *RepoService) Delete(host, owner, name string) error { + var path = fmt.Sprintf("/api/repos/%s/%s/%s?remove=true", host, owner, name) + return s.run("DELETE", path, nil, nil) +} + // PUT /api/repos/{host}/{owner}/{name} func (s *RepoService) SetKey(host, owner, name, pub, priv string) error { var path = fmt.Sprintf("/api/repos/%s/%s/%s", host, owner, name) diff --git a/plugin/remote/bitbucket/bitbucket.go b/plugin/remote/bitbucket/bitbucket.go index 8220c9e5..2e0b4c8e 100644 --- a/plugin/remote/bitbucket/bitbucket.go +++ b/plugin/remote/bitbucket/bitbucket.go @@ -241,6 +241,12 @@ func (r *Bitbucket) Activate(user *model.User, repo *model.Repo, link string) er return err } +// Deactivate removes a repository by removing all the post-commit hooks +// which are equal to link and removing the SSH deploy key. +func (r *Bitbucket) Deactivate(user *model.User, repo *model.Repo, link string) error { + return fmt.Errorf("Remove %#v in bitbucket not implemented", *repo) +} + // ParseHook parses the post-commit hook from the Request body // and returns the required data in a standard format. func (r *Bitbucket) ParseHook(req *http.Request) (*model.Hook, error) { diff --git a/plugin/remote/github/github.go b/plugin/remote/github/github.go index 6c5bac7a..ec923203 100644 --- a/plugin/remote/github/github.go +++ b/plugin/remote/github/github.go @@ -193,6 +193,23 @@ func (r *GitHub) GetScript(user *model.User, repo *model.Repo, hook *model.Hook) return GetFile(client, repo.Owner, repo.Name, ".drone.yml", hook.Sha) } +// Deactivate removes a repository by removing all the post-commit hooks +// which are equal to link and removing the SSH deploy key. +func (r *GitHub) Deactivate(user *model.User, repo *model.Repo, link string) error { + var client = NewClient(r.API, user.Access, r.SkipVerify) + var title, err = GetKeyTitle(link) + if err != nil { + return err + } + + // remove the deploy-key if it is installed remote. + if err := DeleteKey(client, repo.Owner, repo.Name, title, repo.PublicKey); err != nil { + return err + } + + return DeleteHook(client, repo.Owner, repo.Name, link) +} + // Activate activates a repository by adding a Post-commit hook and // a Public Deploy key, if applicable. func (r *GitHub) Activate(user *model.User, repo *model.Repo, link string) error { diff --git a/plugin/remote/github/helper.go b/plugin/remote/github/helper.go index 4d23180e..257bdfb8 100644 --- a/plugin/remote/github/helper.go +++ b/plugin/remote/github/helper.go @@ -173,6 +173,16 @@ func GetHook(client *github.Client, owner, name, url string) (*github.Hook, erro return nil, nil } +func DeleteHook(client *github.Client, owner, name, url string) error { + hook, err := GetHook(client, owner, name, url) + if err != nil { + return err + } + + _, err = client.Repositories.DeleteHook(owner, name, *hook.ID) + return err +} + // CreateHook is a heper function that creates a post-commit hook // for the specified repository. func CreateHook(client *github.Client, owner, name, url string) (*github.Hook, error) { @@ -230,7 +240,26 @@ func GetKeyTitle(rawurl string) (string, error) { return fmt.Sprintf("drone@%s", uri.Host), nil } -// CreateKey is a heper function that creates a deploy key +// DeleteKey is a helper function that deletes a deploy key +// for the specified repository. +func DeleteKey(client *github.Client, owner, name, title, key string) error { + var k = new(github.Key) + k.Title = github.String(title) + k.Key = github.String(key) + keys, _, err := client.Repositories.ListKeys(owner, name, nil) + if err != nil { + return err + } + for _, rk := range keys { + if rk.Key != nil && rk.Key == k.Key { + _, err = client.Repositories.DeleteKey(owner, name, *rk.ID) + return err + } + } + return fmt.Errorf("%s not found in the list of keys", title) +} + +// CreateKey is a helper function that creates a deploy key // for the specified repository. func CreateKey(client *github.Client, owner, name, title, key string) (*github.Key, error) { var k = new(github.Key) @@ -240,7 +269,7 @@ func CreateKey(client *github.Client, owner, name, title, key string) (*github.K return created, err } -// CreateUpdateKey is a heper function that creates a deployment key +// CreateUpdateKey is a helper function that creates a deployment key // for the specified repository if it does not already exist, otherwise // it updates the existing key func CreateUpdateKey(client *github.Client, owner, name, title, key string) (*github.Key, error) { diff --git a/plugin/remote/gitlab/gitlab.go b/plugin/remote/gitlab/gitlab.go index 23a15d43..9bbd3ce9 100644 --- a/plugin/remote/gitlab/gitlab.go +++ b/plugin/remote/gitlab/gitlab.go @@ -6,6 +6,7 @@ import ( "net/http" "net/url" "strconv" + "strings" "time" "code.google.com/p/goauth2/oauth" @@ -179,6 +180,42 @@ func (r *Gitlab) Activate(user *model.User, repo *model.Repo, link string) error return client.AddProjectHook(path, link, true, false, true) } +// Deactivate removes a repository by removing all the post-commit hooks +// which are equal to link and removing the SSH deploy key. +func (r *Gitlab) Deactivate(user *model.User, repo *model.Repo, link string) error { + var client = NewClient(r.url, user.Access, r.SkipVerify) + var path = ns(repo.Owner, repo.Name) + + keys, err := client.ProjectDeployKeys(path) + if err != nil { + return err + } + var pubkey = strings.TrimSpace(repo.PublicKey) + for _, k := range keys { + if pubkey == strings.TrimSpace(k.Key) { + fmt.Printf("remove deploy key: %+v\n", k) + if err := client.RemoveProjectDeployKey(path, strconv.Itoa(k.Id)); err != nil { + return err + } + break + } + } + hooks, err := client.ProjectHooks(path) + if err != nil { + return err + } + link += "?owner=" + repo.Owner + "&name=" + repo.Name + for _, h := range hooks { + if link == h.Url { + if err := client.RemoveProjectHook(path, strconv.Itoa(h.Id)); err != nil { + return err + } + break + } + } + return nil +} + // ParseHook parses the post-commit hook from the Request body // and returns the required data in a standard format. func (r *Gitlab) ParseHook(req *http.Request) (*model.Hook, error) { diff --git a/plugin/remote/gogs/gogs.go b/plugin/remote/gogs/gogs.go index edc71893..af81015f 100644 --- a/plugin/remote/gogs/gogs.go +++ b/plugin/remote/gogs/gogs.go @@ -153,6 +153,12 @@ func (r *Gogs) Activate(user *model.User, repo *model.Repo, link string) error { return err } +// Deactivate removes a repository by removing all the post-commit hooks +// which are equal to link and removing the SSH deploy key. +func (r *Gogs) Deactivate(user *model.User, repo *model.Repo, link string) error { + return fmt.Errorf("Remove %#v in gots not implemented", *repo) +} + // ParseHook parses the post-commit hook from the Request body // and returns the required data in a standard format. func (r *Gogs) ParseHook(req *http.Request) (*model.Hook, error) { diff --git a/plugin/remote/remote.go b/plugin/remote/remote.go index 0d7ad2dc..862e8c15 100644 --- a/plugin/remote/remote.go +++ b/plugin/remote/remote.go @@ -29,6 +29,10 @@ type Remote interface { // adding the SSH deploy key, if applicable. Activate(user *model.User, repo *model.Repo, link string) error + // Deactivate removes a repository by removing all the post-commit hooks + // which are equal to link and removing the SSH deploy key. + Deactivate(user *model.User, repo *model.Repo, link string) error + // ParseHook parses the post-commit hook from the Request body // and returns the required data in a standard format. ParseHook(r *http.Request) (*model.Hook, error) diff --git a/server/handler/repo.go b/server/handler/repo.go index 5b2048a5..2209cc50 100644 --- a/server/handler/repo.go +++ b/server/handler/repo.go @@ -52,6 +52,37 @@ func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) { var ctx = context.FromC(c) var repo = ToRepo(c) + var rm = r.FormValue("remove") // using ?remove=true + + // completely remove the repository from the database + if len(rm) != 0 { + var user = ToUser(c) + var remote = remote.Lookup(repo.Host) + if remote == nil { + w.WriteHeader(http.StatusNotFound) + return + } + + // Request a new token and update + user_token, err := remote.GetToken(user) + if user_token != nil { + user.Access = user_token.AccessToken + user.Secret = user_token.RefreshToken + datastore.PutUser(ctx, user) + } else if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + // setup the post-commit hook with the remote system and + // if necessary, register the public key + var hook = fmt.Sprintf("%s/api/hook/%s/%s", httputil.GetURL(r), repo.Remote, repo.Token) + if err := remote.Deactivate(user, repo, hook); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } + // disable everything repo.Active = false repo.PullRequest = false From 347aa247854ea77bb75d93dbcd289ac395a46748 Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Wed, 4 Feb 2015 15:13:23 +0100 Subject: [PATCH 02/13] remove Printf output and do a real removal of the repository in the datastore --- plugin/remote/gitlab/gitlab.go | 1 - server/handler/repo.go | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/plugin/remote/gitlab/gitlab.go b/plugin/remote/gitlab/gitlab.go index 9bbd3ce9..155d0d7f 100644 --- a/plugin/remote/gitlab/gitlab.go +++ b/plugin/remote/gitlab/gitlab.go @@ -193,7 +193,6 @@ func (r *Gitlab) Deactivate(user *model.User, repo *model.Repo, link string) err var pubkey = strings.TrimSpace(repo.PublicKey) for _, k := range keys { if pubkey == strings.TrimSpace(k.Key) { - fmt.Printf("remove deploy key: %+v\n", k) if err := client.RemoveProjectDeployKey(path, strconv.Itoa(k.Id)); err != nil { return err } diff --git a/server/handler/repo.go b/server/handler/repo.go index 2209cc50..97bd842e 100644 --- a/server/handler/repo.go +++ b/server/handler/repo.go @@ -81,6 +81,11 @@ func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } + + if err := datastore.DelRepo(ctx, repo); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } } // disable everything From bd8fb51c2a9936e011dd387ae7b415c8538558a8 Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Thu, 5 Feb 2015 13:13:17 +0100 Subject: [PATCH 03/13] rework to delete the repository from the datastore if there are previous errors from the remote --- plugin/remote/github/helper.go | 2 +- plugin/remote/gogs/gogs.go | 2 +- server/handler/repo.go | 48 ++++++++++++++++++---------------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/plugin/remote/github/helper.go b/plugin/remote/github/helper.go index 257bdfb8..0fdbadc9 100644 --- a/plugin/remote/github/helper.go +++ b/plugin/remote/github/helper.go @@ -256,7 +256,7 @@ func DeleteKey(client *github.Client, owner, name, title, key string) error { return err } } - return fmt.Errorf("%s not found in the list of keys", title) + return nil } // CreateKey is a helper function that creates a deploy key diff --git a/plugin/remote/gogs/gogs.go b/plugin/remote/gogs/gogs.go index af81015f..73038a4d 100644 --- a/plugin/remote/gogs/gogs.go +++ b/plugin/remote/gogs/gogs.go @@ -156,7 +156,7 @@ func (r *Gogs) Activate(user *model.User, repo *model.Repo, link string) error { // Deactivate removes a repository by removing all the post-commit hooks // which are equal to link and removing the SSH deploy key. func (r *Gogs) Deactivate(user *model.User, repo *model.Repo, link string) error { - return fmt.Errorf("Remove %#v in gots not implemented", *repo) + return fmt.Errorf("Remove %#v in gogs not implemented", *repo) } // ParseHook parses the post-commit hook from the Request body diff --git a/server/handler/repo.go b/server/handler/repo.go index 97bd842e..3fdf0d8c 100644 --- a/server/handler/repo.go +++ b/server/handler/repo.go @@ -7,6 +7,7 @@ import ( "github.com/drone/drone/plugin/remote" "github.com/drone/drone/server/datastore" + "github.com/drone/drone/shared/build/log" "github.com/drone/drone/shared/httputil" "github.com/drone/drone/shared/model" "github.com/drone/drone/shared/sshutil" @@ -59,33 +60,34 @@ func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) { var user = ToUser(c) var remote = remote.Lookup(repo.Host) if remote == nil { - w.WriteHeader(http.StatusNotFound) - return + log.Errf("no remote for host '%s' found", repo.Host) + } else { + // Request a new token and update + user_token, err := remote.GetToken(user) + if err != nil { + log.Errf("no token for user '%s' on remote '%s' ", repo.Host) + } else { + if user_token != nil { + user.Access = user_token.AccessToken + user.Secret = user_token.RefreshToken + datastore.PutUser(ctx, user) + } + // setup the post-commit hook with the remote system and + // and deactiveate this hook/user on the remote system + var hook = fmt.Sprintf("%s/api/hook/%s/%s", httputil.GetURL(r), repo.Remote, repo.Token) + if err := remote.Deactivate(user, repo, hook); err != nil { + log.Errf("deactivate on remote '%s' failed: %s", repo.Host, err) + } + } } - - // Request a new token and update - user_token, err := remote.GetToken(user) - if user_token != nil { - user.Access = user_token.AccessToken - user.Secret = user_token.RefreshToken - datastore.PutUser(ctx, user) - } else if err != nil { - w.WriteHeader(http.StatusBadRequest) - return - } - - // setup the post-commit hook with the remote system and - // if necessary, register the public key - var hook = fmt.Sprintf("%s/api/hook/%s/%s", httputil.GetURL(r), repo.Remote, repo.Token) - if err := remote.Deactivate(user, repo, hook); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - + // fail through: if any of the actions on the remote failed + // we try to delete the repo in our datastore anyway if err := datastore.DelRepo(ctx, repo); err != nil { w.WriteHeader(http.StatusInternalServerError) - return + } else { + w.WriteHeader(http.StatusNoContent) } + return } // disable everything From ae236a3d4d28b8d7b54d14aa66b59f5aa054db47 Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Thu, 5 Feb 2015 15:27:26 +0100 Subject: [PATCH 04/13] reworked to have two distinct REST handlers --- client/repos.go | 4 +-- server/handler/repo.go | 74 ++++++++++++++++++++++------------------- server/router/router.go | 1 + shared/model/user.go | 2 +- 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/client/repos.go b/client/repos.go index 0b77c15e..5afa1452 100644 --- a/client/repos.go +++ b/client/repos.go @@ -35,12 +35,12 @@ func (s *RepoService) Enable(host, owner, name string) error { // DELETE /api/repos/{host}/{owner}/{name} func (s *RepoService) Disable(host, owner, name string) error { var path = fmt.Sprintf("/api/repos/%s/%s/%s", host, owner, name) - return s.run("DELETE", path, nil, nil) + return s.run("PATCH", path, nil, nil) } // DELETE /api/repos/{host}/{owner}/{name}?remove=true func (s *RepoService) Delete(host, owner, name string) error { - var path = fmt.Sprintf("/api/repos/%s/%s/%s?remove=true", host, owner, name) + var path = fmt.Sprintf("/api/repos/%s/%s/%s", host, owner, name) return s.run("DELETE", path, nil, nil) } diff --git a/server/handler/repo.go b/server/handler/repo.go index 13738411..a299bc2a 100644 --- a/server/handler/repo.go +++ b/server/handler/repo.go @@ -43,9 +43,8 @@ func GetRepo(c web.C, w http.ResponseWriter, r *http.Request) { }{repo, repo.PublicKey, repo.Params, role}) } -// DelRepo accepts a request to inactivate the named -// repository. This will disable all builds in the system -// for this repository. +// DelRepo accepts a request to delete the named +// repository. // // DEL /api/repos/:host/:owner/:name // @@ -53,42 +52,49 @@ func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) { var ctx = context.FromC(c) var repo = ToRepo(c) - var rm = r.FormValue("remove") // using ?remove=true - // completely remove the repository from the database - if len(rm) != 0 { - var user = ToUser(c) - var remote = remote.Lookup(repo.Host) - if remote == nil { - log.Errf("no remote for host '%s' found", repo.Host) + var user = ToUser(c) + var remote = remote.Lookup(repo.Host) + if remote == nil { + log.Errf("no remote for host '%s' found", repo.Host) + } else { + // Request a new token and update + user_token, err := remote.GetToken(user) + if err != nil { + log.Errf("no token for user '%s' on remote '%s' ", repo.Host) } else { - // Request a new token and update - user_token, err := remote.GetToken(user) - if err != nil { - log.Errf("no token for user '%s' on remote '%s' ", repo.Host) - } else { - if user_token != nil { - user.Access = user_token.AccessToken - user.Secret = user_token.RefreshToken - datastore.PutUser(ctx, user) - } - // setup the post-commit hook with the remote system and - // and deactiveate this hook/user on the remote system - var hook = fmt.Sprintf("%s/api/hook/%s/%s", httputil.GetURL(r), repo.Remote, repo.Token) - if err := remote.Deactivate(user, repo, hook); err != nil { - log.Errf("deactivate on remote '%s' failed: %s", repo.Host, err) - } + if user_token != nil { + user.Access = user_token.AccessToken + user.Secret = user_token.RefreshToken + user.TokenExpiry = user_token.Expiry + datastore.PutUser(ctx, user) + } + // setup the post-commit hook with the remote system and + // and deactiveate this hook/user on the remote system + var hook = fmt.Sprintf("%s/api/hook/%s/%s", httputil.GetURL(r), repo.Remote, repo.Token) + if err := remote.Deactivate(user, repo, hook); err != nil { + log.Errf("deactivate on remote '%s' failed: %s", repo.Host, err) } } - // fail through: if any of the actions on the remote failed - // we try to delete the repo in our datastore anyway - if err := datastore.DelRepo(ctx, repo); err != nil { - w.WriteHeader(http.StatusInternalServerError) - } else { - w.WriteHeader(http.StatusNoContent) - } - return } + // fail through: if any of the actions on the remote failed + // we try to delete the repo in our datastore anyway + if err := datastore.DelRepo(ctx, repo); err != nil { + w.WriteHeader(http.StatusInternalServerError) + } else { + w.WriteHeader(http.StatusNoContent) + } +} + +// PatchRepo accepts a request to inactivate the named +// repository. This will disable all builds in the system +// for this repository. +// +// PATCH /api/repos/:host/:owner/:name +// +func PatchRepo(c web.C, w http.ResponseWriter, r *http.Request) { + var ctx = context.FromC(c) + var repo = ToRepo(c) // disable everything repo.Active = false diff --git a/server/router/router.go b/server/router/router.go index 0980a848..51bc2c6d 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -46,6 +46,7 @@ func New() *web.Mux { repos.Put("/api/repos/:host/:owner/:name", handler.PutRepo) repos.Post("/api/repos/:host/:owner/:name", handler.PostRepo) repos.Delete("/api/repos/:host/:owner/:name", handler.DelRepo) + repos.Patch("/api/repos/:host/:owner/:name", handler.PatchRepo) mux.Handle("/api/repos/:host/:owner/:name", repos) mux.Handle("/api/repos/:host/:owner/:name/*", repos) diff --git a/shared/model/user.go b/shared/model/user.go index 2b7b5ad1..7f7f9a65 100644 --- a/shared/model/user.go +++ b/shared/model/user.go @@ -20,7 +20,7 @@ type User struct { Created int64 `meddler:"user_created" json:"created_at"` Updated int64 `meddler:"user_updated" json:"updated_at"` Synced int64 `meddler:"user_synced" json:"synced_at"` - TokenExpiry int64 `meddler:"user_access_expires" json:"-"` + TokenExpiry int64 `meddler:"user_access_expires,zeroisnull" json:"-"` } func NewUser(remote, login, email string) *User { From f57640a402ebf9d7fd1e245b504d2e0b518cb090 Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Fri, 6 Feb 2015 11:36:31 +0100 Subject: [PATCH 05/13] remove hook/key from a bitbucket repo --- plugin/remote/bitbucket/bitbucket.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/plugin/remote/bitbucket/bitbucket.go b/plugin/remote/bitbucket/bitbucket.go index 2e0b4c8e..c4bd1fcc 100644 --- a/plugin/remote/bitbucket/bitbucket.go +++ b/plugin/remote/bitbucket/bitbucket.go @@ -5,6 +5,7 @@ import ( "net/http" "net/url" "regexp" + "strings" "time" "github.com/drone/drone/shared/httputil" @@ -244,7 +245,26 @@ func (r *Bitbucket) Activate(user *model.User, repo *model.Repo, link string) er // Deactivate removes a repository by removing all the post-commit hooks // which are equal to link and removing the SSH deploy key. func (r *Bitbucket) Deactivate(user *model.User, repo *model.Repo, link string) error { - return fmt.Errorf("Remove %#v in bitbucket not implemented", *repo) + var client = bitbucket.New( + r.Client, + r.Secret, + user.Access, + user.Secret, + ) + + if keys, err := client.RepoKeys.List(repo.Owner, repo.Name); err == nil { + repokey := strings.TrimSpace(repo.PublicKey) + for _, k := range keys { + if k.Key == repokey { + if err := client.RepoKeys.Delete(repo.Owner, repo.Name, k.Id); err != nil { + return err + } else { + break + } + } + } + } + return client.Brokers.DeleteUrl(repo.Owner, repo.Name, link, bitbucket.BrokerTypePost) } // ParseHook parses the post-commit hook from the Request body From 7b02878df9c295005532365e3965d006003e775d Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Fri, 6 Feb 2015 12:02:02 +0100 Subject: [PATCH 06/13] reuse more existing code --- plugin/remote/bitbucket/bitbucket.go | 29 +++++++++++++++------------- plugin/remote/github/helper.go | 14 +++----------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/plugin/remote/bitbucket/bitbucket.go b/plugin/remote/bitbucket/bitbucket.go index c4bd1fcc..e29f0d41 100644 --- a/plugin/remote/bitbucket/bitbucket.go +++ b/plugin/remote/bitbucket/bitbucket.go @@ -5,7 +5,6 @@ import ( "net/http" "net/url" "regexp" - "strings" "time" "github.com/drone/drone/shared/httputil" @@ -251,18 +250,12 @@ func (r *Bitbucket) Deactivate(user *model.User, repo *model.Repo, link string) user.Access, user.Secret, ) - - if keys, err := client.RepoKeys.List(repo.Owner, repo.Name); err == nil { - repokey := strings.TrimSpace(repo.PublicKey) - for _, k := range keys { - if k.Key == repokey { - if err := client.RepoKeys.Delete(repo.Owner, repo.Name, k.Id); err != nil { - return err - } else { - break - } - } - } + title, err := GetKeyTitle(link) + if err != nil { + return err + } + if err := client.RepoKeys.DeleteName(repo.Owner, repo.Name, title); err != nil { + return err } return client.Brokers.DeleteUrl(repo.Owner, repo.Name, link, bitbucket.BrokerTypePost) } @@ -305,3 +298,13 @@ func (r *Bitbucket) OpenRegistration() bool { func (r *Bitbucket) GetToken(user *model.User) (*model.Token, error) { return nil, nil } + +// GetKeyTitle is a helper function that generates a title for the +// RSA public key based on the username and domain name. +func GetKeyTitle(rawurl string) (string, error) { + var uri, err = url.Parse(rawurl) + if err != nil { + return "", err + } + return fmt.Sprintf("drone@%s", uri.Host), nil +} diff --git a/plugin/remote/github/helper.go b/plugin/remote/github/helper.go index 0fdbadc9..5d8051b7 100644 --- a/plugin/remote/github/helper.go +++ b/plugin/remote/github/helper.go @@ -243,19 +243,11 @@ func GetKeyTitle(rawurl string) (string, error) { // DeleteKey is a helper function that deletes a deploy key // for the specified repository. func DeleteKey(client *github.Client, owner, name, title, key string) error { - var k = new(github.Key) - k.Title = github.String(title) - k.Key = github.String(key) - keys, _, err := client.Repositories.ListKeys(owner, name, nil) - if err != nil { + var k, _ = GetKey(client, owner, name, title) + if k != nil { + _, err := client.Repositories.DeleteKey(owner, name, *k.ID) return err } - for _, rk := range keys { - if rk.Key != nil && rk.Key == k.Key { - _, err = client.Repositories.DeleteKey(owner, name, *rk.ID) - return err - } - } return nil } From d3b337ff30edaa5052b2bbb8199b74679fce39bc Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Fri, 6 Feb 2015 12:05:39 +0100 Subject: [PATCH 07/13] bug in error handling --- plugin/remote/github/helper.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/remote/github/helper.go b/plugin/remote/github/helper.go index 5d8051b7..2f05ea0c 100644 --- a/plugin/remote/github/helper.go +++ b/plugin/remote/github/helper.go @@ -243,12 +243,12 @@ func GetKeyTitle(rawurl string) (string, error) { // DeleteKey is a helper function that deletes a deploy key // for the specified repository. func DeleteKey(client *github.Client, owner, name, title, key string) error { - var k, _ = GetKey(client, owner, name, title) - if k != nil { - _, err := client.Repositories.DeleteKey(owner, name, *k.ID) + var k, err = GetKey(client, owner, name, title) + if err != nil { return err } - return nil + _, err = client.Repositories.DeleteKey(owner, name, *k.ID) + return err } // CreateKey is a helper function that creates a deploy key From aeb68951158871b8ef41d3cc56d4d74d6eea89ed Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Wed, 11 Feb 2015 07:56:22 +0100 Subject: [PATCH 08/13] change the deactivate endpoint to HTTP-POST --- server/handler/repo.go | 8 ++++---- server/router/router.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/handler/repo.go b/server/handler/repo.go index a299bc2a..2bf54bcd 100644 --- a/server/handler/repo.go +++ b/server/handler/repo.go @@ -86,13 +86,13 @@ func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) { } } -// PatchRepo accepts a request to inactivate the named +// DeactivateRepo accepts a request to deactivate the named // repository. This will disable all builds in the system // for this repository. // -// PATCH /api/repos/:host/:owner/:name +// POST /api/repos/:host/:owner/:name/deactivate // -func PatchRepo(c web.C, w http.ResponseWriter, r *http.Request) { +func DeactivateRepo(c web.C, w http.ResponseWriter, r *http.Request) { var ctx = context.FromC(c) var repo = ToRepo(c) @@ -106,7 +106,7 @@ func PatchRepo(c web.C, w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) return } - w.WriteHeader(http.StatusNoContent) + json.NewEncoder(w).Encode(repo) } // PostRepo accapets a request to activate the named repository diff --git a/server/router/router.go b/server/router/router.go index 51bc2c6d..b197d067 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -46,7 +46,7 @@ func New() *web.Mux { repos.Put("/api/repos/:host/:owner/:name", handler.PutRepo) repos.Post("/api/repos/:host/:owner/:name", handler.PostRepo) repos.Delete("/api/repos/:host/:owner/:name", handler.DelRepo) - repos.Patch("/api/repos/:host/:owner/:name", handler.PatchRepo) + repos.Post("/api/repos/:host/:owner/:name/deactivate", handler.DeactivateRepo) mux.Handle("/api/repos/:host/:owner/:name", repos) mux.Handle("/api/repos/:host/:owner/:name/*", repos) From 46251ffa9249ca9efbd6ba382700405e01804506 Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Thu, 12 Feb 2015 08:41:04 +0100 Subject: [PATCH 09/13] remove builtin log package and use standard --- server/handler/repo.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/handler/repo.go b/server/handler/repo.go index 2bf54bcd..98c79f4d 100644 --- a/server/handler/repo.go +++ b/server/handler/repo.go @@ -3,11 +3,11 @@ package handler import ( "encoding/json" "fmt" + "log" "net/http" "github.com/drone/drone/plugin/remote" "github.com/drone/drone/server/datastore" - "github.com/drone/drone/shared/build/log" "github.com/drone/drone/shared/httputil" "github.com/drone/drone/shared/model" "github.com/drone/drone/shared/sshutil" @@ -56,12 +56,12 @@ func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) { var user = ToUser(c) var remote = remote.Lookup(repo.Host) if remote == nil { - log.Errf("no remote for host '%s' found", repo.Host) + log.Printf("[ERROR] no remote for host '%s' found", repo.Host) } else { // Request a new token and update user_token, err := remote.GetToken(user) if err != nil { - log.Errf("no token for user '%s' on remote '%s' ", repo.Host) + log.Printf("[ERROR] no token for user '%s' on remote '%s' ", user.Email, repo.Host) } else { if user_token != nil { user.Access = user_token.AccessToken @@ -73,7 +73,7 @@ func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) { // and deactiveate this hook/user on the remote system var hook = fmt.Sprintf("%s/api/hook/%s/%s", httputil.GetURL(r), repo.Remote, repo.Token) if err := remote.Deactivate(user, repo, hook); err != nil { - log.Errf("deactivate on remote '%s' failed: %s", repo.Host, err) + log.Printf("[ERROR] deactivate on remote '%s' failed: %s", repo.Host, err) } } } From f64bb1df9b336e5d45652c1a2fa8b09d45fe76df Mon Sep 17 00:00:00 2001 From: Andy Gardner Date: Thu, 12 Feb 2015 12:18:12 +0200 Subject: [PATCH 10/13] Implementing angular-moment to automatically update dates / durations --- server/app/index.html | 1 + server/app/scripts/app.js | 7 ++++++- server/app/scripts/filters/filters.js | 2 +- server/app/views/commit.html | 8 ++++---- server/app/views/repo.html | 22 +++++++++++----------- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/server/app/index.html b/server/app/index.html index 755b059d..31b95a09 100644 --- a/server/app/index.html +++ b/server/app/index.html @@ -29,6 +29,7 @@ + diff --git a/server/app/scripts/app.js b/server/app/scripts/app.js index 4f1a670b..097e74ac 100644 --- a/server/app/scripts/app.js +++ b/server/app/scripts/app.js @@ -2,9 +2,14 @@ var app = angular.module('app', [ 'ngRoute', - 'ui.filters' + 'ui.filters', + 'angularMoment' ]); +angular.module('app').constant('angularMomentConfig', { + preprocess: 'unix' +}); + // First, parse the query string var params = {}, queryString = location.hash.substring(1), regex = /([^&=]+)=([^&]*)/g, m; diff --git a/server/app/scripts/filters/filters.js b/server/app/scripts/filters/filters.js index 32c1c088..2100369b 100644 --- a/server/app/scripts/filters/filters.js +++ b/server/app/scripts/filters/filters.js @@ -25,7 +25,7 @@ /** * toDate is a helper function that returns a human readable - * string gor the given unix date. + * string for the given unix date. */ function toDate() { return function(date) { diff --git a/server/app/views/commit.html b/server/app/views/commit.html index 2cfdfd80..787b1241 100644 --- a/server/app/views/commit.html +++ b/server/app/views/commit.html @@ -8,14 +8,14 @@
-

{{ commit.duration | toDuration}}

+

{{ commit.duration | amDurationFormat:'seconds':false }}

-
{{ commit.finished_at | fromNow }}
-
Started {{ commit.started_at | fromNow }}
-
Created {{ commit.created_at}}
+
+
Started
+
Created
diff --git a/server/app/views/repo.html b/server/app/views/repo.html index bd0328a0..474ca39b 100644 --- a/server/app/views/repo.html +++ b/server/app/views/repo.html @@ -70,11 +70,11 @@ {{ commit.sha | shortHash }} ({{ commit.branch }}) {{ commit.author }} - {{ commit.duration | toDuration }} - {{ commit.started_at | fromNow }} - - + {{ commit.duration | amDurationFormat:'seconds':false }} + + - {{ commit.finished_at | fromNow }} + - @@ -88,24 +88,24 @@

{{ commit.message }}

- {{ commit.author }}
{{ commit.finished_at | fromNow }}
- {{ commit.author }}
Started {{ commit.started_at | fromNow }}
- {{ commit.author }}
Created {{ commit.created_at}}
+ {{ commit.author }}
+ {{ commit.author }}
Started
+ {{ commit.author }}
Created
-
+

Pull Requests

{{ commit.message }}

- {{ commit.author }}
{{ commit.finished_at | fromNow }}
- {{ commit.author }}
Started {{ commit.started_at | fromNow }}
- {{ commit.author }}
Created {{ commit.created_at}}
+ {{ commit.author }}
+ {{ commit.author }}
Started
+ {{ commit.author }}
Created
From 77bab3601363880ec8a9ceadd378dac3e3bf3d83 Mon Sep 17 00:00:00 2001 From: Ulrich Schreiner Date: Thu, 12 Feb 2015 11:33:30 +0100 Subject: [PATCH 11/13] bug in CLI; wrong endpoint call --- client/repos.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/repos.go b/client/repos.go index 5afa1452..29c0d38f 100644 --- a/client/repos.go +++ b/client/repos.go @@ -32,10 +32,10 @@ func (s *RepoService) Enable(host, owner, name string) error { return s.run("POST", path, nil, nil) } -// DELETE /api/repos/{host}/{owner}/{name} +// POST /api/repos/{host}/{owner}/{name}/deactivate func (s *RepoService) Disable(host, owner, name string) error { - var path = fmt.Sprintf("/api/repos/%s/%s/%s", host, owner, name) - return s.run("PATCH", path, nil, nil) + var path = fmt.Sprintf("/api/repos/%s/%s/%s/deactivate", host, owner, name) + return s.run("POST", path, nil, nil) } // DELETE /api/repos/{host}/{owner}/{name}?remove=true From a5dd61f4806b83003c4b9b06793107b111d4861d Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Thu, 12 Feb 2015 15:19:31 -0800 Subject: [PATCH 12/13] display list of required orgs in github login error --- plugin/remote/github/github.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/remote/github/github.go b/plugin/remote/github/github.go index ec923203..88ceb709 100644 --- a/plugin/remote/github/github.go +++ b/plugin/remote/github/github.go @@ -102,7 +102,7 @@ func (r *GitHub) Authorize(res http.ResponseWriter, req *http.Request) (*model.L return nil, fmt.Errorf("Could not check org membership. %s", err) } if !allowedOrg { - return nil, fmt.Errorf("User does not belong to correct org") + return nil, fmt.Errorf("User does not belong to correct org. Must belong to %v", r.Orgs) } } From 8d1015a106a9bfae83360dbbec427474568d61fa Mon Sep 17 00:00:00 2001 From: masarakki Date: Fri, 13 Feb 2015 14:08:30 +0900 Subject: [PATCH 13/13] Change repo to be private when GHE is private mode. --- plugin/remote/github/github.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/remote/github/github.go b/plugin/remote/github/github.go index 6c5bac7a..cb442fcb 100644 --- a/plugin/remote/github/github.go +++ b/plugin/remote/github/github.go @@ -169,6 +169,7 @@ func (r *GitHub) GetRepos(user *model.User) ([]*model.Repo, error) { if r.Private || repo.Private { repo.CloneURL = *item.SSHURL + repo.Private = true } // if no permissions we should skip the repository