From 5c7a66534d74cc90649920a3360e1651f47eaff6 Mon Sep 17 00:00:00 2001 From: Joachim Hill-Grannec Date: Sat, 13 Aug 2016 19:06:15 -0700 Subject: [PATCH 1/7] Adding the ability for the bitbucket server remote to update the status of commits on the server --- remote/bitbucketserver/bitbucketserver.go | 13 +++++-- remote/bitbucketserver/convert.go | 42 +++++++++++++++++++++++ remote/bitbucketserver/internal/client.go | 36 ++++++++++++++++++- remote/bitbucketserver/internal/types.go | 8 +++++ 4 files changed, 96 insertions(+), 3 deletions(-) diff --git a/remote/bitbucketserver/bitbucketserver.go b/remote/bitbucketserver/bitbucketserver.go index 8b70edf82..6012955f2 100644 --- a/remote/bitbucketserver/bitbucketserver.go +++ b/remote/bitbucketserver/bitbucketserver.go @@ -149,8 +149,17 @@ func (c *Config) File(u *model.User, r *model.Repo, b *model.Build, f string) ([ } // Status is not supported by the bitbucketserver driver. -func (*Config) Status(*model.User, *model.Repo, *model.Build, string) error { - return nil +func (c *Config) Status(u *model.User,r *model.Repo,b *model.Build,link string) error { + status := internal.BuildStatus{ + State: convertStatus(b.Status), + Desc: convertDesc(b.Status), + Key: "Drone", + Url: link, + } + + client := internal.NewClientWithToken(c.URL, c.Consumer, u.Token) + + return client.CreateStatus(b.Commit, &status) } func (c *Config) Netrc(user *model.User, r *model.Repo) (*model.Netrc, error) { diff --git a/remote/bitbucketserver/convert.go b/remote/bitbucketserver/convert.go index 65fe8e3cb..20f7069fb 100644 --- a/remote/bitbucketserver/convert.go +++ b/remote/bitbucketserver/convert.go @@ -13,6 +13,48 @@ import ( "time" ) + +const ( + statusPending = "INPROGRESS" + statusSuccess = "SUCCESSFUL" + statusFailure = "FAILED" +) + +const ( + descPending = "this build is pending" + descSuccess = "the build was successful" + descFailure = "the build failed" + descError = "oops, something went wrong" +) + +// convertStatus is a helper function used to convert a Drone status to a +// Bitbucket commit status. +func convertStatus(status string) string { + switch status { + case model.StatusPending, model.StatusRunning: + return statusPending + case model.StatusSuccess: + return statusSuccess + default: + return statusFailure + } +} + +// convertDesc is a helper function used to convert a Drone status to a +// Bitbucket status description. +func convertDesc(status string) string { + switch status { + case model.StatusPending, model.StatusRunning: + return descPending + case model.StatusSuccess: + return descSuccess + case model.StatusFailure: + return descFailure + default: + return descError + } +} + // convertRepo is a helper function used to convert a Bitbucket server repository // structure to the common Drone repository structure. func convertRepo(from *internal.Repo) *model.Repo { diff --git a/remote/bitbucketserver/internal/client.go b/remote/bitbucketserver/internal/client.go index 058538481..11bf904fe 100644 --- a/remote/bitbucketserver/internal/client.go +++ b/remote/bitbucketserver/internal/client.go @@ -9,6 +9,7 @@ import ( "github.com/mrjones/oauth" "io/ioutil" "net/http" + "io" ) const ( @@ -20,6 +21,7 @@ const ( pathSource = "%s/projects/%s/repos/%s/browse/%s?at=%s&raw" hookName = "com.atlassian.stash.plugin.stash-web-post-receive-hooks-plugin:postReceiveHook" pathHookEnabled = "%s/rest/api/1.0/projects/%s/repos/%s/settings/hooks/%s/enabled" + pathStatus = "%s/rest/build-status/1.0/commits/%s" ) type Client struct { @@ -151,11 +153,18 @@ func (c *Client) CreateHook(owner string, name string, callBackLink string) erro return c.doPut(fmt.Sprintf(pathHookEnabled, c.base, owner, name, hookName), hookBytes) } +func (c *Client) CreateStatus(revision string, status *BuildStatus) error { + uri := fmt.Sprintf(pathStatus, c.base, revision) + return c.doPost(uri, status) +} + func (c *Client) DeleteHook(owner string, name string, link string) error { //TODO: eventially should only delete the link callback return c.doDelete(fmt.Sprintf(pathHookEnabled, c.base, owner, name, hookName)) } +//TODO: make these as as general do with the action + //Helper function to help create the hook func (c *Client) doPut(url string, body []byte) error { request, err := http.NewRequest("PUT", url, bytes.NewBuffer(body)) @@ -166,9 +175,34 @@ func (c *Client) doPut(url string, body []byte) error { } defer response.Body.Close() return nil - } + +//Helper function to help create the hook +func (c *Client) doPost(url string, status *BuildStatus) error { + // write it to the body of the request. + var buf io.ReadWriter + if status != nil { + buf = new(bytes.Buffer) + err := json.NewEncoder(buf).Encode(status) + if err != nil { + return err + } + } + request, err := http.NewRequest("POST", url, buf) + request.Header.Add("Content-Type", "application/json") + response, err := c.client.Do(request) + if err != nil { + return err + } + defer response.Body.Close() + return nil +} + + + + + //Helper function to do delete on the hook func (c *Client) doDelete(url string) error { request, err := http.NewRequest("DELETE", url, nil) diff --git a/remote/bitbucketserver/internal/types.go b/remote/bitbucketserver/internal/types.go index 0e879e272..9b50c3a09 100644 --- a/remote/bitbucketserver/internal/types.go +++ b/remote/bitbucketserver/internal/types.go @@ -24,6 +24,14 @@ type SelfRefLink struct { Href string `json:"href"` } +type BuildStatus struct { + State string `json:"state"` + Key string `json:"key"` + Name string `json:"name,omitempty"` + Url string `json:"url"` + Desc string `json:"description,omitempty"` +} + type Repo struct { Forkable bool `json:"forkable"` ID int `json:"id"` From 95b3a78aa9351eaba79483297f20e3842f67ff80 Mon Sep 17 00:00:00 2001 From: Joachim Hill-Grannec Date: Sun, 14 Aug 2016 12:27:53 -0700 Subject: [PATCH 2/7] Update to add the name which has a better indication for the label of what build the status is for --- remote/bitbucketserver/bitbucketserver.go | 1 + 1 file changed, 1 insertion(+) diff --git a/remote/bitbucketserver/bitbucketserver.go b/remote/bitbucketserver/bitbucketserver.go index 6012955f2..cb4e415f1 100644 --- a/remote/bitbucketserver/bitbucketserver.go +++ b/remote/bitbucketserver/bitbucketserver.go @@ -153,6 +153,7 @@ func (c *Config) Status(u *model.User,r *model.Repo,b *model.Build,link string) status := internal.BuildStatus{ State: convertStatus(b.Status), Desc: convertDesc(b.Status), + Name: fmt.Sprintf("Drone #%d - %s", b.Number, b.Branch), Key: "Drone", Url: link, } From a4076e00ff253a9fd22670a2355c9cde29f1e4a0 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Mon, 15 Aug 2016 00:02:11 +0200 Subject: [PATCH 3/7] Correct arg length checks --- drone/org_secret_add.go | 2 +- drone/org_secret_list.go | 2 +- drone/org_secret_rm.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drone/org_secret_add.go b/drone/org_secret_add.go index 52ac250dc..c9145fb28 100644 --- a/drone/org_secret_add.go +++ b/drone/org_secret_add.go @@ -42,7 +42,7 @@ var orgSecretAddCmd = cli.Command{ } func orgSecretAdd(c *cli.Context) error { - if len(c.Args().Tail()) != 3 { + if len(c.Args()) != 3 { cli.ShowSubcommandHelp(c) return nil } diff --git a/drone/org_secret_list.go b/drone/org_secret_list.go index ea0144b9b..550224d0b 100644 --- a/drone/org_secret_list.go +++ b/drone/org_secret_list.go @@ -35,7 +35,7 @@ var orgSecretListCmd = cli.Command{ } func orgSecretList(c *cli.Context) error { - if len(c.Args().Tail()) != 1 { + if len(c.Args()) != 1 { cli.ShowSubcommandHelp(c) return nil } diff --git a/drone/org_secret_rm.go b/drone/org_secret_rm.go index c0b4170d0..fc46d7b60 100644 --- a/drone/org_secret_rm.go +++ b/drone/org_secret_rm.go @@ -17,7 +17,7 @@ var orgSecretRemoveCmd = cli.Command{ } func orgSecretRemove(c *cli.Context) error { - if len(c.Args().Tail()) != 2 { + if len(c.Args()) != 2 { cli.ShowSubcommandHelp(c) return nil } From 3539988604c2c80c484272d99e459113aaa8b172 Mon Sep 17 00:00:00 2001 From: Vaidas Jablonskis Date: Fri, 19 Aug 2016 18:27:08 +0100 Subject: [PATCH 4/7] Fix URI encoding fmt.Sprintf was interpreting URL encoding chars previously. Ouch. --- client/client_impl.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/client_impl.go b/client/client_impl.go index 89f78f7c0..ca661a88e 100644 --- a/client/client_impl.go +++ b/client/client_impl.go @@ -222,8 +222,8 @@ func (c *client) BuildQueue() ([]*model.Feed, error) { func (c *client) BuildStart(owner, name string, num int, params map[string]string) (*model.Build, error) { out := new(model.Build) val := parseToQueryParams(params) - uri := fmt.Sprintf(pathBuild+"?"+val.Encode(), c.base, owner, name, num) - err := c.post(uri, nil, out) + uri := fmt.Sprintf(pathBuild, c.base, owner, name, num) + err := c.post(uri+"?"+val.Encode(), nil, out) return out, err } @@ -240,8 +240,8 @@ func (c *client) BuildFork(owner, name string, num int, params map[string]string out := new(model.Build) val := parseToQueryParams(params) val.Set("fork", "true") - uri := fmt.Sprintf(pathBuild+"?"+val.Encode(), c.base, owner, name, num) - err := c.post(uri, nil, out) + uri := fmt.Sprintf(pathBuild, c.base, owner, name, num) + err := c.post(uri+"?"+val.Encode(), nil, out) return out, err } @@ -259,8 +259,8 @@ func (c *client) Deploy(owner, name string, num int, env string, params map[stri val.Set("fork", "true") val.Set("event", "deployment") val.Set("deploy_to", env) - uri := fmt.Sprintf(pathBuild+"?"+val.Encode(), c.base, owner, name, num) - err := c.post(uri, nil, out) + uri := fmt.Sprintf(pathBuild, c.base, owner, name, num) + err := c.post(uri+"?"+val.Encode(), nil, out) return out, err } From 0f7253febb1cad14e7fa115799fa170b57731eb8 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Thu, 25 Aug 2016 11:35:28 -0700 Subject: [PATCH 5/7] choose ambassador by platform --- agent/agent.go | 2 +- yaml/transform/pod.go | 41 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index 9a63fcf4c..2a1e343fa 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -167,7 +167,7 @@ func (a *Agent) prep(w *queue.Work) (*yaml.Config, error) { transform.ImageVolume(conf, []string{a.Local + ":" + conf.Workspace.Path}) } - transform.Pod(conf) + transform.Pod(conf, a.Platform) return conf, nil } diff --git a/yaml/transform/pod.go b/yaml/transform/pod.go index ae734cd6a..dd92acbb8 100644 --- a/yaml/transform/pod.go +++ b/yaml/transform/pod.go @@ -9,21 +9,54 @@ import ( "github.com/gorilla/securecookie" ) +type ambassador struct { + image string + entrypoint []string + command []string +} + +// default linux amd64 ambassador +var defaultAmbassador = ambassador{ + image: "busybox:latest", + entrypoint: []string{"/bin/sleep"}, + command: []string{"86400"}, +} + +// lookup ambassador configuration by architecture and os +var lookupAmbassador = map[string]ambassador{ + "linux/amd64": { + image: "busybox:latest", + entrypoint: []string{"/bin/sleep"}, + command: []string{"86400"}, + }, + "linux/arm": { + image: "armhf/alpine:latest", + entrypoint: []string{"/bin/sleep"}, + command: []string{"86400"}, + }, +} + // Pod transforms the containers in the Yaml to use Pod networking, where every // container shares the localhost connection. -func Pod(c *yaml.Config) error { +func Pod(c *yaml.Config, platform string) error { rand := base64.RawURLEncoding.EncodeToString( securecookie.GenerateRandomKey(8), ) + // choose the ambassador configuration based on os and architecture + conf, ok := lookupAmbassador[platform] + if !ok { + conf = defaultAmbassador + } + ambassador := &yaml.Container{ ID: fmt.Sprintf("drone_ambassador_%s", rand), Name: "ambassador", - Image: "busybox:latest", + Image: conf.image, Detached: true, - Entrypoint: []string{"/bin/sleep"}, - Command: []string{"86400"}, + Entrypoint: conf.entrypoint, + Command: conf.command, Volumes: []string{c.Workspace.Path, c.Workspace.Base}, Environment: map[string]string{}, } From e482ef2790349f500454c3f5c21b37cd70e0d0f2 Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Thu, 25 Aug 2016 13:02:23 -0600 Subject: [PATCH 6/7] Correct escaping of commands in YAML --- yaml/transform/command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yaml/transform/command.go b/yaml/transform/command.go index cf4892f01..a90e8c2a1 100644 --- a/yaml/transform/command.go +++ b/yaml/transform/command.go @@ -40,7 +40,7 @@ func toScript(commands []string) string { var buf bytes.Buffer for _, command := range commands { escaped := fmt.Sprintf("%q", command) - escaped = strings.Replace(command, "$", `$\`, -1) + escaped = strings.Replace(escaped, "$", `\$`, -1) buf.WriteString(fmt.Sprintf( traceScript, escaped, From 5b58768d637aec8f84e0e09b9a4479da2da0547a Mon Sep 17 00:00:00 2001 From: Brendan Gaulin Date: Thu, 25 Aug 2016 18:00:07 -0400 Subject: [PATCH 7/7] OAuth2 GHE Always Register BustedURL When going through the oauth2 module in go, there is a list of "busted" URLs which don't implement OAuth2 properly. Github is on that list, however Github Enterprise(GHE) uses different URLs for each instance. Instead of adding all of these to the global list in the oauth module, we can simply flag all of our tokens as broken until github updates their API. --- remote/github/github.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/remote/github/github.go b/remote/github/github.go index 026380cdf..abd05dc19 100644 --- a/remote/github/github.go +++ b/remote/github/github.go @@ -67,6 +67,9 @@ func New(opts Opts) (remote.Remote, error) { remote.URL = strings.TrimSuffix(opts.URL, "/") remote.API = remote.URL + "/api/v3/" } + + // Hack to enable oauth2 access in older GHE + oauth2.RegisterBrokenAuthHeaderProvider(remote.URL) return remote, nil }