dmitri.shuralyov.com/service/change/...

add CommitEvent event type

This results in a more complete and readable timeline.

Populate it from Gerrit CLs. It's helpful to see when
new patch sets have been uploaded in between comments.

It's not supported by other change.Service implementations
yet, but that can be done when there's some demand for it.
dmitshur committed 3 months ago commit bd27112db59ba9f1e01f6d1e36ea7715c9dde98c
gerritapi/gerritapi.go
@@ -275,11 +275,11 @@ func (s service) GetDiff(ctx context.Context, repo string, id uint64, opt *chang
 func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt *change.ListTimelineOptions) ([]interface{}, error) {
 	// TODO: Pagination. Respect opt.Start and opt.Length, if given.
 
 	project := project(repo)
 	chg, resp, err := s.cl.Changes.GetChangeDetail(fmt.Sprintf("%s~%d", project, id), &gerrit.ChangeOptions{
-		AdditionalFields: []string{"CURRENT_REVISION"},
+		AdditionalFields: []string{"ALL_REVISIONS"},
 	})
 	if err != nil {
 		if resp != nil && resp.StatusCode == http.StatusNotFound {
 			return nil, os.ErrNotExist
 		}
@@ -299,10 +299,11 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt *
 		User:      s.gerritUser(chg.Owner),
 		CreatedAt: chg.Created.Time,
 		Body:      commitMessageBody(commit.Message),
 		Editable:  false,
 	})
+	var mergedRevisionSHA string // Set to merged revision SHA when a change.MergedEvent event is encountered.
 	for idx, message := range chg.Messages {
 		if strings.HasPrefix(message.Tag, "autogenerated:") {
 		Outer:
 			switch message.Tag[len("autogenerated:"):] {
 			case "gerrit:merged":
@@ -312,10 +313,11 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt *
 					Payload: change.MergedEvent{
 						CommitID: chg.CurrentRevision,
 						RefName:  chg.Branch,
 					},
 				})
+				mergedRevisionSHA = chg.CurrentRevision
 			case "gerrit:newPatchSet":
 				// Parse a new patchset message, check if it has comments.
 				body, err := parsePSMessage(message.Message, message.RevisionNumber)
 				if err != nil {
 					return nil, err
@@ -427,10 +429,25 @@ func (s service) ListTimeline(ctx context.Context, repo string, id uint64, opt *
 			Body:      body,
 			Editable:  false,
 			Comments:  cs,
 		})
 	}
+	for sha, r := range chg.Revisions {
+		if r.Number == 1 || sha == mergedRevisionSHA {
+			// Skip first revision because it's equal to the change itself, and
+			// skip merged revision because it's equal to the change.MergedEvent.
+			continue
+		}
+		timeline = append(timeline, change.TimelineItem{
+			Actor:     s.gerritUser(r.Uploader),
+			CreatedAt: r.Created.Time,
+			Payload: change.CommitEvent{
+				SHA:     sha,
+				Subject: fmt.Sprintf("Patch Set %d", r.Number),
+			},
+		})
+	}
 	return timeline, nil
 }
 
 func parseMessage(m string) (labels string, body string, ok bool) {
 	// "Patch Set ".
timeline.go
@@ -74,10 +74,16 @@ type (
 	RenamedEvent struct {
 		From string
 		To   string
 	}
 
+	// CommitEvent is when a change gets a new commit.
+	CommitEvent struct {
+		SHA     string
+		Subject string
+	}
+
 	// LabeledEvent is when a change is labeled.
 	LabeledEvent struct {
 		Label issues.Label
 	}
 	// UnlabeledEvent is when a change is unlabeled.