github.com/jonsyu1/godel@v0.0.0-20171017211503-64567a0cf169/apps/distgo/cmd/publish/bintray_publish.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package publish 16 17 import ( 18 "fmt" 19 "io" 20 "io/ioutil" 21 "net/http" 22 "net/url" 23 "path" 24 "strings" 25 26 "github.com/pkg/errors" 27 28 "github.com/palantir/godel/apps/distgo/params" 29 ) 30 31 type BintrayConnectionInfo struct { 32 BasicConnectionInfo 33 Subject string 34 Repository string 35 Release bool 36 DownloadsList bool 37 } 38 39 func (b *BintrayConnectionInfo) Publish(buildSpec params.ProductBuildSpec, paths ProductPaths, stdout io.Writer) ([]string, error) { 40 baseURL := strings.Join([]string{b.URL, "content", b.Subject, b.Repository, buildSpec.ProductName, buildSpec.ProductVersion, paths.productPath}, "/") 41 artifactURLs, err := b.uploadArtifacts(baseURL, paths, nil, stdout) 42 if err != nil { 43 return artifactURLs, err 44 } 45 if b.Release { 46 if err := b.release(buildSpec, stdout); err != nil { 47 fmt.Fprintln(stdout, "Uploading artifacts succeeded, but publish of uploaded artifacts failed:", err) 48 } 49 } 50 if b.DownloadsList { 51 if err := b.addToDownloadsList(buildSpec, paths, stdout); err != nil { 52 fmt.Fprintln(stdout, "Uploading artifacts succeeded, but addings artifact to downloads list failed:", err) 53 } 54 } 55 return artifactURLs, err 56 } 57 58 func (b *BintrayConnectionInfo) release(buildSpec params.ProductBuildSpec, stdout io.Writer) error { 59 publishURLString := strings.Join([]string{b.URL, "content", b.Subject, b.Repository, buildSpec.ProductName, buildSpec.ProductVersion, "publish"}, "/") 60 return b.runBintrayCommand(publishURLString, http.MethodPost, `{"publish_wait_for_secs":-1}`, "running Bintray publish for uploaded artifacts", stdout) 61 } 62 63 func (b *BintrayConnectionInfo) addToDownloadsList(buildSpec params.ProductBuildSpec, paths ProductPaths, stdout io.Writer) error { 64 for _, currArtifactPath := range paths.artifactPaths { 65 downloadsListURLString := strings.Join([]string{b.URL, "file_metadata", b.Subject, b.Repository, paths.productPath, path.Base(currArtifactPath)}, "/") 66 if err := b.runBintrayCommand(downloadsListURLString, http.MethodPut, `{"list_in_downloads":true}`, "adding artifact to Bintray downloads list for package", stdout); err != nil { 67 return err 68 } 69 } 70 return nil 71 } 72 73 func (b *BintrayConnectionInfo) runBintrayCommand(urlString, httpMethod, jsonContent, cmdMsg string, stdout io.Writer) (rErr error) { 74 url, err := url.Parse(urlString) 75 if err != nil { 76 return errors.Wrapf(err, "failed to parse %s as URL", urlString) 77 } 78 79 capitalizedMsg := cmdMsg 80 if len(cmdMsg) > 0 { 81 capitalizedMsg = strings.ToUpper(string(cmdMsg[0])) + cmdMsg[1:] 82 } 83 84 fmt.Fprintf(stdout, "%s...", capitalizedMsg) 85 defer func() { 86 fmt.Fprintln(stdout) 87 }() 88 89 reader := strings.NewReader(jsonContent) 90 91 header := http.Header{} 92 header.Set("Content-Type", "application/json") 93 req := http.Request{ 94 Method: httpMethod, 95 URL: url, 96 Header: header, 97 Body: ioutil.NopCloser(reader), 98 ContentLength: int64(len([]byte(jsonContent))), 99 } 100 req.SetBasicAuth(b.Username, b.Password) 101 102 resp, err := http.DefaultClient.Do(&req) 103 if err != nil { 104 return errors.Wrapf(err, "%s", cmdMsg) 105 } 106 defer func() { 107 if err := resp.Body.Close(); err != nil && rErr == nil { 108 rErr = errors.Wrapf(err, "failed to close response body for URL %s", urlString) 109 } 110 }() 111 112 if resp.StatusCode >= http.StatusBadRequest { 113 return errors.Errorf("%s resulted in response: %s", cmdMsg, resp.Status) 114 } 115 116 fmt.Fprint(stdout, "done") 117 118 return nil 119 }