code: func summarizeBuild(c context.Context, b *buildbot.Build) (*model.BuildSummary, error) {
  	bs := &model.BuildSummary{
  		BuildKey:  datastore.KeyForObj(c, (*buildEntity)(b)),
  		BuilderID: fmt.Sprintf("buildbot/%s/%s", b.Master, b.Buildername),
  		BuildID:   fmt.Sprintf("buildbot/%s/%s/%d", b.Master, b.Buildername, b.Number),
  	}
  
  	bs.Experimental = b.Experimental()
  
  	bs.ContextURI = []string{
  		fmt.Sprintf("buildbot://%s/build/%s/%d", b.Master, b.Buildername, b.Number),
  		fmt.Sprintf("buildbot://%s/bot/%s", b.Master, b.Slave),
  	}
  
  	// Try to extract the Buildbucket URL, if available.
  	if uri, ok := getBuildbucketURI(b); ok {
  		bs.ContextURI = append(bs.ContextURI, uri)
  	}
  
  	bs.Summary.Start = b.Times.Start.Time
  	bs.Summary.End = b.Times.Finish.Time
  	bs.Summary.Status = b.Status()
  
  	// Start time acts as a proxy for creation time.
  	bs.Created = b.Times.Start.Time
  
  	// Populates BuildSet and ManifestKey
  	if err := attachRevisionInfo(c, b, bs); err != nil {
  		return nil, err
  	}
  
  	bs.AnnotationURL, _ = b.PropertyValue("log_location").(string)
  
  	// we use the number of steps as the top bits, and the status (Finished
  	// > other) as the low bits as a very dumb version number.
  	bs.Version = int64(len(b.Steps)) << 1
  	if b.Finished {
  		bs.Version |= 1
  	}
  
  	return bs, nil
  }
docs: // summarizeBuild creates a build summary from the buildbot build.