| OLD | NEW |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. | 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package buildbucket | 5 package buildbucket |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "errors" | 9 "errors" |
| 10 "fmt" | 10 "fmt" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 Build bucketApi.ApiCommonBuildMessage | 45 Build bucketApi.ApiCommonBuildMessage |
| 46 Hostname string | 46 Hostname string |
| 47 } | 47 } |
| 48 | 48 |
| 49 var ( | 49 var ( |
| 50 errNoLogLocation = errors.New("log_location tag not found") | 50 errNoLogLocation = errors.New("log_location tag not found") |
| 51 errNoProject = errors.New("project tag not found") | 51 errNoProject = errors.New("project tag not found") |
| 52 ) | 52 ) |
| 53 | 53 |
| 54 type parameters struct { | 54 type parameters struct { |
| 55 » builderName string `json:"builder_name"` | 55 » BuilderName string `json:"builder_name"` |
| 56 » properties string `json:"properties"` | 56 » Properties string `json:"properties"` |
| 57 } | 57 } |
| 58 | 58 |
| 59 func isLUCI(build *bucketApi.ApiCommonBuildMessage) bool { | 59 func isLUCI(build *bucketApi.ApiCommonBuildMessage) bool { |
| 60 // All luci buckets are assumed to be prefixed with luci. | 60 // All luci buckets are assumed to be prefixed with luci. |
| 61 return strings.HasPrefix(build.Bucket, "luci.") | 61 return strings.HasPrefix(build.Bucket, "luci.") |
| 62 } | 62 } |
| 63 | 63 |
| 64 // PubSubHandler is a webhook that stores the builds coming in from pubsub. | 64 // PubSubHandler is a webhook that stores the builds coming in from pubsub. |
| 65 func PubSubHandler(ctx *router.Context) { | 65 func PubSubHandler(ctx *router.Context) { |
| 66 err := pubSubHandlerImpl(ctx.Context, ctx.Request) | 66 err := pubSubHandlerImpl(ctx.Context, ctx.Request) |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 build := &data.Build | 177 build := &data.Build |
| 178 p := parameters{} | 178 p := parameters{} |
| 179 err := json.Unmarshal([]byte(build.ParametersJson), &p) | 179 err := json.Unmarshal([]byte(build.ParametersJson), &p) |
| 180 if err != nil { | 180 if err != nil { |
| 181 logging.WithError(err).Errorf(c, "could not unmarshal build para
meters") | 181 logging.WithError(err).Errorf(c, "could not unmarshal build para
meters") |
| 182 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status
, "Rejected") | 182 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status
, "Rejected") |
| 183 // Permanent error, since this is probably a type of build we do
not recognize. | 183 // Permanent error, since this is probably a type of build we do
not recognize. |
| 184 return err | 184 return err |
| 185 } | 185 } |
| 186 logging.Debugf(c, "Received from %s: build %s/%s (%s)\n%s", | 186 logging.Debugf(c, "Received from %s: build %s/%s (%s)\n%s", |
| 187 » » host, build.Bucket, p.builderName, build.Status, build) | 187 » » host, build.Bucket, p.BuilderName, build.Status, build) |
| 188 if !isLUCI(build) { | 188 if !isLUCI(build) { |
| 189 logging.Infof(c, "This is not a luci build, ignoring") | 189 logging.Infof(c, "This is not a luci build, ignoring") |
| 190 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status
, "Rejected") | 190 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status
, "Rejected") |
| 191 return nil | 191 return nil |
| 192 } | 192 } |
| 193 | 193 |
| 194 buildEntry, err := processBuild(c, host, build) | 194 buildEntry, err := processBuild(c, host, build) |
| 195 if err != nil { | 195 if err != nil { |
| 196 logging.WithError(err).Errorf(c, "failed to update build") | 196 logging.WithError(err).Errorf(c, "failed to update build") |
| 197 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status
, "Rejected") | 197 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status
, "Rejected") |
| 198 // Probably a datastore or network flake, make this into a trans
ient error | 198 // Probably a datastore or network flake, make this into a trans
ient error |
| 199 return transient.Tag.Apply(err) | 199 return transient.Tag.Apply(err) |
| 200 } | 200 } |
| 201 action := "Created" | 201 action := "Created" |
| 202 if buildEntry.created != buildEntry.modified { | 202 if buildEntry.created != buildEntry.modified { |
| 203 action = "Modified" | 203 action = "Modified" |
| 204 } | 204 } |
| 205 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status, action
) | 205 buildCounter.Add(c, 1, build.Bucket, isLUCI(build), build.Status, action
) |
| 206 | 206 |
| 207 return saveBuildSummary( | 207 return saveBuildSummary( |
| 208 » » c, datastore.MakeKey(c, "buildEntry", buildEntry.key), p.builder
Name, buildEntry) | 208 » » c, datastore.MakeKey(c, "buildEntry", buildEntry.key), p.Builder
Name, buildEntry) |
| 209 } | 209 } |
| 210 | 210 |
| 211 // This returns 500 (Internal Server Error) if it encounters a transient error, | 211 // This returns 500 (Internal Server Error) if it encounters a transient error, |
| 212 // and returns 200 (OK) if everything is OK, or if it encounters a permanent err
or. | 212 // and returns 200 (OK) if everything is OK, or if it encounters a permanent err
or. |
| 213 func pubSubHandlerImpl(c context.Context, r *http.Request) error { | 213 func pubSubHandlerImpl(c context.Context, r *http.Request) error { |
| 214 var data psMsg | 214 var data psMsg |
| 215 | 215 |
| 216 msg := common.PubSubSubscription{} | 216 msg := common.PubSubSubscription{} |
| 217 defer r.Body.Close() | 217 defer r.Body.Close() |
| 218 dec := json.NewDecoder(r.Body) | 218 dec := json.NewDecoder(r.Body) |
| 219 if err := dec.Decode(&msg); err != nil { | 219 if err := dec.Decode(&msg); err != nil { |
| 220 logging.WithError(err).Errorf(c, "could not decode message:\n%s"
, r.Body) | 220 logging.WithError(err).Errorf(c, "could not decode message:\n%s"
, r.Body) |
| 221 // This might be a transient error, e.g. when the json format ch
anges | 221 // This might be a transient error, e.g. when the json format ch
anges |
| 222 // and Milo isn't updated yet. | 222 // and Milo isn't updated yet. |
| 223 return transient.Tag.Apply(err) | 223 return transient.Tag.Apply(err) |
| 224 } | 224 } |
| 225 bData, err := msg.GetData() | 225 bData, err := msg.GetData() |
| 226 if err != nil { | 226 if err != nil { |
| 227 logging.WithError(err).Errorf(c, "could not parse pubsub message
string") | 227 logging.WithError(err).Errorf(c, "could not parse pubsub message
string") |
| 228 return err | 228 return err |
| 229 } | 229 } |
| 230 if err := json.Unmarshal(bData, &data); err != nil { | 230 if err := json.Unmarshal(bData, &data); err != nil { |
| 231 logging.WithError(err).Errorf(c, "could not parse pubsub message
data") | 231 logging.WithError(err).Errorf(c, "could not parse pubsub message
data") |
| 232 return err | 232 return err |
| 233 } | 233 } |
| 234 | 234 |
| 235 return handlePubSubBuild(c, &data) | 235 return handlePubSubBuild(c, &data) |
| 236 } | 236 } |
| OLD | NEW |