github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/artifactory/artifactory.go (about) 1 // Package artifactory provides a Pipe that push to artifactory 2 package artifactory 3 4 import ( 5 "encoding/json" 6 "fmt" 7 "io" 8 h "net/http" 9 10 "github.com/goreleaser/goreleaser/internal/http" 11 "github.com/goreleaser/goreleaser/internal/pipe" 12 "github.com/goreleaser/goreleaser/pkg/context" 13 ) 14 15 // Pipe for Artifactory. 16 type Pipe struct{} 17 18 func (Pipe) String() string { return "artifactory" } 19 func (Pipe) Skip(ctx *context.Context) bool { return len(ctx.Config.Artifactories) == 0 } 20 21 // Default sets the pipe defaults. 22 func (Pipe) Default(ctx *context.Context) error { 23 for i := range ctx.Config.Artifactories { 24 if ctx.Config.Artifactories[i].ChecksumHeader == "" { 25 ctx.Config.Artifactories[i].ChecksumHeader = "X-Checksum-SHA256" 26 } 27 ctx.Config.Artifactories[i].Method = h.MethodPut 28 } 29 return http.Defaults(ctx.Config.Artifactories) 30 } 31 32 // Publish artifacts to artifactory. 33 // 34 // Docs: https://www.jfrog.com/confluence/display/RTF/Artifactory+REST+API#ArtifactoryRESTAPI-Example-DeployinganArtifact 35 func (Pipe) Publish(ctx *context.Context) error { 36 // Check requirements for every instance we have configured. 37 // If not fulfilled, we can skip this pipeline 38 for _, instance := range ctx.Config.Artifactories { 39 instance := instance 40 if skip := http.CheckConfig(ctx, &instance, "artifactory"); skip != nil { 41 return pipe.Skip(skip.Error()) 42 } 43 } 44 45 return http.Upload(ctx, ctx.Config.Artifactories, "artifactory", checkResponse) 46 } 47 48 // An ErrorResponse reports one or more errors caused by an API request. 49 type errorResponse struct { 50 Response *h.Response // HTTP response that caused this error 51 Errors []Error `json:"errors"` // more detail on individual errors 52 } 53 54 func (r *errorResponse) Error() string { 55 return fmt.Sprintf("%v %v: %d %+v", 56 r.Response.Request.Method, r.Response.Request.URL, 57 r.Response.StatusCode, r.Errors) 58 } 59 60 // An Error reports more details on an individual error in an ErrorResponse. 61 type Error struct { 62 Status int `json:"status"` // Error code 63 Message string `json:"message"` // Message describing the error. 64 } 65 66 // checkResponse checks the API response for errors, and returns them if 67 // present. A response is considered an error if it has a status code outside 68 // the 200 range. 69 // API error responses are expected to have either no response 70 // body, or a JSON response body that maps to ErrorResponse. Any other 71 // response body will be silently ignored. 72 func checkResponse(r *h.Response) error { 73 defer r.Body.Close() 74 if c := r.StatusCode; 200 <= c && c <= 299 { 75 return nil 76 } 77 errorResponse := &errorResponse{Response: r} 78 data, err := io.ReadAll(r.Body) 79 if err == nil && data != nil { 80 err := json.Unmarshal(data, errorResponse) 81 if err != nil { 82 return fmt.Errorf("unexpected error: %w: %s", err, string(data)) 83 } 84 } 85 return errorResponse 86 }