Skip to content

Commit 120157c

Browse files
authored
feat: allow filter reports and scm based on a date range (#335)
1 parent 336ba0c commit 120157c

File tree

5 files changed

+109
-11
lines changed

5 files changed

+109
-11
lines changed

pkg/database/report.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,25 @@ func SearchReport(ctx context.Context, id string) (*model.PipelineReport, error)
7373
}
7474

7575
// SearchLatestReport searches the latest reports according some parameters.
76-
func SearchLatestReport(ctx context.Context, scmID, sourceID, conditionID, targetID string, options ReportSearchOptions, limit, page int) ([]SearchLatestReportData, int, error) {
76+
func SearchLatestReport(ctx context.Context, scmID, sourceID, conditionID, targetID string, options ReportSearchOptions, limit, page int, startTime, endTime string) ([]SearchLatestReportData, int, error) {
7777
queryString := ""
7878
var args []any
7979

8080
query := psql.Select(
8181
sm.From("pipelineReports"),
8282
sm.Columns("id", "data", "created_at", "updated_at"),
8383
sm.OrderBy(psql.Quote("updated_at")).Desc(),
84-
sm.Where(
85-
psql.Raw(fmt.Sprintf("updated_at > current_date - interval '%d day'", options.Days)),
86-
),
8784
)
8885

86+
if err := applyUpdatedAtRangeFilter(DateRangeFilterParams{
87+
Query: &query,
88+
DateRangeDays: options.Days,
89+
StartTime: startTime,
90+
EndTime: endTime,
91+
}); err != nil {
92+
return nil, 0, fmt.Errorf("applying updated_at range filter: %w", err)
93+
}
94+
8995
if sourceID != "" {
9096
// Ensure sourceID is a valid UUID
9197
if _, err := uuid.Parse(sourceID); err != nil {

pkg/database/scm.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ type SCMDataset struct {
145145
}
146146

147147
// GetSCMSummary returns a list of scms summary from the scm database table.
148-
func GetSCMSummary(ctx context.Context, scmRows []model.SCM, totalCount, monitoringDurationDays int) (*SCMDataset, error) {
148+
func GetSCMSummary(ctx context.Context, scmRows []model.SCM, totalCount, monitoringDurationDays int, startTime, endTime string) (*SCMDataset, error) {
149149

150150
dataset := SCMDataset{}
151151

@@ -167,12 +167,18 @@ func GetSCMSummary(ctx context.Context, scmRows []model.SCM, totalCount, monitor
167167
psql.Arg(fmt.Sprintf("{%s}", scmID)),
168168
),
169169
),
170-
sm.Where(
171-
psql.Raw(fmt.Sprintf("updated_at > current_date - interval '%d day'", monitoringDurationDays)),
172-
),
173170
sm.Columns("id", "data", "updated_at"),
174171
)
175172

173+
if err := applyUpdatedAtRangeFilter(DateRangeFilterParams{
174+
Query: &filteredSCMsQuery,
175+
DateRangeDays: monitoringDurationDays,
176+
StartTime: startTime,
177+
EndTime: endTime,
178+
}); err != nil {
179+
return nil, fmt.Errorf("applying updated_at range filter: %w", err)
180+
}
181+
176182
query := psql.Select(
177183
sm.Distinct(
178184
psql.Raw("data ->> 'ID'"),

pkg/database/time_utils.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package database
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
"github.com/stephenafamo/bob"
8+
"github.com/stephenafamo/bob/dialect/psql"
9+
"github.com/stephenafamo/bob/dialect/psql/dialect"
10+
"github.com/stephenafamo/bob/dialect/psql/sm"
11+
)
12+
13+
// DateRangeFilterParams holds parameters for applying a date range filter to a query.
14+
type DateRangeFilterParams struct {
15+
Query *bob.BaseQuery[*dialect.SelectQuery]
16+
DateRangeDays int
17+
StartTime string
18+
EndTime string
19+
}
20+
21+
// applyUpdatedAtRangeFilter applies a time range filter to the given query based on the provided
22+
// startTime and endTime strings in RFC3339 format. If both are empty and dateRangeDays is greater than zero,
23+
// it filters records updated within the last dateRangeDays days.
24+
func applyUpdatedAtRangeFilter(r DateRangeFilterParams) error {
25+
if r.StartTime == "" && r.EndTime == "" && r.DateRangeDays > 0 {
26+
start := time.Now().UTC().Add(-time.Duration(r.DateRangeDays) * 24 * time.Hour)
27+
r.Query.Apply(
28+
sm.Where(
29+
psql.Raw("updated_at > ?", start),
30+
),
31+
)
32+
return nil
33+
}
34+
35+
if r.StartTime == "" && r.EndTime == "" {
36+
return nil
37+
}
38+
39+
if r.StartTime == "" || r.EndTime == "" {
40+
return fmt.Errorf("both startTime and endTime must be provided for time range filtering")
41+
}
42+
43+
startT, err := time.Parse("2006-01-02 15:04:05Z07:00", r.StartTime)
44+
if err != nil {
45+
return fmt.Errorf("parsing startTime: %w", err)
46+
}
47+
endT, err := time.Parse("2006-01-02 15:04:05Z07:00", r.EndTime)
48+
if err != nil {
49+
return fmt.Errorf("parsing endTime: %w", err)
50+
}
51+
52+
startTimeUTC := startT.UTC()
53+
endTimeUTC := endT.UTC()
54+
55+
if startTimeUTC.After(endTimeUTC) {
56+
startTimeUTC, endTimeUTC = endTimeUTC, startTimeUTC
57+
}
58+
59+
r.Query.Apply(
60+
sm.Where(
61+
psql.Raw("updated_at >= ? AND updated_at < ?", startTimeUTC, endTimeUTC),
62+
),
63+
)
64+
65+
return nil
66+
}

pkg/server/report_handlers.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ func SearchPipelineReports(c *gin.Context) {
114114
// Page is the page number for pagination
115115
// This is optional and can be used to paginate the results
116116
Page int `json:"page"`
117+
// StartTime is the start time for the time range filter
118+
// This is optional and can be used to filter reports by a specific start time
119+
// Time format is RFC3339: 2006-01-02T15:04:05Z07:00
120+
StartTime string `json:"start_time"`
121+
// EndTime is the end time for the time range filter
122+
// This is optional and can be used to filter reports by a specific end time
123+
// Time format is RFC3339: 2006-01-02T15:04:05Z07:00
124+
EndTime string `json:"end_time"`
117125
}
118126

119127
queryParams := queryData{}
@@ -130,6 +138,7 @@ func SearchPipelineReports(c *gin.Context) {
130138
c, queryParams.ScmID, queryParams.SourceID, queryParams.ConditionID,
131139
queryParams.TargetID, database.ReportSearchOptions{Days: monitoringDurationDays},
132140
queryParams.Limit, queryParams.Page,
141+
queryParams.StartTime, queryParams.EndTime,
133142
)
134143
if err != nil {
135144
logrus.Errorf("searching for latest report: %s", err)
@@ -152,12 +161,18 @@ func SearchPipelineReports(c *gin.Context) {
152161
// @Param scmid query string false "SCM ID"
153162
// @Param limit query string false "Limit the number of reports returned, default is 100"
154163
// @Param page query string false "Page number for pagination, default is 1"
164+
// @Param start_time query string false "Start time for filtering reports (RFC3339 format)"
165+
// @Param end_time query string false "End time for filtering reports (RFC3339 format)"
166+
// @Accept json
167+
// @Produce json
155168
// @Success 200 {object} GetPipelineReportsResponse
156169
// @Failure 500 {object} DefaultResponseModel
157170
// @Router /api/pipeline/reports [get]
158171
func ListPipelineReports(c *gin.Context) {
159172
queryParams := c.Request.URL.Query()
160173
scmID := queryParams.Get("scmid")
174+
startTime := queryParams.Get("start_time")
175+
endTime := queryParams.Get("end_time")
161176

162177
limit, page, err := getPaginationParamFromURLQuery(c)
163178
if err != nil {
@@ -173,6 +188,7 @@ func ListPipelineReports(c *gin.Context) {
173188
database.ReportSearchOptions{Days: monitoringDurationDays},
174189
limit,
175190
page,
191+
startTime, endTime,
176192
)
177193

178194
if err != nil {

pkg/server/scmdb_handlers.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type ListSCMsResponse struct {
2828
// @Param summary query bool false "Return a summary of the SCMs"
2929
// @Param limit query string false "Limit the number of reports returned, default is 100"
3030
// @Param page query string false "Page number for pagination, default is 1"
31+
// @Param start_time query string false "Start time for filtering SCMs (RFC3339 format)"
32+
// @Param end_time query string false "End time for filtering SCMs (RFC3339 format)"
3133
// @Success 200 {object} DefaultResponseModel
3234
// @Failure 500 {object} DefaultResponseModel
3335
// @Router /api/pipeline/scms [get]
@@ -36,6 +38,8 @@ func ListSCMs(c *gin.Context) {
3638
url := c.Request.URL.Query().Get("url")
3739
branch := c.Request.URL.Query().Get("branch")
3840
summary := c.Request.URL.Query().Get("summary")
41+
startTime := c.Request.URL.Query().Get("start_time")
42+
endTime := c.Request.URL.Query().Get("end_time")
3943

4044
limit, page, err := getPaginationParamFromURLQuery(c)
4145
if err != nil {
@@ -57,7 +61,7 @@ func ListSCMs(c *gin.Context) {
5761
}
5862

5963
if strings.ToUpper(summary) == "TRUE" {
60-
findSCMSummary(c, rows, totalCount)
64+
findSCMSummary(c, rows, totalCount, startTime, endTime)
6165
return
6266
}
6367

@@ -74,11 +78,11 @@ type FindSCMSummaryResponse struct {
7478
}
7579

7680
// findSCMSummary returns a summary of all git repositories detected.
77-
func findSCMSummary(c *gin.Context, scmRows []model.SCM, totalCount int) {
81+
func findSCMSummary(c *gin.Context, scmRows []model.SCM, totalCount int, startTime, endTime string) {
7882

7983
var data map[string]database.SCMBranchDataset
8084

81-
dataset, err := database.GetSCMSummary(c, scmRows, totalCount, monitoringDurationDays) // Assuming 30 days as the default monitoring duration
85+
dataset, err := database.GetSCMSummary(c, scmRows, totalCount, monitoringDurationDays, startTime, endTime) // Assuming 30 days as the default monitoring duration
8286
if err != nil {
8387
logrus.Errorf("getting scm summary failed: %s", err)
8488
c.JSON(http.StatusInternalServerError, DefaultResponseModel{

0 commit comments

Comments
 (0)