diff --git a/.drone.yml b/.drone.yml index d372a27e6..9024cfd2d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -118,7 +118,7 @@ pipeline: image: plugins/docker repo: drone/drone secrets: [ docker_username, docker_password ] - tag: [ 0.8, 0.8.5 ] + tag: [ 0.8, 0.8.7 ] when: event: tag @@ -127,7 +127,7 @@ pipeline: repo: drone/agent dockerfile: Dockerfile.agent secrets: [ docker_username, docker_password ] - tag: [ 0.8, 0.8.5 ] + tag: [ 0.8, 0.8.7 ] when: event: tag diff --git a/plugins/secrets/vault/kubernetes.go b/plugins/secrets/vault/kubernetes.go index f289a8aff..32a88f500 100644 --- a/plugins/secrets/vault/kubernetes.go +++ b/plugins/secrets/vault/kubernetes.go @@ -12,13 +12,13 @@ Vault JSON Response { "auth": { "client_token" = "token", - "lease_duration" = "1234s" + "lease_duration" = 1234 } } */ type vaultAuth struct { Token string `json:"client_token"` - Lease string `json:"lease_duration"` + Lease int `json:"lease_duration"` } type vaultResp struct { Auth vaultAuth @@ -42,10 +42,7 @@ func getKubernetesToken(addr, role, mount, tokenFile string) (string, time.Durat return "", 0, err } - ttl, err := time.ParseDuration(resp.Auth.Lease) - if err != nil { - return "", 0, err - } + ttl := time.Duration(resp.Auth.Lease) * time.Second return resp.Auth.Token, ttl, nil } diff --git a/plugins/secrets/vault/kubernetes_test.go b/plugins/secrets/vault/kubernetes_test.go index 1e1fbedee..42cfe6370 100644 --- a/plugins/secrets/vault/kubernetes_test.go +++ b/plugins/secrets/vault/kubernetes_test.go @@ -17,9 +17,9 @@ func TestGetKubernetesToken(t *testing.T) { b, _ := ioutil.ReadFile(fakeJwtFile) fakeJwt := string(b) fakeClientToken := "fakeClientToken" - fakeLeaseMinutes := "10m" - fakeLeaseDuration, _ := time.ParseDuration(fakeLeaseMinutes) - fakeResp := fmt.Sprintf("{\"auth\": {\"client_token\": \"%s\", \"lease_duration\": \"%s\"}}", fakeClientToken, fakeLeaseMinutes) + fakeLeaseSeconds := 86400 + fakeLeaseDuration := time.Duration(fakeLeaseSeconds) * time.Second + fakeResp := fmt.Sprintf("{\"auth\": {\"client_token\": \"%s\", \"lease_duration\": %d}}", fakeClientToken, fakeLeaseSeconds) expectedPath := "/v1/auth/kubernetes/login" ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/remote/bitbucketserver/internal/client.go b/remote/bitbucketserver/internal/client.go index b569fcb18..774efd175 100644 --- a/remote/bitbucketserver/internal/client.go +++ b/remote/bitbucketserver/internal/client.go @@ -23,10 +23,11 @@ import ( "net/http" "strconv" + "strings" + log "github.com/Sirupsen/logrus" "github.com/drone/drone/model" "github.com/mrjones/oauth" - "strings" ) const ( @@ -61,10 +62,13 @@ func NewClientWithToken(url string, consumer *oauth.Consumer, AccessToken string func (c *Client) FindCurrentUser() (*User, error) { CurrentUserIdResponse, err := c.client.Get(fmt.Sprintf(currentUserId, c.base)) + if CurrentUserIdResponse != nil { + defer CurrentUserIdResponse.Body.Close() + } if err != nil { return nil, err } - defer CurrentUserIdResponse.Body.Close() + bits, err := ioutil.ReadAll(CurrentUserIdResponse.Body) if err != nil { return nil, err @@ -72,10 +76,12 @@ func (c *Client) FindCurrentUser() (*User, error) { login := string(bits) CurrentUserResponse, err := c.client.Get(fmt.Sprintf(pathUser, c.base, login)) + if CurrentUserResponse != nil { + defer CurrentUserResponse.Body.Close() + } if err != nil { return nil, err } - defer CurrentUserResponse.Body.Close() contents, err := ioutil.ReadAll(CurrentUserResponse.Body) if err != nil { @@ -95,10 +101,12 @@ func (c *Client) FindCurrentUser() (*User, error) { func (c *Client) FindRepo(owner string, name string) (*Repo, error) { urlString := fmt.Sprintf(pathRepo, c.base, owner, name) response, err := c.client.Get(urlString) + if response != nil { + defer response.Body.Close() + } if err != nil { log.Error(err) } - defer response.Body.Close() contents, err := ioutil.ReadAll(response.Body) repo := Repo{} err = json.Unmarshal(contents, &repo) @@ -120,7 +128,10 @@ func (c *Client) FindRepoPerms(owner string, repo string) (*model.Perm, error) { return perms, err } // Must have admin to be able to list hooks. If have access the enable perms - _, err = c.client.Get(fmt.Sprintf(pathHook, c.base, owner, repo, hookName)) + resp, err := c.client.Get(fmt.Sprintf(pathHook, c.base, owner, repo, hookName)) + if resp != nil { + defer resp.Body.Close() + } if err == nil { perms.Push = true perms.Admin = true @@ -131,13 +142,15 @@ func (c *Client) FindRepoPerms(owner string, repo string) (*model.Perm, error) { func (c *Client) FindFileForRepo(owner string, repo string, fileName string, ref string) ([]byte, error) { response, err := c.client.Get(fmt.Sprintf(pathSource, c.base, owner, repo, fileName, ref)) + if response != nil { + defer response.Body.Close() + } if err != nil { log.Error(err) } if response.StatusCode == 404 { return nil, nil } - defer response.Body.Close() responseBytes, err := ioutil.ReadAll(response.Body) if err != nil { log.Error(err) @@ -191,10 +204,13 @@ func (c *Client) DeleteHook(owner string, name string, link string) error { func (c *Client) GetHookDetails(owner string, name string) (*HookPluginDetails, error) { urlString := fmt.Sprintf(pathHookDetails, c.base, owner, name, hookName) response, err := c.client.Get(urlString) + if response != nil { + defer response.Body.Close() + } if err != nil { return nil, err } - defer response.Body.Close() + hookDetails := HookPluginDetails{} err = json.NewDecoder(response.Body).Decode(&hookDetails) return &hookDetails, err @@ -203,10 +219,13 @@ func (c *Client) GetHookDetails(owner string, name string) (*HookPluginDetails, func (c *Client) GetHooks(owner string, name string) (*HookSettings, error) { urlString := fmt.Sprintf(pathHookSettings, c.base, owner, name, hookName) response, err := c.client.Get(urlString) + if response != nil { + defer response.Body.Close() + } if err != nil { return nil, err } - defer response.Body.Close() + hookSettings := HookSettings{} err = json.NewDecoder(response.Body).Decode(&hookSettings) return &hookSettings, err @@ -219,10 +238,12 @@ func (c *Client) doPut(url string, body []byte) error { request, err := http.NewRequest("PUT", url, bytes.NewBuffer(body)) request.Header.Add("Content-Type", "application/json") response, err := c.client.Do(request) + if response != nil { + defer response.Body.Close() + } if err != nil { return err } - defer response.Body.Close() return nil } @@ -240,22 +261,20 @@ func (c *Client) doPost(url string, status *BuildStatus) error { 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 + if response != nil { + defer response.Body.Close() } - defer response.Body.Close() - return nil + return err } //Helper function to do delete on the hook func (c *Client) doDelete(url string) error { request, err := http.NewRequest("DELETE", url, nil) response, err := c.client.Do(request) - if err != nil { - return err + if response != nil { + defer response.Body.Close() } - defer response.Body.Close() - return nil + return err } //Helper function to get repos paginated @@ -263,10 +282,12 @@ func (c *Client) paginatedRepos(start int) ([]*Repo, error) { limit := 1000 requestUrl := fmt.Sprintf(pathRepos, c.base, strconv.Itoa(start), strconv.Itoa(limit)) response, err := c.client.Get(requestUrl) + if response != nil { + defer response.Body.Close() + } if err != nil { return nil, err } - defer response.Body.Close() var repoResponse Repos err = json.NewDecoder(response.Body).Decode(&repoResponse) if err != nil { diff --git a/remote/gitea/helper.go b/remote/gitea/helper.go index 0b0a918ac..e330545f6 100644 --- a/remote/gitea/helper.go +++ b/remote/gitea/helper.go @@ -82,13 +82,18 @@ func buildFromPush(hook *pushHook) *model.Build { sender = hook.Sender.Login } + message := "" + if len(hook.Commits) > 0 { + message = hook.Commits[0].Message + } + return &model.Build{ Event: model.EventPush, Commit: hook.After, Ref: hook.Ref, Link: hook.Compare, Branch: strings.TrimPrefix(hook.Ref, "refs/heads/"), - Message: hook.Commits[0].Message, + Message: message, Avatar: avatar, Author: author, Email: hook.Sender.Email, diff --git a/server/stream.go b/server/stream.go index 6dd19a9ba..5856044ee 100644 --- a/server/stream.go +++ b/server/stream.go @@ -188,6 +188,9 @@ func LogStreamSSE(c *gin.Context) { go func() { // TODO remove global variable Config.Services.Logs.Tail(ctx, fmt.Sprint(proc.ID), func(entries ...*logging.Entry) { + defer func() { + recover() // fix #2480 + }() for _, entry := range entries { select { case <-ctx.Done(): diff --git a/vendor/github.com/drone/envsubst/funcs.go b/vendor/github.com/drone/envsubst/funcs.go index 8df1c9876..94a3be1f2 100644 --- a/vendor/github.com/drone/envsubst/funcs.go +++ b/vendor/github.com/drone/envsubst/funcs.go @@ -1,11 +1,12 @@ package envsubst import ( - "path" "strconv" "strings" "unicode" "unicode/utf8" + + "github.com/drone/envsubst/path" ) // defines a parameter substitution function. @@ -89,8 +90,8 @@ func toSubstr(s string, args ...string) string { if pos+length >= len(s) { // if the position exceeds the length of the - // string an empty string is returned - return "" + // string just return the rest of it like bash + return s[pos:] } return s[pos : pos+length] @@ -183,7 +184,7 @@ func trimLongestSuffix(s string, args ...string) string { func trimShortest(s, arg string) string { var shortestMatch string - for i :=0 ; i < len(s); i++ { + for i := 0; i < len(s); i++ { match, err := path.Match(arg, s[0:len(s)-i]) if err != nil { @@ -191,7 +192,7 @@ func trimShortest(s, arg string) string { } if match { - shortestMatch = s[0:len(s)-i] + shortestMatch = s[0 : len(s)-i] } } @@ -203,7 +204,7 @@ func trimShortest(s, arg string) string { } func trimLongest(s, arg string) string { - for i :=0 ; i < len(s); i++ { + for i := 0; i < len(s); i++ { match, err := path.Match(arg, s[0:len(s)-i]) if err != nil { diff --git a/vendor/github.com/drone/envsubst/match.go b/vendor/github.com/drone/envsubst/match.go deleted file mode 100644 index e2f94b580..000000000 --- a/vendor/github.com/drone/envsubst/match.go +++ /dev/null @@ -1,20 +0,0 @@ -package envsubst - -func matches() { - -} - -// alnum -// alpha -// ascii -// blank -// cntrl -// digit -// graph -// lower -// print -// punct -// space -// upper -// word -// xdigit diff --git a/vendor/github.com/drone/envsubst/parse/parse.go b/vendor/github.com/drone/envsubst/parse/parse.go index ef826289d..683b44d54 100644 --- a/vendor/github.com/drone/envsubst/parse/parse.go +++ b/vendor/github.com/drone/envsubst/parse/parse.go @@ -174,10 +174,6 @@ func (t *Tree) parseSubstrFunc(name string) (Node, error) { default: return nil, ErrBadSubstitution } - // err := t.consumeDelimiter(acceptColon, scanIdent|scanRbrack) - // if err != nil { - // return nil, err - // } // scan arg[2] { @@ -258,8 +254,15 @@ func (t *Tree) parseReplaceFunc(name string) (Node, error) { return nil, ErrBadSubstitution } + // check for blank string + switch t.scanner.peek() { + case '}': + return node, t.consumeRbrack() + } + + // scan arg[2] { - param, err := t.parseParam(acceptNotClosing, scanIdent) + param, err := t.parseParam(acceptNotClosing, scanIdent|scanEscape) if err != nil { return nil, err } diff --git a/vendor/github.com/drone/envsubst/path/match.go b/vendor/github.com/drone/envsubst/path/match.go new file mode 100644 index 000000000..9306b0c9d --- /dev/null +++ b/vendor/github.com/drone/envsubst/path/match.go @@ -0,0 +1,207 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "errors" + "unicode/utf8" +) + +// ErrBadPattern indicates a globbing pattern was malformed. +var ErrBadPattern = errors.New("syntax error in pattern") + +// Match reports whether name matches the shell file name pattern. +// The pattern syntax is: +// +// pattern: +// { term } +// term: +// '*' matches any sequence of non-/ characters +// '?' matches any single non-/ character +// '[' [ '^' ] { character-range } ']' +// character class (must be non-empty) +// c matches character c (c != '*', '?', '\\', '[') +// '\\' c matches character c +// +// character-range: +// c matches character c (c != '\\', '-', ']') +// '\\' c matches character c +// lo '-' hi matches character c for lo <= c <= hi +// +// Match requires pattern to match all of name, not just a substring. +// The only possible returned error is ErrBadPattern, when pattern +// is malformed. +// +func Match(pattern, name string) (matched bool, err error) { +Pattern: + for len(pattern) > 0 { + var star bool + var chunk string + star, chunk, pattern = scanChunk(pattern) + if star && chunk == "" { + // Trailing * matches rest of string unless it has a /. + // return !strings.Contains(name, "/"), nil + + // Return rest of string + return true, nil + } + // Look for match at current position. + t, ok, err := matchChunk(chunk, name) + // if we're the last chunk, make sure we've exhausted the name + // otherwise we'll give a false result even if we could still match + // using the star + if ok && (len(t) == 0 || len(pattern) > 0) { + name = t + continue + } + if err != nil { + return false, err + } + if star { + // Look for match skipping i+1 bytes. + for i := 0; i < len(name); i++ { + t, ok, err := matchChunk(chunk, name[i+1:]) + if ok { + // if we're the last chunk, make sure we exhausted the name + if len(pattern) == 0 && len(t) > 0 { + continue + } + name = t + continue Pattern + } + if err != nil { + return false, err + } + } + } + return false, nil + } + return len(name) == 0, nil +} + +// scanChunk gets the next segment of pattern, which is a non-star string +// possibly preceded by a star. +func scanChunk(pattern string) (star bool, chunk, rest string) { + for len(pattern) > 0 && pattern[0] == '*' { + pattern = pattern[1:] + star = true + } + inrange := false + var i int +Scan: + for i = 0; i < len(pattern); i++ { + switch pattern[i] { + case '\\': + // error check handled in matchChunk: bad pattern. + if i+1 < len(pattern) { + i++ + } + case '[': + inrange = true + case ']': + inrange = false + case '*': + if !inrange { + break Scan + } + } + } + return star, pattern[0:i], pattern[i:] +} + +// matchChunk checks whether chunk matches the beginning of s. +// If so, it returns the remainder of s (after the match). +// Chunk is all single-character operators: literals, char classes, and ?. +func matchChunk(chunk, s string) (rest string, ok bool, err error) { + for len(chunk) > 0 { + if len(s) == 0 { + return + } + switch chunk[0] { + case '[': + // character class + r, n := utf8.DecodeRuneInString(s) + s = s[n:] + chunk = chunk[1:] + // possibly negated + notNegated := true + if len(chunk) > 0 && chunk[0] == '^' { + notNegated = false + chunk = chunk[1:] + } + // parse all ranges + match := false + nrange := 0 + for { + if len(chunk) > 0 && chunk[0] == ']' && nrange > 0 { + chunk = chunk[1:] + break + } + var lo, hi rune + if lo, chunk, err = getEsc(chunk); err != nil { + return + } + hi = lo + if chunk[0] == '-' { + if hi, chunk, err = getEsc(chunk[1:]); err != nil { + return + } + } + if lo <= r && r <= hi { + match = true + } + nrange++ + } + if match != notNegated { + return + } + + case '?': + _, n := utf8.DecodeRuneInString(s) + s = s[n:] + chunk = chunk[1:] + + case '\\': + chunk = chunk[1:] + if len(chunk) == 0 { + err = ErrBadPattern + return + } + fallthrough + + default: + if chunk[0] != s[0] { + return + } + s = s[1:] + chunk = chunk[1:] + } + } + return s, true, nil +} + +// getEsc gets a possibly-escaped character from chunk, for a character class. +func getEsc(chunk string) (r rune, nchunk string, err error) { + if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' { + err = ErrBadPattern + return + } + if chunk[0] == '\\' { + chunk = chunk[1:] + if len(chunk) == 0 { + err = ErrBadPattern + return + } + } + r, n := utf8.DecodeRuneInString(chunk) + if r == utf8.RuneError && n == 1 { + err = ErrBadPattern + } + nchunk = chunk[n:] + if len(nchunk) == 0 { + err = ErrBadPattern + } + return +} diff --git a/vendor/vendor.json b/vendor/vendor.json index e45986fa1..c57b90f83 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -476,16 +476,22 @@ "revisionTime": "2017-02-10T18:43:46Z" }, { - "checksumSHA1": "pjMV8mwWcQ0Kk9cbLWweTGiqYPk=", + "checksumSHA1": "oX91yMnimWNI17gVk7iQIE0p2pw=", "path": "github.com/drone/envsubst", - "revision": "523de92ea410a5756012669fb628fe42a3056b3e", - "revisionTime": "2017-03-25T05:49:59Z" + "revision": "15e3f9b7e16332eee3bbdff9ef31f95d23c5da2c", + "revisionTime": "2018-10-18T14:46:17Z" }, { - "checksumSHA1": "CVG/vocbXGLbGKRO//TOlicOBkw=", + "checksumSHA1": "CCV0ixQVgQNOsnUn8JlxGJ1v8c4=", "path": "github.com/drone/envsubst/parse", - "revision": "523de92ea410a5756012669fb628fe42a3056b3e", - "revisionTime": "2017-03-25T05:49:59Z" + "revision": "15e3f9b7e16332eee3bbdff9ef31f95d23c5da2c", + "revisionTime": "2018-10-18T14:46:17Z" + }, + { + "checksumSHA1": "k8a4yeccwcAfBwHgj16Da0F9iQE=", + "path": "github.com/drone/envsubst/path", + "revision": "15e3f9b7e16332eee3bbdff9ef31f95d23c5da2c", + "revisionTime": "2018-10-18T14:46:17Z" }, { "checksumSHA1": "AT++gcbYW/VQxkmbInFJk1Feg3o=", diff --git a/version/version.go b/version/version.go index 4be904ee1..4070a7298 100644 --- a/version/version.go +++ b/version/version.go @@ -22,7 +22,7 @@ var ( // VersionMinor is for functionality in a backwards-compatible manner. VersionMinor int64 = 8 // VersionPatch is for backwards-compatible bug fixes. - VersionPatch int64 = 5 + VersionPatch int64 = 7 // VersionPre indicates prerelease. VersionPre string // VersionDev indicates development branch. Releases will be empty string.