in bigquery/main.go [203:317]
func (n *bqNotifier) SendNotification(ctx context.Context, build *cbpb.Build) error {
if !n.filter.Apply(ctx, build) {
log.V(2).Infof("not doing BQ write for build %v", build.Id)
return nil
}
if build.BuildTriggerId == "" {
log.Warningf("build passes filter but does not have a trigger ID. Build id: %q, status: %v", build.Id, build.GetStatus())
}
if !terminalStatusCodes[build.Status] {
log.Infof("not writing to BigQuery for non-terminal build status %v", build.Status.String())
return nil
}
log.Infof("sending Big Query write for build %q (status: %q)", build.Id, build.Status)
if build.ProjectId == "" {
return fmt.Errorf("build missing project id")
}
buildImages := []*buildImage{}
shaSet := make(map[string]bool)
if build.Status == cbpb.Build_SUCCESS {
for _, image := range build.GetImages() {
buildImage, err := imageManifestToBuildImage(image)
if err != nil {
return fmt.Errorf("error parsing image manifest: %v", err)
}
if shaSet[buildImage.SHA] {
continue
}
shaSet[buildImage.SHA] = true
buildImages = append(buildImages, buildImage)
}
}
buildSteps := []*buildStep{}
createTime, err := parsePBTime(build.CreateTime)
if err != nil {
return fmt.Errorf("error parsing CreateTime: %v", err)
}
startTime, err := parsePBTime(build.StartTime)
if err != nil {
return fmt.Errorf("error parsing StartTime: %v", err)
}
finishTime, err := parsePBTime(build.FinishTime)
if err != nil {
return fmt.Errorf("error parsing FinishTime: %v", err)
}
unixZeroTimestamp := timestamppb.New(time.Unix(0, 0))
for _, step := range build.GetSteps() {
st := step.GetTiming().GetStartTime()
et := step.GetTiming().GetEndTime()
if st == nil {
st = unixZeroTimestamp
}
if et == nil {
et = unixZeroTimestamp
}
startTime, err := parsePBTime(st)
if err != nil {
return fmt.Errorf("error parsing StartTime: %v", err)
}
endTime, err := parsePBTime(et)
if err != nil {
return fmt.Errorf("error parsing EndTime: %v", err)
}
newStep := &buildStep{
Name: step.Name,
ID: step.Id,
Status: step.GetStatus().String(),
Args: step.Args,
StartTime: startTime,
EndTime: endTime,
}
buildSteps = append(buildSteps, newStep)
}
logURL, err := notifiers.AddUTMParams(build.LogUrl, notifiers.StorageMedium)
if err != nil {
return fmt.Errorf("error generating UTM params: %v", err)
}
substitutions := []*substitution{}
for key, value := range build.Substitutions {
substitutions = append(substitutions, &substitution{key, value})
}
var bindings map[string]string
if n.br != nil {
bindings, err = n.br.Resolve(ctx, nil, build)
if err != nil {
return fmt.Errorf("failed to resolve bindings: %w", err)
}
}
n.tmplView = ¬ifiers.TemplateView{
Build: ¬ifiers.BuildView{Build: build},
Params: bindings,
}
var buf bytes.Buffer
if err := n.tmpl.Execute(&buf, n.tmplView); err != nil {
return err
}
newRow := &bqRow{
ProjectID: build.ProjectId,
ID: build.Id,
BuildTriggerID: build.BuildTriggerId,
Status: build.Status.String(),
Images: buildImages,
Steps: buildSteps,
CreateTime: createTime,
StartTime: startTime,
FinishTime: finishTime,
Tags: build.Tags,
Env: build.Options.Env,
LogURL: logURL,
Substitutions: substitutions,
JSON: buf.String(),
}
return n.client.WriteRow(ctx, newRow)
}