diff --git a/velodrome/fetcher/client.go b/velodrome/fetcher/client.go index ae2385ab0934..e2917c5f3ebf 100644 --- a/velodrome/fetcher/client.go +++ b/velodrome/fetcher/client.go @@ -56,6 +56,7 @@ func (client *Client) AddFlags(cmd *cobra.Command) { "The github project to scan") } +// CheckFlags looks for organization and project flags to configure the client func (client *Client) CheckFlags() error { if client.Org == "" { return fmt.Errorf("organization flag must be set") @@ -125,6 +126,7 @@ type ClientInterface interface { FetchPullComments(issueID int, last time.Time, c chan *github.PullRequestComment) } +// RepositoryName returns github's repository name in the form of org/project func (client *Client) RepositoryName() string { return fmt.Sprintf("%s/%s", client.Org, client.Project) } diff --git a/velodrome/fetcher/conversion.go b/velodrome/fetcher/conversion.go index c7937e5f717f..e88769c51e56 100644 --- a/velodrome/fetcher/conversion.go +++ b/velodrome/fetcher/conversion.go @@ -103,7 +103,7 @@ func NewIssueEvent(gIssueEvent *github.IssueEvent, issueID int, repository strin Label: label, Event: *gIssueEvent.Event, EventCreatedAt: *gIssueEvent.CreatedAt, - IssueId: strconv.Itoa(issueID), + IssueID: strconv.Itoa(issueID), Assignee: assignee, Actor: actor, Repository: strings.ToLower(repository), @@ -111,7 +111,7 @@ func NewIssueEvent(gIssueEvent *github.IssueEvent, issueID int, repository strin } // newLabels creates a new Label for each label in the issue -func newLabels(issueId int, gLabels []github.Label, repository string) ([]sql.Label, error) { +func newLabels(issueID int, gLabels []github.Label, repository string) ([]sql.Label, error) { labels := []sql.Label{} repository = strings.ToLower(repository) @@ -120,7 +120,7 @@ func newLabels(issueId int, gLabels []github.Label, repository string) ([]sql.La return nil, fmt.Errorf("Label is missing name field") } labels = append(labels, sql.Label{ - IssueID: strconv.Itoa(issueId), + IssueID: strconv.Itoa(issueID), Name: *label.Name, Repository: repository, }) @@ -130,7 +130,7 @@ func newLabels(issueId int, gLabels []github.Label, repository string) ([]sql.La } // newAssignees creates a new Label for each label in the issue -func newAssignees(issueId int, gAssignees []*github.User, repository string) ([]sql.Assignee, error) { +func newAssignees(issueID int, gAssignees []*github.User, repository string) ([]sql.Assignee, error) { assignees := []sql.Assignee{} repository = strings.ToLower(repository) @@ -139,7 +139,7 @@ func newAssignees(issueId int, gAssignees []*github.User, repository string) ([] return nil, fmt.Errorf("Assignee is missing Login field") } assignees = append(assignees, sql.Assignee{ - IssueID: strconv.Itoa(issueId), + IssueID: strconv.Itoa(issueID), Name: *assignee.Login, Repository: repository, }) @@ -149,7 +149,7 @@ func newAssignees(issueId int, gAssignees []*github.User, repository string) ([] } // NewIssueComment creates a Comment from a github.IssueComment -func NewIssueComment(issueId int, gComment *github.IssueComment, repository string) (*sql.Comment, error) { +func NewIssueComment(issueID int, gComment *github.IssueComment, repository string) (*sql.Comment, error) { if gComment.ID == nil || gComment.Body == nil || gComment.CreatedAt == nil || @@ -164,7 +164,7 @@ func NewIssueComment(issueId int, gComment *github.IssueComment, repository stri return &sql.Comment{ ID: strconv.Itoa(*gComment.ID), - IssueID: strconv.Itoa(issueId), + IssueID: strconv.Itoa(issueID), Body: *gComment.Body, User: login, CommentCreatedAt: *gComment.CreatedAt, @@ -175,7 +175,7 @@ func NewIssueComment(issueId int, gComment *github.IssueComment, repository stri } // NewPullComment creates a Comment from a github.PullRequestComment -func NewPullComment(issueId int, gComment *github.PullRequestComment, repository string) (*sql.Comment, error) { +func NewPullComment(issueID int, gComment *github.PullRequestComment, repository string) (*sql.Comment, error) { if gComment.ID == nil || gComment.Body == nil || gComment.CreatedAt == nil || @@ -189,7 +189,7 @@ func NewPullComment(issueId int, gComment *github.PullRequestComment, repository } return &sql.Comment{ ID: strconv.Itoa(*gComment.ID), - IssueID: strconv.Itoa(issueId), + IssueID: strconv.Itoa(issueID), Body: *gComment.Body, User: login, CommentCreatedAt: *gComment.CreatedAt, diff --git a/velodrome/fetcher/conversion_test.go b/velodrome/fetcher/conversion_test.go index a52925e4ab8a..74b02fbd085d 100644 --- a/velodrome/fetcher/conversion_test.go +++ b/velodrome/fetcher/conversion_test.go @@ -28,7 +28,7 @@ import ( ) func makeIssue(number int, - title, body, state, user, prUrl, repository string, + title, body, state, user, prURL, repository string, comments int, isPullRequest bool, createdAt, updatedAt, closedAt time.Time) *sql.Issue { @@ -54,7 +54,7 @@ func makeIssue(number int, } func makeGithubIssue(number int, - title, body, state, user, prUrl string, + title, body, state, user, prURL string, comments int, isPullRequest bool, createdAt, updatedAt, closedAt time.Time) *github.Issue { @@ -64,8 +64,8 @@ func makeGithubIssue(number int, pBody = &body } var pullRequest *github.PullRequestLinks - if prUrl != "" { - pullRequest = &github.PullRequestLinks{URL: &prUrl} + if prURL != "" { + pullRequest = &github.PullRequestLinks{URL: &prURL} } gUser := &github.User{Login: &user} var pClosedAt *time.Time @@ -142,7 +142,7 @@ func TestNewIssue(t *testing.T) { } func makeIssueEvent( - eventId, issueId int, + eventID, issueID int, label, event, assignee, actor, repository string, createdAt time.Time) *sql.IssueEvent { @@ -158,11 +158,11 @@ func makeIssueEvent( } return &sql.IssueEvent{ - ID: strconv.Itoa(eventId), + ID: strconv.Itoa(eventID), Label: pLabel, Event: event, EventCreatedAt: createdAt, - IssueId: strconv.Itoa(issueId), + IssueID: strconv.Itoa(issueID), Assignee: pAssignee, Actor: pActor, Repository: repository, @@ -170,7 +170,7 @@ func makeIssueEvent( } func makeGithubIssueEvent( - eventId int, + eventID int, label, event, assignee, actor string, createdAt time.Time) *github.IssueEvent { @@ -189,7 +189,7 @@ func makeGithubIssueEvent( } return &github.IssueEvent{ - ID: &eventId, + ID: &eventID, Label: gLabel, Event: &event, CreatedAt: &createdAt, @@ -244,7 +244,7 @@ func createLabel(name string) github.Label { func TestNewLabels(t *testing.T) { tests := []struct { gLabels []github.Label - issueId int + issueID int expectedLabels []sql.Label }{ // Empty list gives empty list @@ -266,7 +266,7 @@ func TestNewLabels(t *testing.T) { } for _, test := range tests { - actualLabels, _ := newLabels(test.issueId, test.gLabels, "FULL/REPO") + actualLabels, _ := newLabels(test.issueID, test.gLabels, "FULL/REPO") if !reflect.DeepEqual(actualLabels, test.expectedLabels) { t.Error("Actual: ", actualLabels, "doesn't match expected: ", test.expectedLabels) @@ -302,10 +302,10 @@ func makeGithubPullComment(id int, body, login string, createdAt, updatedAt time } } -func makeComment(issueId, Id int, body, login, repository string, createdAt, updatedAt time.Time, pullRequest bool) *sql.Comment { +func makeComment(issueID, iD int, body, login, repository string, createdAt, updatedAt time.Time, pullRequest bool) *sql.Comment { return &sql.Comment{ - ID: strconv.Itoa(Id), - IssueID: strconv.Itoa(issueId), + ID: strconv.Itoa(iD), + IssueID: strconv.Itoa(issueID), Body: body, User: login, CommentCreatedAt: createdAt, @@ -318,14 +318,14 @@ func makeComment(issueId, Id int, body, login, repository string, createdAt, upd func TestNewIssueComment(t *testing.T) { tests := []struct { gComment *github.IssueComment - issueId int + issueID int expectedComment *sql.Comment }{ { gComment: makeGithubIssueComment(1, "Body", "Login", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), time.Date(2001, time.January, 1, 19, 30, 0, 0, time.UTC)), - issueId: 12, + issueID: 12, expectedComment: makeComment(12, 1, "Body", "Login", "full/repo", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), time.Date(2001, time.January, 1, 19, 30, 0, 0, time.UTC), false), @@ -334,7 +334,7 @@ func TestNewIssueComment(t *testing.T) { gComment: makeGithubIssueComment(1, "Body", "", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), time.Date(2001, time.January, 1, 19, 30, 0, 0, time.UTC)), - issueId: 12, + issueID: 12, expectedComment: makeComment(12, 1, "Body", "", "full/repo", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), time.Date(2001, time.January, 1, 19, 30, 0, 0, time.UTC), false), @@ -342,7 +342,7 @@ func TestNewIssueComment(t *testing.T) { } for _, test := range tests { - actualComment, _ := NewIssueComment(test.issueId, test.gComment, "FULL/REPO") + actualComment, _ := NewIssueComment(test.issueID, test.gComment, "FULL/REPO") if !reflect.DeepEqual(actualComment, test.expectedComment) { t.Error("Actual: ", actualComment, "doesn't match expected: ", test.expectedComment) @@ -353,7 +353,7 @@ func TestNewIssueComment(t *testing.T) { func TestNewPullComment(t *testing.T) { tests := []struct { gComment *github.PullRequestComment - issueId int + issueID int repository string expectedComment *sql.Comment }{ @@ -361,7 +361,7 @@ func TestNewPullComment(t *testing.T) { gComment: makeGithubPullComment(1, "Body", "Login", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), time.Date(2001, time.January, 1, 19, 30, 0, 0, time.UTC)), - issueId: 12, + issueID: 12, repository: "FULL/REPO", expectedComment: makeComment(12, 1, "Body", "Login", "full/repo", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), @@ -371,7 +371,7 @@ func TestNewPullComment(t *testing.T) { gComment: makeGithubPullComment(1, "Body", "", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), time.Date(2001, time.January, 1, 19, 30, 0, 0, time.UTC)), - issueId: 12, + issueID: 12, repository: "FULL/REPO", expectedComment: makeComment(12, 1, "Body", "", "full/repo", time.Date(2000, time.January, 1, 19, 30, 0, 0, time.UTC), @@ -380,7 +380,7 @@ func TestNewPullComment(t *testing.T) { } for _, test := range tests { - actualComment, _ := NewPullComment(test.issueId, test.gComment, test.repository) + actualComment, _ := NewPullComment(test.issueID, test.gComment, test.repository) if !reflect.DeepEqual(actualComment, test.expectedComment) { t.Error("Actual: ", actualComment, "doesn't match expected: ", test.expectedComment) diff --git a/velodrome/fetcher/issue-events.go b/velodrome/fetcher/issue-events.go index c5b93b8a83e0..0028ad9fb463 100644 --- a/velodrome/fetcher/issue-events.go +++ b/velodrome/fetcher/issue-events.go @@ -30,7 +30,7 @@ func findLatestEvent(issueID int, db *gorm.DB, repository string) (*int, error) query := db. Select("id, event_created_at"). - Where(&sql.IssueEvent{IssueId: strconv.Itoa(issueID)}). + Where(&sql.IssueEvent{IssueID: strconv.Itoa(issueID)}). Where("repository = ?", repository). Order("event_created_at desc"). First(&latestEvent) diff --git a/velodrome/fetcher/issue-events_test.go b/velodrome/fetcher/issue-events_test.go index 662486865ddb..d0b619735715 100644 --- a/velodrome/fetcher/issue-events_test.go +++ b/velodrome/fetcher/issue-events_test.go @@ -45,8 +45,8 @@ func TestFindLatestUpdate(t *testing.T) { }, { []sql.IssueEvent{ - {ID: "2", IssueId: "7", EventCreatedAt: time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, - {ID: "7", IssueId: "7", EventCreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, + {ID: "2", IssueID: "7", EventCreatedAt: time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, + {ID: "7", IssueID: "7", EventCreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, }, 0, "TWO", @@ -54,9 +54,9 @@ func TestFindLatestUpdate(t *testing.T) { }, { []sql.IssueEvent{ - {ID: "2", IssueId: "7", EventCreatedAt: time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, - {ID: "7", IssueId: "2", EventCreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, - {ID: "1", IssueId: "7", EventCreatedAt: time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "TWO"}, + {ID: "2", IssueID: "7", EventCreatedAt: time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, + {ID: "7", IssueID: "2", EventCreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, + {ID: "1", IssueID: "7", EventCreatedAt: time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "TWO"}, }, 2, "ONE", @@ -64,9 +64,9 @@ func TestFindLatestUpdate(t *testing.T) { }, { []sql.IssueEvent{ - {ID: "2", IssueId: "7", EventCreatedAt: time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, - {ID: "7", IssueId: "7", EventCreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, - {ID: "1", IssueId: "7", EventCreatedAt: time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "TWO"}, + {ID: "2", IssueID: "7", EventCreatedAt: time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, + {ID: "7", IssueID: "7", EventCreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "ONE"}, + {ID: "1", IssueID: "7", EventCreatedAt: time.Date(1998, 1, 1, 0, 0, 0, 0, time.UTC), Repository: "TWO"}, }, 1, "TWO", diff --git a/velodrome/sql/model.go b/velodrome/sql/model.go index 3186fbc68cde..f2459f11e84e 100644 --- a/velodrome/sql/model.go +++ b/velodrome/sql/model.go @@ -59,7 +59,7 @@ type IssueEvent struct { Label *string Event string EventCreatedAt time.Time `gorm:"index:repo_created"` - IssueId string + IssueID string Assignee *string Actor *string } diff --git a/velodrome/token-counter/token-counter.go b/velodrome/token-counter/token-counter.go index f914dffa8b04..b4f34d478dca 100644 --- a/velodrome/token-counter/token-counter.go +++ b/velodrome/token-counter/token-counter.go @@ -68,7 +68,7 @@ func GetUsername(client *github.Client) (string, error) { return "", err } if user.Login == nil { - return "", errors.New("Users.Get(\"\") returned empty login.") + return "", errors.New("Users.Get(\"\") returned empty login") } return *user.Login, nil diff --git a/velodrome/transform/plugins/author_filter_wrapper.go b/velodrome/transform/plugins/author_filter_wrapper.go index 140fcd49f28a..50c78ae097dc 100644 --- a/velodrome/transform/plugins/author_filter_wrapper.go +++ b/velodrome/transform/plugins/author_filter_wrapper.go @@ -21,6 +21,7 @@ import ( "k8s.io/test-infra/velodrome/sql" ) +// AuthorFilterPluginWrapper ignore comments and events from some authors type AuthorFilterPluginWrapper struct { ignoredAuthors []string @@ -29,12 +30,14 @@ type AuthorFilterPluginWrapper struct { var _ Plugin = &AuthorFilterPluginWrapper{} +// NewAuthorFilterPluginWrapper is the constructor for AuthorFilterPluginWrapper func NewAuthorFilterPluginWrapper(plugin Plugin) *AuthorFilterPluginWrapper { return &AuthorFilterPluginWrapper{ plugin: plugin, } } +// AddFlags adds "ignore-authors" to the command help func (a *AuthorFilterPluginWrapper) AddFlags(cmd *cobra.Command) { cmd.Flags().StringSliceVar(&a.ignoredAuthors, "ignore-authors", []string{}, "Name of people to ignore") } @@ -48,6 +51,7 @@ func (a *AuthorFilterPluginWrapper) match(author string) bool { return false } +// ReceiveIssue calls plugin.ReceiveIssue() if the author is not filtered func (a *AuthorFilterPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { if a.match(issue.User) { return nil @@ -55,6 +59,7 @@ func (a *AuthorFilterPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { return a.plugin.ReceiveIssue(issue) } +// ReceiveIssueEvent calls plugin.ReceiveIssueEvent() if the author is not filtered func (a *AuthorFilterPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Point { if event.Actor != nil && a.match(*event.Actor) { return nil @@ -62,6 +67,7 @@ func (a *AuthorFilterPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Po return a.plugin.ReceiveIssueEvent(event) } +// ReceiveComment calls plugin.ReceiveComment() if the author is not filtered func (a *AuthorFilterPluginWrapper) ReceiveComment(comment sql.Comment) []Point { if a.match(comment.User) { return nil diff --git a/velodrome/transform/plugins/author_logger_wrapper.go b/velodrome/transform/plugins/author_logger_wrapper.go index 7b798991a470..1ed5b7e14069 100644 --- a/velodrome/transform/plugins/author_logger_wrapper.go +++ b/velodrome/transform/plugins/author_logger_wrapper.go @@ -21,7 +21,7 @@ import ( "k8s.io/test-infra/velodrome/sql" ) -// Logs the author on all the Points returned. This is enabled by command-line. +// AuthorLoggerPluginWrapper logs the author on all the Points returned. This is enabled by command-line. type AuthorLoggerPluginWrapper struct { plugin Plugin enabled bool @@ -29,16 +29,19 @@ type AuthorLoggerPluginWrapper struct { var _ Plugin = &AuthorLoggerPluginWrapper{} +// NewAuthorLoggerPluginWrapper is the constructor for AuthorLoggerPluginWrapper func NewAuthorLoggerPluginWrapper(plugin Plugin) *AuthorLoggerPluginWrapper { return &AuthorLoggerPluginWrapper{ plugin: plugin, } } +// AddFlags adds "log-authors" to the command help func (a *AuthorLoggerPluginWrapper) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&a.enabled, "log-author", false, "Log the author for each metric") } +// ReceiveIssue is a wrapper on plugin.ReceiveIssue() logging the author func (a *AuthorLoggerPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { points := a.plugin.ReceiveIssue(issue) if a.enabled { @@ -53,6 +56,7 @@ func (a *AuthorLoggerPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { return points } +// ReceiveIssueEvent is a wrapper on plugin.ReceiveIssueEvent() logging the author func (a *AuthorLoggerPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Point { points := a.plugin.ReceiveIssueEvent(event) @@ -70,6 +74,7 @@ func (a *AuthorLoggerPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Po return points } +// ReceiveComment is a wrapper on plugin.ReceiveComment() logging the author func (a *AuthorLoggerPluginWrapper) ReceiveComment(comment sql.Comment) []Point { points := a.plugin.ReceiveComment(comment) diff --git a/velodrome/transform/plugins/bundle.go b/velodrome/transform/plugins/bundle.go index 5dcb3c65a96a..1504762ba298 100644 --- a/velodrome/transform/plugins/bundle.go +++ b/velodrome/transform/plugins/bundle.go @@ -43,7 +43,7 @@ type BundledStates struct { states map[string]State } -// NewBundledStates creates a new BundledStates +// NewBundledStates is the constructor for BundledStates func NewBundledStates(description string) BundledStates { return BundledStates{ description: description, @@ -88,7 +88,7 @@ func (b BundledStates) Total(t time.Time) (count int, sum int64) { // Percentile returns given percentile for age of all active states at time t func (b BundledStates) Percentile(t time.Time, percentile int) time.Duration { if percentile > 100 || percentile <= 0 { - panic(fmt.Errorf("Percentile %d is out of scope.", percentile)) + panic(fmt.Errorf("percentile %d is out of scope", percentile)) } ages := []time.Duration{} diff --git a/velodrome/transform/plugins/bundle_test.go b/velodrome/transform/plugins/bundle_test.go index 04c681b7e537..e225209c93c9 100644 --- a/velodrome/transform/plugins/bundle_test.go +++ b/velodrome/transform/plugins/bundle_test.go @@ -24,8 +24,8 @@ import ( func TestBundle(t *testing.T) { bundle := NewBundledStates("merged") - if got_count, got_sum := bundle.Total(time.Unix(0, 10)); got_count != 0 || got_sum != 0 { - t.Errorf("bundle.Total(time.Unix(0, 10)) = (%d, %d), want (0, 0)", got_count, got_sum) + if gotCount, gotSum := bundle.Total(time.Unix(0, 10)); gotCount != 0 || gotSum != 0 { + t.Errorf("bundle.Total(time.Unix(0, 10)) = (%d, %d), want (0, 0)", gotCount, gotSum) } if got := bundle.Percentile(time.Unix(0, 10), 50); got != 0 { t.Errorf("bundle.Percentile(time.Unix(0, 10), 50) = %s, want 0", got) @@ -39,11 +39,11 @@ func TestBundle(t *testing.T) { } // we have 50 triggered state - want_count := 50 + wantCount := 50 // Total age at time 5000 is: (50*51)/2 - want_sum := int64(1275) - if got_count, got_sum := bundle.Total(time.Unix(50*60, 0)); got_count != want_count || got_sum != want_sum { - t.Errorf("bundle.Total() = (%d, %d), want (%d, %d)", got_count, got_sum, want_count, want_sum) + wantSum := int64(1275) + if gotCount, gotSum := bundle.Total(time.Unix(50*60, 0)); gotCount != wantCount || gotSum != wantSum { + t.Errorf("bundle.Total() = (%d, %d), want (%d, %d)", gotCount, gotSum, wantCount, wantSum) } // The issue in the middle has been opened for 25 minutes want := 25 * time.Minute diff --git a/velodrome/transform/plugins/comment_counter.go b/velodrome/transform/plugins/comment_counter.go index 0702da948e91..a6c4d02effeb 100644 --- a/velodrome/transform/plugins/comment_counter.go +++ b/velodrome/transform/plugins/comment_counter.go @@ -23,6 +23,7 @@ import ( "k8s.io/test-infra/velodrome/sql" ) +// CommentCounterPlugin counts comments type CommentCounterPlugin struct { matcher []*regexp.Regexp pattern []string @@ -30,10 +31,12 @@ type CommentCounterPlugin struct { var _ Plugin = &CommentCounterPlugin{} +// AddFlags adds "comments" to the command help func (c *CommentCounterPlugin) AddFlags(cmd *cobra.Command) { cmd.Flags().StringSliceVar(&c.pattern, "comments", []string{}, "Regexps to match comments") } +// CheckFlags looks for comments matching regexes func (c *CommentCounterPlugin) CheckFlags() error { for _, pattern := range c.pattern { matcher, err := regexp.Compile(pattern) @@ -45,14 +48,17 @@ func (c *CommentCounterPlugin) CheckFlags() error { return nil } +// ReceiveIssue is needed to implement a Plugin func (CommentCounterPlugin) ReceiveIssue(issue sql.Issue) []Point { return nil } +// ReceiveIssueEvent is needed to implement a Plugin func (CommentCounterPlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point { return nil } +// ReceiveComment adds matching comments to InfluxDB func (c *CommentCounterPlugin) ReceiveComment(comment sql.Comment) []Point { points := []Point{} for _, matcher := range c.matcher { diff --git a/velodrome/transform/plugins/count.go b/velodrome/transform/plugins/count.go index 27f42c072218..8a1fd1fc5adf 100644 --- a/velodrome/transform/plugins/count.go +++ b/velodrome/transform/plugins/count.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" ) +// NewCountPlugin counts events and number of issues in given state, and for how long. func NewCountPlugin(runner func(Plugin) error) *cobra.Command { stateCounter := &StatePlugin{} eventCounter := &EventCounterPlugin{} diff --git a/velodrome/transform/plugins/dummy.go b/velodrome/transform/plugins/dummy.go index eaddb70ce94a..5c3d9f2df6e2 100644 --- a/velodrome/transform/plugins/dummy.go +++ b/velodrome/transform/plugins/dummy.go @@ -18,16 +18,20 @@ package plugins import "k8s.io/test-infra/velodrome/sql" +// DummyPlugin is an empty plugin type DummyPlugin struct{} +// ReceiveIssue is needed to implement a Plugin func (DummyPlugin) ReceiveIssue(issue sql.Issue) []Point { return nil } +// ReceiveIssueEvent is needed to implement a Plugin func (DummyPlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point { return nil } +// ReceiveComment is needed to implement a Plugin func (DummyPlugin) ReceiveComment(comment sql.Comment) []Point { return nil } diff --git a/velodrome/transform/plugins/event_counter.go b/velodrome/transform/plugins/event_counter.go index 537c19223635..03da2c5502c6 100644 --- a/velodrome/transform/plugins/event_counter.go +++ b/velodrome/transform/plugins/event_counter.go @@ -21,6 +21,7 @@ import ( "k8s.io/test-infra/velodrome/sql" ) +// EventCounterPlugin counts events type EventCounterPlugin struct { matcher EventMatcher desc string @@ -28,19 +29,23 @@ type EventCounterPlugin struct { var _ Plugin = &EventCounterPlugin{} +// AddFlags adds "event" to the command help func (e *EventCounterPlugin) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&e.desc, "event", "", "Match event (eg: `opened`)") } +// CheckFlags is delegated to EventMatcher func (e *EventCounterPlugin) CheckFlags() error { e.matcher = NewEventMatcher(e.desc) return nil } +// ReceiveIssue is needed to implement a Plugin func (e *EventCounterPlugin) ReceiveIssue(issue sql.Issue) []Point { return nil } +// ReceiveIssueEvent adds issue events to InfluxDB func (e *EventCounterPlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point { var label string if event.Label != nil { @@ -58,6 +63,7 @@ func (e *EventCounterPlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point { } } +// ReceiveComment is needed to implement a Plugin func (e *EventCounterPlugin) ReceiveComment(comment sql.Comment) []Point { return nil } diff --git a/velodrome/transform/plugins/events.go b/velodrome/transform/plugins/events.go index b0809fddbb3c..5bf73b53661c 100644 --- a/velodrome/transform/plugins/events.go +++ b/velodrome/transform/plugins/events.go @@ -21,6 +21,7 @@ import ( "strings" ) +// EventMatcher generates events based on name and labels type EventMatcher interface { // Does eventName and label match the event Match(eventName, label string) bool @@ -28,119 +29,147 @@ type EventMatcher interface { Opposite() EventMatcher } +// FalseEvent is a false event type FalseEvent struct{} var _ EventMatcher = FalseEvent{} +// Match is false func (FalseEvent) Match(eventName, label string) bool { return false } +// Opposite is true func (FalseEvent) Opposite() EventMatcher { return TrueEvent{} } +// TrueEvent is a true event type TrueEvent struct{} var _ EventMatcher = TrueEvent{} +// Match is true func (TrueEvent) Match(eventName, label string) bool { return true } +// Opposite is false func (TrueEvent) Opposite() EventMatcher { return FalseEvent{} } +// OpenEvent is an "opened" event type OpenEvent struct{} var _ EventMatcher = OpenEvent{} +// Match is "opened" func (OpenEvent) Match(eventName, label string) bool { return eventName == "opened" } +// Opposite is closed func (OpenEvent) Opposite() EventMatcher { return CloseEvent{} } +// CommentEvent is a "commented" event type CommentEvent struct{} var _ EventMatcher = CommentEvent{} +// Match is "commented" func (CommentEvent) Match(eventName, label string) bool { return eventName == "commented" } +// Opposite is false func (CommentEvent) Opposite() EventMatcher { return FalseEvent{} } +// LabelEvent is a "labeled" event type LabelEvent struct { Label string } var _ EventMatcher = LabelEvent{} +// Match is "labeled" with label func (l LabelEvent) Match(eventName, label string) bool { return eventName == "labeled" && label == l.Label } +// Opposite is unlabel func (l LabelEvent) Opposite() EventMatcher { return UnlabelEvent{Label: l.Label} } +// UnlabelEvent is an "unlabeled" event type UnlabelEvent struct { Label string } var _ EventMatcher = UnlabelEvent{} +// Match is "unlabeled" func (u UnlabelEvent) Match(eventName, label string) bool { return eventName == "unlabeled" && label == u.Label } +// Opposite is label func (u UnlabelEvent) Opposite() EventMatcher { return LabelEvent{Label: u.Label} } +// CloseEvent is a "closed" event type CloseEvent struct{} var _ EventMatcher = CloseEvent{} +// Match is "closed" func (CloseEvent) Match(eventName, label string) bool { return eventName == "closed" } +// Opposite is reopen func (CloseEvent) Opposite() EventMatcher { return ReopenEvent{} } +// ReopenEvent is a "reopened" event type ReopenEvent struct{} var _ EventMatcher = ReopenEvent{} +// Match is "reopened" func (ReopenEvent) Match(eventName, label string) bool { return eventName == "reopened" } +// Opposite is close func (ReopenEvent) Opposite() EventMatcher { return CloseEvent{} } +// MergeEvent is a "merged" event type MergeEvent struct{} var _ EventMatcher = MergeEvent{} +// Match is "merged" func (MergeEvent) Match(eventName, label string) bool { return eventName == "merged" } +// Opposite is false func (MergeEvent) Opposite() EventMatcher { // A merge can't be undone. return FalseEvent{} } +// NewEventMatcher returns the correct EventMatcher based on description // Incoming event should have the following form: // eventName:labelName. If eventName is not label, then the second part // can be omitted. diff --git a/velodrome/transform/plugins/fake_comment_wrapper.go b/velodrome/transform/plugins/fake_comment_wrapper.go index e9c30dd82f23..2a0a2828de0a 100644 --- a/velodrome/transform/plugins/fake_comment_wrapper.go +++ b/velodrome/transform/plugins/fake_comment_wrapper.go @@ -20,32 +20,37 @@ import ( "k8s.io/test-infra/velodrome/sql" ) +// FakeCommentPluginWrapper is a plugin wrapper creating fake "commented" events type FakeCommentPluginWrapper struct { plugin Plugin } var _ Plugin = &FakeCommentPluginWrapper{} +// NewFakeCommentPluginWrapper is the constructor for FakeCommentPluginWrapper func NewFakeCommentPluginWrapper(plugin Plugin) *FakeCommentPluginWrapper { return &FakeCommentPluginWrapper{ plugin: plugin, } } +// ReceiveIssue is a wrapper on plugin.ReceiveIssue() func (o *FakeCommentPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { // Pass through return o.plugin.ReceiveIssue(issue) } +// ReceiveIssueEvent is a wrapper on plugin.ReceiveIssueEvent() func (o *FakeCommentPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Point { // Pass through return o.plugin.ReceiveIssueEvent(event) } +// ReceiveComment creates a fake "commented" event func (o *FakeCommentPluginWrapper) ReceiveComment(comment sql.Comment) []Point { // Create a fake "commented" event for every comment we receive. fakeEvent := sql.IssueEvent{ - IssueId: comment.IssueID, + IssueID: comment.IssueID, Event: "commented", EventCreatedAt: comment.CommentCreatedAt, Actor: &comment.User, diff --git a/velodrome/transform/plugins/fake_comment_wrapper_test.go b/velodrome/transform/plugins/fake_comment_wrapper_test.go index 85552b488ffb..609e2c01a5e6 100644 --- a/velodrome/transform/plugins/fake_comment_wrapper_test.go +++ b/velodrome/transform/plugins/fake_comment_wrapper_test.go @@ -33,7 +33,7 @@ func TestFakeCommentWrapper(t *testing.T) { fakeComment := NewFakeCommentPluginWrapper(plugin) plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{ - IssueId: "1", + IssueID: "1", Event: "commented", EventCreatedAt: time.Unix(10, 0), Actor: stringPointer("SomeUser"), diff --git a/velodrome/transform/plugins/fake_open_wrapper.go b/velodrome/transform/plugins/fake_open_wrapper.go index a74dfa2d29d1..197f28d6f04d 100644 --- a/velodrome/transform/plugins/fake_open_wrapper.go +++ b/velodrome/transform/plugins/fake_open_wrapper.go @@ -31,10 +31,12 @@ func (t EventTimeHeap) Len() int { return len(t) } func (t EventTimeHeap) Swap(i, j int) { t[i], t[j] = t[j], t[i] } func (t EventTimeHeap) Less(i, j int) bool { return t[i].EventCreatedAt.Before(t[j].EventCreatedAt) } +// Push adds event to the heap func (t *EventTimeHeap) Push(x interface{}) { *t = append(*t, x.(sql.IssueEvent)) } +// Pop retrieves the last added event func (t *EventTimeHeap) Pop() interface{} { old := *t n := len(old) @@ -54,6 +56,7 @@ type FakeOpenPluginWrapper struct { var _ Plugin = &FakeOpenPluginWrapper{} +// NewFakeOpenPluginWrapper is the constructor for FakeOpenPluginWrapper func NewFakeOpenPluginWrapper(plugin Plugin) *FakeOpenPluginWrapper { return &FakeOpenPluginWrapper{ plugin: plugin, @@ -61,12 +64,13 @@ func NewFakeOpenPluginWrapper(plugin Plugin) *FakeOpenPluginWrapper { } } +// ReceiveIssue creates a fake "opened" event func (o *FakeOpenPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { if _, ok := o.alreadyOpen[issue.ID]; !ok { // Create/Add fake "opened" events heap.Push(&o.openEvents, sql.IssueEvent{ Event: "opened", - IssueId: issue.ID, + IssueID: issue.ID, Actor: &issue.User, EventCreatedAt: issue.IssueCreatedAt, }) @@ -76,6 +80,7 @@ func (o *FakeOpenPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { return o.plugin.ReceiveIssue(issue) } +// ReceiveIssueEvent injects an extra "opened" event before calling plugin.ReceiveIssueEvent() func (o *FakeOpenPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Point { points := []Point{} @@ -87,6 +92,7 @@ func (o *FakeOpenPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Point return append(points, o.plugin.ReceiveIssueEvent(event)...) } +// ReceiveComment is a wrapper on plugin.ReceiveComment() func (o *FakeOpenPluginWrapper) ReceiveComment(comment sql.Comment) []Point { return o.plugin.ReceiveComment(comment) } diff --git a/velodrome/transform/plugins/fake_open_wrapper_test.go b/velodrome/transform/plugins/fake_open_wrapper_test.go index ce710924541f..043bc2c5ffcf 100644 --- a/velodrome/transform/plugins/fake_open_wrapper_test.go +++ b/velodrome/transform/plugins/fake_open_wrapper_test.go @@ -59,13 +59,13 @@ func TestFakeOpenWrapper(t *testing.T) { EventCreatedAt: time.Unix(0, 10), }).Return([]Point{{}}), plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{ - IssueId: "1", + IssueID: "1", Actor: stringPointer("User1"), Event: "opened", EventCreatedAt: time.Unix(0, 20), }).Return([]Point{{}}), plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{ - IssueId: "2", + IssueID: "2", Actor: stringPointer("User2"), Event: "opened", EventCreatedAt: time.Unix(0, 30), @@ -77,7 +77,7 @@ func TestFakeOpenWrapper(t *testing.T) { EventCreatedAt: time.Unix(0, 40), }).Return([]Point{{}}), plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{ - IssueId: "3", + IssueID: "3", Actor: stringPointer("User3"), Event: "opened", EventCreatedAt: time.Unix(0, 50), diff --git a/velodrome/transform/plugins/multiplexer_wrapper.go b/velodrome/transform/plugins/multiplexer_wrapper.go index d059ccc4e172..0aa669ea172b 100644 --- a/velodrome/transform/plugins/multiplexer_wrapper.go +++ b/velodrome/transform/plugins/multiplexer_wrapper.go @@ -20,18 +20,21 @@ import ( "k8s.io/test-infra/velodrome/sql" ) +// MultiplexerPluginWrapper allows registering multiple plugins for events type MultiplexerPluginWrapper struct { plugins []Plugin } var _ Plugin = &MultiplexerPluginWrapper{} +// NewMultiplexerPluginWrapper is the constructor for MultiplexerPluginWrapper func NewMultiplexerPluginWrapper(plugins ...Plugin) *MultiplexerPluginWrapper { return &MultiplexerPluginWrapper{ plugins: plugins, } } +// ReceiveIssue calls plugin.ReceiveIssue() for all plugins func (m *MultiplexerPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { points := []Point{} @@ -42,6 +45,7 @@ func (m *MultiplexerPluginWrapper) ReceiveIssue(issue sql.Issue) []Point { return points } +// ReceiveIssueEvent calls plugin.ReceiveIssueEvent() for all plugins func (m *MultiplexerPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Point { points := []Point{} @@ -52,6 +56,7 @@ func (m *MultiplexerPluginWrapper) ReceiveIssueEvent(event sql.IssueEvent) []Poi return points } +// ReceiveComment calls plugin.ReceiveComment() for all plugins func (m *MultiplexerPluginWrapper) ReceiveComment(comment sql.Comment) []Point { points := []Point{} diff --git a/velodrome/transform/plugins/plugin_mock_test.go b/velodrome/transform/plugins/plugin_mock_test.go index ecdbafb51520..6975caeaa685 100644 --- a/velodrome/transform/plugins/plugin_mock_test.go +++ b/velodrome/transform/plugins/plugin_mock_test.go @@ -27,21 +27,21 @@ import ( // Mock of Plugin interface type MockPlugin struct { ctrl *gomock.Controller - recorder *_MockPluginRecorder + recorder *MockPluginRecorder } -// Recorder for MockPlugin (not exported) -type _MockPluginRecorder struct { +// Recorder for MockPlugin +type MockPluginRecorder struct { mock *MockPlugin } func NewMockPlugin(ctrl *gomock.Controller) *MockPlugin { mock := &MockPlugin{ctrl: ctrl} - mock.recorder = &_MockPluginRecorder{mock} + mock.recorder = &MockPluginRecorder{mock} return mock } -func (_m *MockPlugin) EXPECT() *_MockPluginRecorder { +func (_m *MockPlugin) EXPECT() *MockPluginRecorder { return _m.recorder } @@ -51,7 +51,7 @@ func (_m *MockPlugin) ReceiveIssue(_param0 sql.Issue) []Point { return ret0 } -func (_mr *_MockPluginRecorder) ReceiveIssue(arg0 interface{}) *gomock.Call { +func (_mr *MockPluginRecorder) ReceiveIssue(arg0 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "ReceiveIssue", arg0) } @@ -61,7 +61,7 @@ func (_m *MockPlugin) ReceiveComment(_param0 sql.Comment) []Point { return ret0 } -func (_mr *_MockPluginRecorder) ReceiveComment(arg0 interface{}) *gomock.Call { +func (_mr *MockPluginRecorder) ReceiveComment(arg0 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "ReceiveComment", arg0) } @@ -71,6 +71,6 @@ func (_m *MockPlugin) ReceiveIssueEvent(_param0 sql.IssueEvent) []Point { return ret0 } -func (_mr *_MockPluginRecorder) ReceiveIssueEvent(arg0 interface{}) *gomock.Call { +func (_mr *MockPluginRecorder) ReceiveIssueEvent(arg0 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "ReceiveIssueEvent", arg0) } diff --git a/velodrome/transform/plugins/state.go b/velodrome/transform/plugins/state.go index 32117737a30b..8698539376f8 100644 --- a/velodrome/transform/plugins/state.go +++ b/velodrome/transform/plugins/state.go @@ -23,6 +23,7 @@ import ( "k8s.io/test-infra/velodrome/sql" ) +// StatePlugin records age percentiles of issues in InfluxDB type StatePlugin struct { states BundledStates desc string @@ -31,27 +32,31 @@ type StatePlugin struct { var _ Plugin = &StatePlugin{} +// AddFlags adds "state" and "percentiles" to the command help func (s *StatePlugin) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&s.desc, "state", "", "Description of the state (eg: `opened,!merged,labeled:cool`)") cmd.Flags().IntSliceVar(&s.percentiles, "percentiles", []int{}, "Age percentiles for state") } +// CheckFlags configures which states to monitor func (s *StatePlugin) CheckFlags() error { s.states = NewBundledStates(s.desc) return nil } +// ReceiveIssue is needed to implement a Plugin func (s *StatePlugin) ReceiveIssue(issue sql.Issue) []Point { return nil } +// ReceiveIssueEvent computes age percentiles and saves them to InfluxDB func (s *StatePlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point { label := "" if event.Label != nil { label = *event.Label } - if !s.states.ReceiveEvent(event.IssueId, event.Event, label, event.EventCreatedAt) { + if !s.states.ReceiveEvent(event.IssueID, event.Event, label, event.EventCreatedAt) { return nil } @@ -72,6 +77,7 @@ func (s *StatePlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point { } } +// ReceiveComment is needed to implement a Plugin func (s *StatePlugin) ReceiveComment(comment sql.Comment) []Point { return nil } diff --git a/velodrome/transform/plugins/state_test.go b/velodrome/transform/plugins/state_test.go index 42f8eb9840fd..ffd7be06eefd 100644 --- a/velodrome/transform/plugins/state_test.go +++ b/velodrome/transform/plugins/state_test.go @@ -44,25 +44,25 @@ func TestStatePlugin(t *testing.T) { events: []sql.IssueEvent{ // No change { - IssueId: "1", + IssueID: "1", Event: "opened", EventCreatedAt: time.Unix(10*60, 0), }, // 1 is merged { - IssueId: "1", + IssueID: "1", Event: "merged", EventCreatedAt: time.Unix(20*60, 0), }, // 1 is merged again, no change { - IssueId: "1", + IssueID: "1", Event: "merged", EventCreatedAt: time.Unix(30*60, 0), }, // 2 is merged { - IssueId: "2", + IssueID: "2", Event: "merged", EventCreatedAt: time.Unix(40*60, 0), }, diff --git a/velodrome/transform/plugins/states_test.go b/velodrome/transform/plugins/states_test.go index 3a7223ba390d..c4e46c83aac8 100644 --- a/velodrome/transform/plugins/states_test.go +++ b/velodrome/transform/plugins/states_test.go @@ -55,14 +55,14 @@ func TestActiveStateReceiveMatchingEvent(t *testing.T) { exit: LabelEvent{Label: "test"}, } - got_state, got_changed := state.ReceiveEvent("labeled", "test", time.Unix(0, 10)) - want_state := &InactiveState{UnlabelEvent{Label: "test"}} - want_changed := true - if !reflect.DeepEqual(got_state, want_state) || got_changed != want_changed { + gotState, gotChanged := state.ReceiveEvent("labeled", "test", time.Unix(0, 10)) + wantState := &InactiveState{UnlabelEvent{Label: "test"}} + wantChanged := true + if !reflect.DeepEqual(gotState, wantState) || gotChanged != wantChanged { t.Errorf(`%#v.ReceiveEvent("labeled", "test", _) = (%#v, %t), want (%#v, %t)`, state, - got_state, got_changed, - want_state, want_changed) + gotState, gotChanged, + wantState, wantChanged) } } @@ -72,14 +72,14 @@ func TestActiveStateReceiveNonMatchingEvent(t *testing.T) { exit: LabelEvent{Label: "test"}, } - got_state, got_changed := state.ReceiveEvent("labeled", "non-matching", time.Unix(0, 10)) - want_state := &state - want_changed := false - if !reflect.DeepEqual(got_state, want_state) || got_changed != want_changed { + gotState, gotChanged := state.ReceiveEvent("labeled", "non-matching", time.Unix(0, 10)) + wantState := &state + wantChanged := false + if !reflect.DeepEqual(gotState, wantState) || gotChanged != wantChanged { t.Errorf(`%#v.ReceiveEvent("labeled", "non-matching", _) = (%#v, %t), want (%#v, %t)`, state, - got_state, got_changed, - want_state, want_changed) + gotState, gotChanged, + wantState, wantChanged) } } @@ -101,14 +101,14 @@ func TestInactiveStateReceiveMatchingEvent(t *testing.T) { entry: LabelEvent{Label: "test"}, } - got_state, got_changed := state.ReceiveEvent("labeled", "test", time.Unix(0, 10)) - want_state := &ActiveState{startTime: time.Unix(0, 10), exit: UnlabelEvent{Label: "test"}} - want_changed := true - if !reflect.DeepEqual(got_state, want_state) || got_changed != want_changed { + gotState, gotChanged := state.ReceiveEvent("labeled", "test", time.Unix(0, 10)) + wantState := &ActiveState{startTime: time.Unix(0, 10), exit: UnlabelEvent{Label: "test"}} + wantChanged := true + if !reflect.DeepEqual(gotState, wantState) || gotChanged != wantChanged { t.Errorf(`%#v.ReceiveEvent("labeled", "test", _) = (%#v, %t), want (%#v, %t)`, state, - got_state, got_changed, - want_state, want_changed) + gotState, gotChanged, + wantState, wantChanged) } } @@ -117,14 +117,14 @@ func TestInactiveStateReceiveNonMatchingEvent(t *testing.T) { entry: LabelEvent{Label: "test"}, } - got_state, got_changed := state.ReceiveEvent("labeled", "non-matching", time.Unix(0, 10)) - want_state := &state - want_changed := false - if !reflect.DeepEqual(got_state, want_state) || got_changed != want_changed { + gotState, gotChanged := state.ReceiveEvent("labeled", "non-matching", time.Unix(0, 10)) + wantState := &state + wantChanged := false + if !reflect.DeepEqual(gotState, wantState) || gotChanged != wantChanged { t.Errorf(`%#v.ReceiveEvent("labeled", "non-matching", _) = (%#v, %t), want (%#v, %t)`, state, - got_state, got_changed, - want_state, want_changed) + gotState, gotChanged, + wantState, wantChanged) } } @@ -178,7 +178,7 @@ func TestMultiStateInactive(t *testing.T) { func TestMultiStateReceiveEvent(t *testing.T) { var want, got, state State - var want_changed, got_changed bool + var wantChanged, gotChanged bool // We are looking for "merged,!closed", i.e. "merged" but not "closed" state = &MultiState{ []State{ @@ -186,42 +186,42 @@ func TestMultiStateReceiveEvent(t *testing.T) { &ActiveState{exit: CloseEvent{}, startTime: time.Time{}}, }, } - got, got_changed = state.ReceiveEvent("closed", "", time.Unix(0, 10)) - want, want_changed = &MultiState{ + got, gotChanged = state.ReceiveEvent("closed", "", time.Unix(0, 10)) + want, wantChanged = &MultiState{ []State{ &InactiveState{entry: MergeEvent{}}, &InactiveState{entry: ReopenEvent{}}, }, }, true - if !reflect.DeepEqual(got, want) || got_changed != want_changed { + if !reflect.DeepEqual(got, want) || gotChanged != wantChanged { t.Errorf(`%#v.ReceiveEvent("closed", "", _) = (%#v, %t), want (%#v, %t)`, - state, got, got_changed, want, want_changed) + state, got, gotChanged, want, wantChanged) } state = got - got, got_changed = state.ReceiveEvent("merged", "", time.Unix(0, 20)) - want, want_changed = &MultiState{ + got, gotChanged = state.ReceiveEvent("merged", "", time.Unix(0, 20)) + want, wantChanged = &MultiState{ []State{ &ActiveState{exit: FalseEvent{}, startTime: time.Unix(0, 20)}, &InactiveState{entry: ReopenEvent{}}, }, }, true - if !reflect.DeepEqual(got, want) || got_changed != want_changed { + if !reflect.DeepEqual(got, want) || gotChanged != wantChanged { t.Errorf(`%#v.ReceiveEvent("merged", "", time.Unix(0, 20)) = (%#v, %t), want (%#v, %t)`, - state, got, got_changed, want, want_changed) + state, got, gotChanged, want, wantChanged) } state = got - got, got_changed = state.ReceiveEvent("reopened", "", time.Unix(0, 30)) - want, want_changed = &MultiState{ + got, gotChanged = state.ReceiveEvent("reopened", "", time.Unix(0, 30)) + want, wantChanged = &MultiState{ []State{ &ActiveState{exit: FalseEvent{}, startTime: time.Unix(0, 20)}, &ActiveState{exit: CloseEvent{}, startTime: time.Unix(0, 30)}, }, }, true - if !reflect.DeepEqual(got, want) || got_changed != want_changed { + if !reflect.DeepEqual(got, want) || gotChanged != wantChanged { t.Errorf(`%#v.ReceiveEvent("merged", "", time.Unix(0, 20)) = (%#v, %t), want (%#v, %t)`, - state, got, got_changed, want, want_changed) + state, got, gotChanged, want, wantChanged) } } diff --git a/velodrome/transform/plugins/type_filter_wrapper.go b/velodrome/transform/plugins/type_filter_wrapper.go index 07e10319edf7..265245f96cb8 100644 --- a/velodrome/transform/plugins/type_filter_wrapper.go +++ b/velodrome/transform/plugins/type_filter_wrapper.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" ) +// TypeFilterWrapperPlugin allows ignoring either PR or issues from processing type TypeFilterWrapperPlugin struct { pullRequests bool issues bool @@ -36,6 +37,7 @@ type TypeFilterWrapperPlugin struct { var _ Plugin = &TypeFilterWrapperPlugin{} +// NewTypeFilterWrapperPlugin is the constructor of TypeFilterWrapperPlugin func NewTypeFilterWrapperPlugin(plugin Plugin) *TypeFilterWrapperPlugin { return &TypeFilterWrapperPlugin{ plugin: plugin, @@ -43,19 +45,22 @@ func NewTypeFilterWrapperPlugin(plugin Plugin) *TypeFilterWrapperPlugin { } } +// AddFlags adds "no-pull-requests" and "no-issues" to the command help func (t *TypeFilterWrapperPlugin) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&t.pullRequests, "no-pull-requests", false, "Ignore pull-requests") cmd.Flags().BoolVar(&t.issues, "no-issues", false, "Ignore issues") } +// CheckFlags makes sure not both PR and issues are ignored func (t *TypeFilterWrapperPlugin) CheckFlags() error { if t.pullRequests && t.issues { return fmt.Errorf( - "You can't ignore both pull-requests and issues.") + "you can't ignore both pull-requests and issues") } return nil } +// ReceiveIssue calls plugin.ReceiveIssue() if issues are not ignored func (t *TypeFilterWrapperPlugin) ReceiveIssue(issue sql.Issue) []Point { if issue.IsPR && t.pullRequests { return nil @@ -67,13 +72,15 @@ func (t *TypeFilterWrapperPlugin) ReceiveIssue(issue sql.Issue) []Point { } } +// ReceiveIssueEvent calls plugin.ReceiveIssueEvent() if issues are not ignored func (t *TypeFilterWrapperPlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point { - if !t.pass[event.IssueId] { + if !t.pass[event.IssueID] { return nil } return t.plugin.ReceiveIssueEvent(event) } +// ReceiveComment calls plugin.ReceiveComment() if issues are not ignored func (t *TypeFilterWrapperPlugin) ReceiveComment(comment sql.Comment) []Point { if !t.pass[comment.IssueID] { return nil diff --git a/velodrome/transform/plugins/type_filter_wrapper_test.go b/velodrome/transform/plugins/type_filter_wrapper_test.go index 48f15bdbdfd1..3fe03c0c4dab 100644 --- a/velodrome/transform/plugins/type_filter_wrapper_test.go +++ b/velodrome/transform/plugins/type_filter_wrapper_test.go @@ -45,16 +45,16 @@ func TestTypeFilterWrapperFilterNothing(t *testing.T) { // Filter nothing. plugin.EXPECT().ReceiveIssue(sql.Issue{ID: "1", IsPR: false}).Return([]Point{{}}) - plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueId: "1"}).Return([]Point{{}}) + plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueID: "1"}).Return([]Point{{}}) plugin.EXPECT().ReceiveComment(sql.Comment{IssueID: "1"}).Return([]Point{{}}) plugin.EXPECT().ReceiveIssue(sql.Issue{ID: "2", IsPR: true}).Return([]Point{{}}) - plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueId: "2"}).Return([]Point{{}}) + plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueID: "2"}).Return([]Point{{}}) plugin.EXPECT().ReceiveComment(sql.Comment{IssueID: "2"}).Return([]Point{{}}) if p := typefilter.ReceiveIssue(sql.Issue{ID: "1", IsPR: false}); len(p) != 1 { t.Error("Nothing should be filtered") } - if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueId: "1"}); len(p) != 1 { + if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueID: "1"}); len(p) != 1 { t.Error("Nothing should be filtered") } if p := typefilter.ReceiveComment(sql.Comment{IssueID: "1"}); len(p) != 1 { @@ -64,7 +64,7 @@ func TestTypeFilterWrapperFilterNothing(t *testing.T) { if p := typefilter.ReceiveIssue(sql.Issue{ID: "2", IsPR: true}); len(p) != 1 { t.Error("Nothing should be filtered") } - if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueId: "2"}); len(p) != 1 { + if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueID: "2"}); len(p) != 1 { t.Error("Nothing should be filtered") } if p := typefilter.ReceiveComment(sql.Comment{IssueID: "2"}); len(p) != 1 { @@ -82,13 +82,13 @@ func TestTypeFilterWrapperFilterIssues(t *testing.T) { typefilter.issues = true plugin.EXPECT().ReceiveIssue(sql.Issue{ID: "2", IsPR: true}).Return([]Point{{}}) - plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueId: "2"}).Return([]Point{{}}) + plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueID: "2"}).Return([]Point{{}}) plugin.EXPECT().ReceiveComment(sql.Comment{IssueID: "2"}).Return([]Point{{}}) if p := typefilter.ReceiveIssue(sql.Issue{ID: "1", IsPR: false}); len(p) != 0 { t.Error("Issue 1 is an issue, should be filtered but received point for Issue") } - if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueId: "1"}); len(p) != 0 { + if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueID: "1"}); len(p) != 0 { t.Error("Issue 1 is an issue, should be filtered but received point for IssueEvent") } if p := typefilter.ReceiveComment(sql.Comment{IssueID: "1"}); len(p) != 0 { @@ -98,7 +98,7 @@ func TestTypeFilterWrapperFilterIssues(t *testing.T) { if p := typefilter.ReceiveIssue(sql.Issue{ID: "2", IsPR: true}); len(p) != 1 { t.Error("Issue 2 is a PR, should have received point for Issue") } - if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueId: "2"}); len(p) != 1 { + if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueID: "2"}); len(p) != 1 { t.Error("Issue 2 is a PR, should have received point for IssueEvent") } if p := typefilter.ReceiveComment(sql.Comment{IssueID: "2"}); len(p) != 1 { @@ -116,13 +116,13 @@ func TestTypeFilterWrapperFilterPR(t *testing.T) { typefilter.pullRequests = true plugin.EXPECT().ReceiveIssue(sql.Issue{ID: "2", IsPR: false}).Return([]Point{{}}) - plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueId: "2"}).Return([]Point{{}}) + plugin.EXPECT().ReceiveIssueEvent(sql.IssueEvent{IssueID: "2"}).Return([]Point{{}}) plugin.EXPECT().ReceiveComment(sql.Comment{IssueID: "2"}).Return([]Point{{}}) if p := typefilter.ReceiveIssue(sql.Issue{ID: "1", IsPR: true}); len(p) != 0 { t.Error("Issue 1 is a PR, should be filtered but received point for Issue") } - if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueId: "1"}); len(p) != 0 { + if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueID: "1"}); len(p) != 0 { t.Error("Issue 1 is a PR, should be filtered but received point for IssueEvent") } if p := typefilter.ReceiveComment(sql.Comment{IssueID: "1"}); len(p) != 0 { @@ -132,7 +132,7 @@ func TestTypeFilterWrapperFilterPR(t *testing.T) { if p := typefilter.ReceiveIssue(sql.Issue{ID: "2", IsPR: false}); len(p) != 1 { t.Error("Issue 2 is an issue, should have received point for Issue") } - if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueId: "2"}); len(p) != 1 { + if p := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueID: "2"}); len(p) != 1 { t.Error("Issue 2 is an issue, should have received point for IssueEvent") } if p := typefilter.ReceiveComment(sql.Comment{IssueID: "2"}); len(p) != 1 { @@ -152,7 +152,7 @@ func TestTypeFilterWrapperFilterMissingIssue(t *testing.T) { t.Errorf("ReceiveComment() = %v, expected nil", points) } - if points := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueId: "1"}); points != nil { + if points := typefilter.ReceiveIssueEvent(sql.IssueEvent{IssueID: "1"}); points != nil { t.Errorf("ReceiveIssueEvent() = %v, expected nil", points) } } diff --git a/velodrome/transform/transform.go b/velodrome/transform/transform.go index 4fcb4908e3dc..816d1b2416c8 100644 --- a/velodrome/transform/transform.go +++ b/velodrome/transform/transform.go @@ -43,12 +43,12 @@ type transformConfig struct { func (config *transformConfig) CheckRootFlags() error { if config.repository == "" { - return fmt.Errorf("Repository must be set.") + return fmt.Errorf("repository must be set") } config.repository = strings.ToLower(config.repository) if config.metricName == "" { - return fmt.Errorf("Metric name must be set.") + return fmt.Errorf("metric name must be set") } return nil