-
Notifications
You must be signed in to change notification settings - Fork 118
Add support for using regex patterns in findSuite #3456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1167,12 +1167,23 @@ func (pl *ProwLoader) findSuite(name string) *uint { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| suite := &models.Suite{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pl.dbc.DB.Where("name = ?", name).Find(&suite) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if suite.ID == 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pl.suiteCache[name] = nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id := suite.ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pl.suiteCache[name] = &id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // No row - the exact suite name is not in the database (for example, by populateTestSuitesInDB) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !db.IsTestSuiteImportable(name) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pl.suiteCache[name] = nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // If IsTestSuiteImportable() returns true (for example, pattern match), add the Suite row. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| suite.Name = name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tx := pl.dbc.DB.Save(suite) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if tx.Error != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.WithError(tx.Error).Warningf("failed to create suite %q", name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.WithField("suite", name).Info("created new test suite") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return pl.suiteCache[name] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id := suite.ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was curious if ID would be set properly in the struct here since it is created during the save. The indication is that it should be. I wonder if it is still worth a check to verify it isn't 0 after the save though. Worst case would be that the first time it is save that job would be ignored if the ID was still 0. Next query it should exists. ● Analysis of suite.ID Population After Save() You've identified a critical question! Let me trace through the code path: suite := &models.Suite{} // ID = 0, Name = "" Expected GORM Behavior: YES, it should be populated With GORM + PostgreSQL:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pl.suiteCache[name] = &id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return &id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
1169
to
+1186
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With a single array implementation, the solution is more straightforward (no call to an external function):
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (pl *ProwLoader) prowJobRunTestsFromGCS(ctx context.Context, pj *prow.ProwJob, id uint, path string, junitPaths []string) ([]*models.ProwJobRunTest, int, sippyprocessingv1.JobOverallResult, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,8 @@ | ||||||||||||||
| package db | ||||||||||||||
|
|
||||||||||||||
| import ( | ||||||||||||||
| "regexp" | ||||||||||||||
|
|
||||||||||||||
| "github.com/pkg/errors" | ||||||||||||||
| log "github.com/sirupsen/logrus" | ||||||||||||||
| "gorm.io/gorm" | ||||||||||||||
|
|
@@ -74,6 +76,44 @@ var testSuites = []string{ | |||||||||||||
| "tracing-uiplugin", | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // testSuitePatterns are regular expressions (MatchString) for suite names that should be imported | ||||||||||||||
| // without listing every literal name. Patterns are compiled in init(). | ||||||||||||||
| var testSuitePatterns = []string{ | ||||||||||||||
| // LP interop naming: `lp-interop-<product>--<suffix>`. | ||||||||||||||
| `^lp-interop-`, | ||||||||||||||
|
Comment on lines
+82
to
+83
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regex pattern is broader than the documented suite format. Line 82 documents Suggested tightening var testSuitePatterns = []string{
// LP interop naming: `lp-interop-<product>--<suffix>`.
- `^lp-interop-`,
+ `^lp-interop-.+--.+$`,
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The pattern
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| var compiledTestSuitePatterns []*regexp.Regexp | ||||||||||||||
|
oharan2 marked this conversation as resolved.
|
||||||||||||||
|
|
||||||||||||||
| // Invalid regexes panic at process start. | ||||||||||||||
| func init() { | ||||||||||||||
| compiledTestSuitePatterns = make([]*regexp.Regexp, len(testSuitePatterns)) | ||||||||||||||
| for i, p := range testSuitePatterns { | ||||||||||||||
| compiledTestSuitePatterns[i] = regexp.MustCompile(p) | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Runs inside the prow loader on every unknown suite name | ||||||||||||||
| // Reports whether junit from this testsuite name should be imported: either an | ||||||||||||||
| // exact entry in testSuites or a match against testSuitePatterns. | ||||||||||||||
| func IsTestSuiteImportable(name string) bool { | ||||||||||||||
| if name == "" { | ||||||||||||||
| return false | ||||||||||||||
| } | ||||||||||||||
| for _, s := range testSuites { | ||||||||||||||
| if s == name { | ||||||||||||||
| return true | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| for _, re := range compiledTestSuitePatterns { | ||||||||||||||
| if re.MatchString(name) { | ||||||||||||||
| return true | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| return false | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Runs when the DB is set up / migrated. | ||||||||||||||
| func populateTestSuitesInDB(db *gorm.DB) error { | ||||||||||||||
| for _, suiteName := range testSuites { | ||||||||||||||
| s := models.Suite{} | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package db | ||
|
|
||
| import "testing" | ||
|
|
||
| func TestIsTestSuiteImportable(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| want bool | ||
| }{ | ||
| {"", false}, | ||
| {"openshift-tests", true}, | ||
| {"CNV-lp-interop", true}, | ||
| {"ACS-lp-interop", true}, | ||
| {"lp-interop-ACS--my-tests", true}, | ||
| {"lp-interop-Foo", true}, | ||
| {"CNV-lp-interop-extra-suffix", false}, | ||
| {"random-suite", false}, | ||
| {"-lp-interop", false}, | ||
| {"lp-interop", false}, | ||
| } | ||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| if got := IsTestSuiteImportable(tt.name); got != tt.want { | ||
| t.Errorf("IsTestSuiteImportable(%q) = %v, want %v", tt.name, got, tt.want) | ||
| } | ||
| }) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could IsTestSuiteImportable do the save of the suite? Claude noted the duplication of logic. Wondering if the save could be refactored within db/suites so that both populateTestSuitesInDB and IsTestSuiteImportable used the same method.
Duplicate pattern found in:
Both locations contain identical suite creation logic:
suite.Name = name
tx := DB.Save(suite)
if tx.Error != nil {
log.WithError(...).Warningf(...)
return ...
}
log.WithField("suite", name).Info("created new test suite")
Recommendation: Extract into shared function:
// In pkg/db/suites.go
func createSuite(db *gorm.DB, name string) (*models.Suite, error)