Commit e0ae4017ac
Verified · cmc
Layout: unified · split
internal/control/feedline.go +19 −5
| @@ -21,7 +21,10 @@ type FeedLine struct { | ||
| 21 | 21 | WhenT time.Time // parsed from When, for ago/whenT rendering |
| 22 | 22 | State string // a build run's combined status; empty for anything else |
| 23 | 23 | Jobs []string // job names folded into a build run |
| 24 | sha string // the commit a build event fired on, for fold-matching | |
| 24 | // Extra is trailing detail shown after the ref: the label list on a | |
| 25 | // labelled event, empty for everything else. | |
| 26 | Extra string | |
| 27 | sha string // the commit a build event fired on, for fold-matching | |
| 25 | 28 | } |
| 26 | 29 | |
| 27 | 30 | // FeedLines turns stored events into readable lines. An unknown kind |
| @@ -41,10 +44,11 @@ func FeedLines(events []store.FeedEvent) []FeedLine { | ||
| 41 | 44 | statuses := make([][]string, 0, len(events)) |
| 42 | 45 | for _, e := range events { |
| 43 | 46 | var d struct { |
| 44 | Number int64 `json:"number"` | |
| 45 | Job string `json:"job"` | |
| 46 | Tag string `json:"tag"` | |
| 47 | SHA string `json:"sha"` | |
| 47 | Number int64 `json:"number"` | |
| 48 | Job string `json:"job"` | |
| 49 | Tag string `json:"tag"` | |
| 50 | SHA string `json:"sha"` | |
| 51 | Labels []string `json:"labels"` | |
| 48 | 52 | } |
| 49 | 53 | json.Unmarshal([]byte(e.Data), &d) |
| 50 | 54 | kind, rest, _ := strings.Cut(e.Kind, ".") |
| @@ -72,9 +76,15 @@ func FeedLines(events []store.FeedEvent) []FeedLine { | ||
| 72 | 76 | case "issue": |
| 73 | 77 | l.Verb, l.Ref = issueVerb(rest), fmt.Sprintf("#%d", d.Number) |
| 74 | 78 | l.URL = fmt.Sprintf("/%s/issues/%d", e.RepoPath, d.Number) |
| 79 | if rest == "labeled" { | |
| 80 | l.Extra = strings.Join(d.Labels, ", ") | |
| 81 | } | |
| 75 | 82 | case "mr": |
| 76 | 83 | l.Verb, l.Ref = mrVerb(rest), fmt.Sprintf("!%d", d.Number) |
| 77 | 84 | l.URL = fmt.Sprintf("/%s/mrs/%d", e.RepoPath, d.Number) |
| 85 | if rest == "labeled" { | |
| 86 | l.Extra = strings.Join(d.Labels, ", ") | |
| 87 | } | |
| 78 | 88 | case "build": |
| 79 | 89 | l.Verb, l.Ref = "build "+rest, d.Job |
| 80 | 90 | l.URL = fmt.Sprintf("/%s/builds/%d", e.RepoPath, d.Number) |
| @@ -148,6 +158,8 @@ func issueVerb(s string) string { | ||
| 148 | 158 | return "reopened issue" |
| 149 | 159 | case "commented": |
| 150 | 160 | return "commented on" |
| 161 | case "labeled": | |
| 162 | return "labelled" | |
| 151 | 163 | } |
| 152 | 164 | return "issue " + s |
| 153 | 165 | } |
| @@ -162,6 +174,8 @@ func mrVerb(s string) string { | ||
| 162 | 174 | return "commented on" |
| 163 | 175 | case "closed": |
| 164 | 176 | return "closed merge request" |
| 177 | case "labeled": | |
| 178 | return "labelled" | |
| 165 | 179 | } |
| 166 | 180 | return "merge request " + s |
| 167 | 181 | } |
internal/control/feedline_test.go +29
| @@ -158,6 +158,35 @@ func TestFeedLinesParsesWhenT(t *testing.T) { | ||
| 158 | 158 | } |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | // A labelled issue names which labels were added, not just "issue | |
| 162 | // labeled": the sentence is otherwise silent about what changed. | |
| 163 | func TestFeedLinesNamesTheLabelsOnALabelledIssue(t *testing.T) { | |
| 164 | events := []store.FeedEvent{ | |
| 165 | {RepoPath: "krz/gitbay", Actor: "cmc", Kind: "issue.labeled", | |
| 166 | Data: `{"number":262,"labels":["ops","security"]}`}, | |
| 167 | } | |
| 168 | lines := FeedLines(events) | |
| 169 | if len(lines) != 1 { | |
| 170 | t.Fatalf("FeedLines returned %d lines, want 1", len(lines)) | |
| 171 | } | |
| 172 | l := lines[0] | |
| 173 | if l.Verb != "labelled" || l.Ref != "#262" || l.Extra != "ops, security" { | |
| 174 | t.Errorf("got %+v", l) | |
| 175 | } | |
| 176 | } | |
| 177 | ||
| 178 | // Same for a labelled merge request. | |
| 179 | func TestFeedLinesNamesTheLabelsOnALabelledMR(t *testing.T) { | |
| 180 | events := []store.FeedEvent{ | |
| 181 | {RepoPath: "krz/gitbay", Actor: "cmc", Kind: "mr.labeled", | |
| 182 | Data: `{"number":471,"labels":["review"]}`}, | |
| 183 | } | |
| 184 | lines := FeedLines(events) | |
| 185 | if len(lines) != 1 || lines[0].Verb != "labelled" || lines[0].Ref != "!471" || lines[0].Extra != "review" { | |
| 186 | t.Errorf("got %+v", lines) | |
| 187 | } | |
| 188 | } | |
| 189 | ||
| 161 | 190 | // A scheduled job firing daily on an unchanged tip is a separate event |
| 162 | 191 | // each tick, not another job of one run (#240): a repeated job name starts |
| 163 | 192 | // a new line, so three days read as three lines rather than "ran 3 jobs on" |
internal/web/templates/dashboard.html +1 −1
| @@ -46,7 +46,7 @@ | ||
| 46 | 46 | |
| 47 | 47 | <aside class="feedcol" aria-label="Recent activity"> |
| 48 | 48 | <h2 class="colhead">Recent activity</h2> |
| 49 | {{range .Feed}}<p class="feedline"><a href="/{{.Actor}}">{{.Actor}}</a> {{.Verb}} <a href="{{.URL}}"{{if .Jobs}} title="{{join .Jobs ", "}}"{{end}}>{{.Ref}}</a><br><span class="none">{{.Repo}} · <span title="{{whenT .WhenT}}">{{ago .WhenT}}</span></span></p> | |
| 49 | {{range .Feed}}<p class="feedline"><a href="/{{.Actor}}">{{.Actor}}</a> {{.Verb}} <a href="{{.URL}}"{{if .Jobs}} title="{{join .Jobs ", "}}"{{end}}>{{.Ref}}</a>{{if .Extra}} {{.Extra}}{{end}}<br><span class="none">{{.Repo}} · <span title="{{whenT .WhenT}}">{{ago .WhenT}}</span></span></p> | |
| 50 | 50 | {{else}}<p class="none">No activity yet</p>{{end}} |
| 51 | 51 | </aside> |
| 52 | 52 | |
internal/web/templates/owner.html +1 −1
| @@ -36,7 +36,7 @@ | ||
| 36 | 36 | that goes back. */}} |
| 37 | 37 | {{if .Log}}<h3 class="logsub">recent</h3> |
| 38 | 38 | <div class="ownerlog"> |
| 39 | {{range .Log}}<p class="feedline"><a href="/{{.Actor}}">{{.Actor}}</a> {{.Verb}} <a href="{{.URL}}"{{if .Jobs}} title="{{join .Jobs ", "}}"{{end}}>{{.Ref}}</a><br><span class="none">{{.Repo}} · <span title="{{whenT .WhenT}}">{{ago .WhenT}}</span></span></p> | |
| 39 | {{range .Log}}<p class="feedline"><a href="/{{.Actor}}">{{.Actor}}</a> {{.Verb}} <a href="{{.URL}}"{{if .Jobs}} title="{{join .Jobs ", "}}"{{end}}>{{.Ref}}</a>{{if .Extra}} {{.Extra}}{{end}}<br><span class="none">{{.Repo}} · <span title="{{whenT .WhenT}}">{{ago .WhenT}}</span></span></p> | |
| 40 | 40 | {{end}} |
| 41 | 41 | </div> |
| 42 | 42 | <p class="meta"><a href="{{.Feed}}">activity feed</a></p> |