diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2025-03-11 21:38:10 +0100 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-03-11 21:04:55 +0000 |
| commit | ee70e6dbc377b7957fe85c173da580f033ee93a3 (patch) | |
| tree | b5b30a5a6af477b1de5c4775f51e9efcef71d4ed | |
| parent | f9a86f79173ee73cd60ab4b2ff04d49764e53644 (diff) | |
syz-cluster: display and filter by Cc list
For each series, display the Cc'd email list and let users filter the
patch series list by those addresses.
| -rw-r--r-- | syz-cluster/controller/processor_test.go | 2 | ||||
| -rw-r--r-- | syz-cluster/dashboard/handler.go | 11 | ||||
| -rw-r--r-- | syz-cluster/dashboard/templates/index.html | 1 | ||||
| -rw-r--r-- | syz-cluster/dashboard/templates/series.html | 8 | ||||
| -rw-r--r-- | syz-cluster/pkg/db/series_repo.go | 14 | ||||
| -rw-r--r-- | syz-cluster/pkg/db/series_repo_test.go | 16 | ||||
| -rw-r--r-- | syz-cluster/pkg/db/session_repo_test.go | 2 |
7 files changed, 43 insertions, 11 deletions
diff --git a/syz-cluster/controller/processor_test.go b/syz-cluster/controller/processor_test.go index ff85ebec9..00f2c471b 100644 --- a/syz-cluster/controller/processor_test.go +++ b/syz-cluster/controller/processor_test.go @@ -85,7 +85,7 @@ func awaitFinishedSessions(t *testing.T, seriesRepo *db.SeriesRepository, wantFi for i := 0; i < int(deadline/interval); i++ { time.Sleep(interval) - list, err := seriesRepo.ListLatest(context.Background(), time.Time{}, 0) + list, err := seriesRepo.ListLatest(context.Background(), db.SeriesFilter{}, time.Time{}, 0) assert.NoError(t, err) withFinishedSeries := 0 for _, item := range list { diff --git a/syz-cluster/dashboard/handler.go b/syz-cluster/dashboard/handler.go index 2df0ed37f..c20d2225f 100644 --- a/syz-cluster/dashboard/handler.go +++ b/syz-cluster/dashboard/handler.go @@ -79,11 +79,16 @@ func (h *dashboardHandler) seriesList(w http.ResponseWriter, r *http.Request) er type MainPageData struct { // It's probably not the best idea to expose db entities here, // but so far redefining the entity would just duplicate the code. - List []*db.SeriesWithSession + List []*db.SeriesWithSession + Filter db.SeriesFilter + } + data := MainPageData{ + Filter: db.SeriesFilter{ + Cc: r.FormValue("cc"), + }, } - var data MainPageData var err error - data.List, err = h.seriesRepo.ListLatest(r.Context(), time.Time{}, 0) + data.List, err = h.seriesRepo.ListLatest(r.Context(), data.Filter, time.Time{}, 0) if err != nil { return fmt.Errorf("failed to query the list: %w", err) } diff --git a/syz-cluster/dashboard/templates/index.html b/syz-cluster/dashboard/templates/index.html index d3e60cfce..fb8fde0f3 100644 --- a/syz-cluster/dashboard/templates/index.html +++ b/syz-cluster/dashboard/templates/index.html @@ -1,4 +1,5 @@ {{define "content"}} + {{if .Filter.Cc}}<div class="alert alert-dark"><b>Filter: Cc={{.Filter.Cc}}</b></div>{{end}} <table class="table"> <thead class="thead-light"> <tr> diff --git a/syz-cluster/dashboard/templates/series.html b/syz-cluster/dashboard/templates/series.html index c160c0a71..5d7ba6693 100644 --- a/syz-cluster/dashboard/templates/series.html +++ b/syz-cluster/dashboard/templates/series.html @@ -55,6 +55,14 @@ <th>Version</th> <td>{{.Version}}</td> </tr> + <tr> + <th>Cc</th> + <td> + {{range .Cc}} + <a href="/?cc={{.}}">{{.}}</a> + {{end}} + </td> + </tr> </tbody> </table> diff --git a/syz-cluster/pkg/db/series_repo.go b/syz-cluster/pkg/db/series_repo.go index 018d32d8f..affe7f9cf 100644 --- a/syz-cluster/pkg/db/series_repo.go +++ b/syz-cluster/pkg/db/series_repo.go @@ -130,20 +130,28 @@ type SeriesWithSession struct { Session *Session } +type SeriesFilter struct { + Cc string +} + // ListLatest() returns the list of series ordered by the decreasing PublishedAt value. -func (repo *SeriesRepository) ListLatest(ctx context.Context, +func (repo *SeriesRepository) ListLatest(ctx context.Context, filter SeriesFilter, maxPublishedAt time.Time, limit int) ([]*SeriesWithSession, error) { ro := repo.client.ReadOnlyTransaction() defer ro.Close() stmt := spanner.Statement{ - SQL: "SELECT * FROM Series", + SQL: "SELECT * FROM Series WHERE 1=1", Params: map[string]interface{}{}, } if !maxPublishedAt.IsZero() { - stmt.SQL += " WHERE PublishedAt < @toTime" + stmt.SQL += " AND PublishedAt < @toTime" stmt.Params["toTime"] = maxPublishedAt } + if filter.Cc != "" { + stmt.SQL += " AND @cc IN UNNEST(Cc)" + stmt.Params["cc"] = filter.Cc + } stmt.SQL += " ORDER BY PublishedAt DESC" if limit > 0 { stmt.SQL += " LIMIT @limit" diff --git a/syz-cluster/pkg/db/series_repo_test.go b/syz-cluster/pkg/db/series_repo_test.go index c01049e5c..f9462dd90 100644 --- a/syz-cluster/pkg/db/series_repo_test.go +++ b/syz-cluster/pkg/db/series_repo_test.go @@ -58,16 +58,19 @@ func TestSeriesRepositoryList(t *testing.T) { ExtID: "series-3", Title: "Series 3", PublishedAt: time.Date(2020, time.January, 1, 3, 0, 0, 0, time.UTC), + Cc: []string{"a"}, }, { ExtID: "series-1", Title: "Series 1", PublishedAt: time.Date(2020, time.January, 1, 1, 0, 0, 0, time.UTC), + Cc: []string{"a", "b"}, }, { ExtID: "series-2", Title: "Series 2", PublishedAt: time.Date(2020, time.January, 1, 2, 0, 0, 0, time.UTC), + Cc: []string{"c"}, }, } { err := repo.Insert(ctx, series, func() ([]*Patch, error) { return nil, nil }) @@ -81,13 +84,13 @@ func TestSeriesRepositoryList(t *testing.T) { }) t.Run("all", func(t *testing.T) { - list, err := repo.ListLatest(ctx, time.Time{}, 0) + list, err := repo.ListLatest(ctx, SeriesFilter{}, time.Time{}, 0) assert.NoError(t, err) assert.Len(t, list, 3) }) t.Run("with_limit", func(t *testing.T) { - list, err := repo.ListLatest(ctx, time.Time{}, 2) + list, err := repo.ListLatest(ctx, SeriesFilter{}, time.Time{}, 2) assert.NoError(t, err) assert.Len(t, list, 2) assert.Equal(t, "Series 3", list[0].Series.Title) @@ -96,12 +99,19 @@ func TestSeriesRepositoryList(t *testing.T) { t.Run("with_from", func(t *testing.T) { // Skips the latest series. - list, err := repo.ListLatest(ctx, time.Date(2020, time.January, 1, 3, 0, 0, 0, time.UTC), 0) + list, err := repo.ListLatest(ctx, SeriesFilter{}, time.Date(2020, time.January, 1, 3, 0, 0, 0, time.UTC), 0) assert.NoError(t, err) assert.Len(t, list, 2) assert.Equal(t, "Series 2", list[0].Series.Title) assert.Equal(t, "Series 1", list[1].Series.Title) }) + + t.Run("filter_by_cc", func(t *testing.T) { + list, err := repo.ListLatest(ctx, + SeriesFilter{Cc: "a"}, time.Time{}, 0) + assert.NoError(t, err) + assert.Len(t, list, 2) + }) } func TestSeriesRepositoryUpdate(t *testing.T) { diff --git a/syz-cluster/pkg/db/session_repo_test.go b/syz-cluster/pkg/db/session_repo_test.go index 2a3b9bd69..c6f79f975 100644 --- a/syz-cluster/pkg/db/session_repo_test.go +++ b/syz-cluster/pkg/db/session_repo_test.go @@ -20,7 +20,7 @@ func TestSeriesInsertSession(t *testing.T) { assert.NoError(t, err) withSession := func(need int) { - list, err := seriesRepo.ListLatest(ctx, time.Time{}, 10) + list, err := seriesRepo.ListLatest(ctx, SeriesFilter{}, time.Time{}, 10) assert.NoError(t, err) var cnt int for _, item := range list { |
