From 2e046fceb8fe56fb7170495962f24475cee78d46 Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:36:32 -0400 Subject: [PATCH 01/18] Merge pull request from GHSA-7v38-w32m-wx4m * fix(secrets): add substitution field and honor allow_commands for entrypoint * ditch substring detection in favor of strict byte replace for log masking * replace all over replace -1 --- database/secret.go | 63 ++++++++++++++------------- database/secret_test.go | 33 +++++++------- library/log.go | 27 ++++-------- library/log_test.go | 82 ++++++++++++++++++++++------------- library/secret.go | 95 ++++++++++++++++++++++++++++------------- library/secret_test.go | 33 ++++++++++++++ 6 files changed, 210 insertions(+), 123 deletions(-) diff --git a/database/secret.go b/database/secret.go index f9dae86d..a8e6c0e7 100644 --- a/database/secret.go +++ b/database/secret.go @@ -42,21 +42,22 @@ var ( // Secret is the database representation of a secret. type Secret struct { - ID sql.NullInt64 `sql:"id"` - Org sql.NullString `sql:"org"` - Repo sql.NullString `sql:"repo"` - Team sql.NullString `sql:"team"` - Name sql.NullString `sql:"name"` - Value sql.NullString `sql:"value"` - Type sql.NullString `sql:"type"` - Images pq.StringArray `sql:"images" gorm:"type:varchar(1000)"` - Events pq.StringArray `sql:"events" gorm:"type:varchar(1000)"` - AllowEvents sql.NullInt64 `sql:"allow_events"` - AllowCommand sql.NullBool `sql:"allow_command"` - CreatedAt sql.NullInt64 `sql:"created_at"` - CreatedBy sql.NullString `sql:"created_by"` - UpdatedAt sql.NullInt64 `sql:"updated_at"` - UpdatedBy sql.NullString `sql:"updated_by"` + ID sql.NullInt64 `sql:"id"` + Org sql.NullString `sql:"org"` + Repo sql.NullString `sql:"repo"` + Team sql.NullString `sql:"team"` + Name sql.NullString `sql:"name"` + Value sql.NullString `sql:"value"` + Type sql.NullString `sql:"type"` + Images pq.StringArray `sql:"images" gorm:"type:varchar(1000)"` + Events pq.StringArray `sql:"events" gorm:"type:varchar(1000)"` + AllowEvents sql.NullInt64 `sql:"allow_events"` + AllowCommand sql.NullBool `sql:"allow_command"` + AllowSubstitution sql.NullBool `sql:"allow_substitution"` + CreatedAt sql.NullInt64 `sql:"created_at"` + CreatedBy sql.NullString `sql:"created_by"` + UpdatedAt sql.NullInt64 `sql:"updated_at"` + UpdatedBy sql.NullString `sql:"updated_by"` } // Decrypt will manipulate the existing secret value by @@ -196,6 +197,7 @@ func (s *Secret) ToLibrary() *library.Secret { secret.SetEvents(s.Events) secret.SetAllowEvents(library.NewEventsFromMask(s.AllowEvents.Int64)) secret.SetAllowCommand(s.AllowCommand.Bool) + secret.SetAllowSubstitution(s.AllowSubstitution.Bool) secret.SetCreatedAt(s.CreatedAt.Int64) secret.SetCreatedBy(s.CreatedBy.String) secret.SetUpdatedAt(s.UpdatedAt.Int64) @@ -272,21 +274,22 @@ func (s *Secret) Validate() error { // to a database Secret type. func SecretFromLibrary(s *library.Secret) *Secret { secret := &Secret{ - ID: sql.NullInt64{Int64: s.GetID(), Valid: true}, - Org: sql.NullString{String: s.GetOrg(), Valid: true}, - Repo: sql.NullString{String: s.GetRepo(), Valid: true}, - Team: sql.NullString{String: s.GetTeam(), Valid: true}, - Name: sql.NullString{String: s.GetName(), Valid: true}, - Value: sql.NullString{String: s.GetValue(), Valid: true}, - Type: sql.NullString{String: s.GetType(), Valid: true}, - Images: pq.StringArray(s.GetImages()), - Events: pq.StringArray(s.GetEvents()), - AllowEvents: sql.NullInt64{Int64: s.GetAllowEvents().ToDatabase(), Valid: true}, - AllowCommand: sql.NullBool{Bool: s.GetAllowCommand(), Valid: true}, - CreatedAt: sql.NullInt64{Int64: s.GetCreatedAt(), Valid: true}, - CreatedBy: sql.NullString{String: s.GetCreatedBy(), Valid: true}, - UpdatedAt: sql.NullInt64{Int64: s.GetUpdatedAt(), Valid: true}, - UpdatedBy: sql.NullString{String: s.GetUpdatedBy(), Valid: true}, + ID: sql.NullInt64{Int64: s.GetID(), Valid: true}, + Org: sql.NullString{String: s.GetOrg(), Valid: true}, + Repo: sql.NullString{String: s.GetRepo(), Valid: true}, + Team: sql.NullString{String: s.GetTeam(), Valid: true}, + Name: sql.NullString{String: s.GetName(), Valid: true}, + Value: sql.NullString{String: s.GetValue(), Valid: true}, + Type: sql.NullString{String: s.GetType(), Valid: true}, + Images: pq.StringArray(s.GetImages()), + Events: pq.StringArray(s.GetEvents()), + AllowEvents: sql.NullInt64{Int64: s.GetAllowEvents().ToDatabase(), Valid: true}, + AllowCommand: sql.NullBool{Bool: s.GetAllowCommand(), Valid: true}, + AllowSubstitution: sql.NullBool{Bool: s.GetAllowSubstitution(), Valid: true}, + CreatedAt: sql.NullInt64{Int64: s.GetCreatedAt(), Valid: true}, + CreatedBy: sql.NullString{String: s.GetCreatedBy(), Valid: true}, + UpdatedAt: sql.NullInt64{Int64: s.GetUpdatedAt(), Valid: true}, + UpdatedBy: sql.NullString{String: s.GetUpdatedBy(), Valid: true}, } return secret.Nullify() diff --git a/database/secret_test.go b/database/secret_test.go index f4c6d23c..6c61ec44 100644 --- a/database/secret_test.go +++ b/database/secret_test.go @@ -171,6 +171,7 @@ func TestDatabase_Secret_ToLibrary(t *testing.T) { want.SetEvents([]string{"push", "tag", "deployment"}) want.SetAllowEvents(library.NewEventsFromMask(1)) want.SetAllowCommand(true) + want.SetAllowSubstitution(true) want.SetCreatedAt(tsCreate) want.SetCreatedBy("octocat") want.SetUpdatedAt(tsUpdate) @@ -295,6 +296,7 @@ func TestDatabase_SecretFromLibrary(t *testing.T) { s.SetEvents([]string{"push", "tag", "deployment"}) s.SetAllowEvents(library.NewEventsFromMask(1)) s.SetAllowCommand(true) + s.SetAllowSubstitution(true) s.SetCreatedAt(tsCreate) s.SetCreatedBy("octocat") s.SetUpdatedAt(tsUpdate) @@ -314,20 +316,21 @@ func TestDatabase_SecretFromLibrary(t *testing.T) { // type with all fields set to a fake value. func testSecret() *Secret { return &Secret{ - ID: sql.NullInt64{Int64: 1, Valid: true}, - Org: sql.NullString{String: "github", Valid: true}, - Repo: sql.NullString{String: "octocat", Valid: true}, - Team: sql.NullString{String: "octokitties", Valid: true}, - Name: sql.NullString{String: "foo", Valid: true}, - Value: sql.NullString{String: "bar", Valid: true}, - Type: sql.NullString{String: "repo", Valid: true}, - Images: []string{"alpine"}, - Events: []string{"push", "tag", "deployment"}, - AllowEvents: sql.NullInt64{Int64: 1, Valid: true}, - AllowCommand: sql.NullBool{Bool: true, Valid: true}, - CreatedAt: sql.NullInt64{Int64: tsCreate, Valid: true}, - CreatedBy: sql.NullString{String: "octocat", Valid: true}, - UpdatedAt: sql.NullInt64{Int64: tsUpdate, Valid: true}, - UpdatedBy: sql.NullString{String: "octocat2", Valid: true}, + ID: sql.NullInt64{Int64: 1, Valid: true}, + Org: sql.NullString{String: "github", Valid: true}, + Repo: sql.NullString{String: "octocat", Valid: true}, + Team: sql.NullString{String: "octokitties", Valid: true}, + Name: sql.NullString{String: "foo", Valid: true}, + Value: sql.NullString{String: "bar", Valid: true}, + Type: sql.NullString{String: "repo", Valid: true}, + Images: []string{"alpine"}, + Events: []string{"push", "tag", "deployment"}, + AllowEvents: sql.NullInt64{Int64: 1, Valid: true}, + AllowCommand: sql.NullBool{Bool: true, Valid: true}, + AllowSubstitution: sql.NullBool{Bool: true, Valid: true}, + CreatedAt: sql.NullInt64{Int64: tsCreate, Valid: true}, + CreatedBy: sql.NullString{String: "octocat", Valid: true}, + UpdatedAt: sql.NullInt64{Int64: tsUpdate, Valid: true}, + UpdatedBy: sql.NullString{String: "octocat2", Valid: true}, } } diff --git a/library/log.go b/library/log.go index 9c2ce146..3c41f429 100644 --- a/library/log.go +++ b/library/log.go @@ -3,8 +3,8 @@ package library import ( + "bytes" "fmt" - "regexp" "github.com/go-vela/types/constants" ) @@ -45,25 +45,14 @@ func (l *Log) AppendData(data []byte) { func (l *Log) MaskData(secrets []string) { data := l.GetData() + // early exit on empty log or secret list + if len(data) == 0 || len(secrets) == 0 { + return + } + + // byte replace data with masked logs for _, secret := range secrets { - // escape regexp meta characters if they exist within value of secret - // - // https://pkg.go.dev/regexp#QuoteMeta - escaped := regexp.QuoteMeta(secret) - - // create regexp to match secrets in the log data surrounded by regexp metacharacters - // - // https://pkg.go.dev/regexp#MustCompile - buffer := `(\s|^|=|"|\?|:|'|\.|,|&|$|;|\[|\])` - re := regexp.MustCompile((buffer + escaped + buffer)) - - // create a mask for the secret - mask := fmt.Sprintf("$1%s$2", constants.SecretLogMask) - - // replace all regexp matches of secret with mask - // - // https://pkg.go.dev/regexp#Regexp.ReplaceAll - data = re.ReplaceAll(data, []byte(mask)) + data = bytes.ReplaceAll(data, []byte(secret), []byte(constants.SecretLogMask)) } // update data field to masked logs diff --git a/library/log_test.go b/library/log_test.go index 5ea64669..e0125507 100644 --- a/library/log_test.go +++ b/library/log_test.go @@ -42,59 +42,83 @@ func TestLibrary_Log_AppendData(t *testing.T) { func TestLibrary_Log_MaskData(t *testing.T) { // set up test secrets - sVals := []string{"secret", "((%.YY245***pP.><@@}}", "littlesecret", "extrasecret"} - - // set up test logs - s1 := "$ echo $NO_SECRET\nnosecret\n" - s2 := "((%.YY245***pP.><@@}}" - s2Masked := "***" - s3 := "$ echo $SECRET1\n((%.YY245***pP.><@@}}\n$ echo $SECRET2\nlittlesecret\n" - s3Masked := "$ echo $SECRET1\n***\n$ echo $SECRET2\n***\n" - s4 := "SOME_SECRET=((%.YY245***pP.><@@}}" - s4Masked := "SOME_SECRET=***" - s5 := "www.example.com?username=secret&password=extrasecret" - s5Masked := "www.example.com?username=***&password=***" - s6 := "[token: extrasecret]" - s6Masked := "[token: ***]" + sVals := []string{"gh_abc123def456", "((%.YY245***pP.><@@}}", "quick-bear-fox-squid", "SUPERSECRETVALUE"} tests := []struct { - want []byte log []byte + want []byte secrets []string }{ { // no secrets in log - want: []byte(s1), - log: []byte(s1), + log: []byte( + "$ echo hello\nhello\n", + ), + want: []byte( + "$ echo hello\nhello\n", + ), secrets: sVals, }, { // one secret in log - want: []byte(s2Masked), - log: []byte(s2), + log: []byte( + "((%.YY245***pP.><@@}}", + ), + want: []byte( + "***", + ), secrets: sVals, }, { // multiple secrets in log - want: []byte(s3Masked), - log: []byte(s3), + log: []byte( + "$ echo $SECRET1\n((%.YY245***pP.><@@}}\n$ echo $SECRET2\nquick-bear-fox-squid\n", + ), + want: []byte( + "$ echo $SECRET1\n***\n$ echo $SECRET2\n***\n", + ), secrets: sVals, }, { // secret with leading = - want: []byte(s4Masked), - log: []byte(s4), + log: []byte( + "SOME_SECRET=((%.YY245***pP.><@@}}", + ), + want: []byte( + "SOME_SECRET=***", + ), secrets: sVals, }, { // secret baked in URL query params - want: []byte(s5Masked), - log: []byte(s5), + log: []byte( + "www.example.com?username=quick-bear-fox-squid&password=SUPERSECRETVALUE", + ), + want: []byte( + "www.example.com?username=***&password=***", + ), secrets: sVals, }, { // secret in verbose brackets - want: []byte(s6Masked), - log: []byte(s6), + log: []byte( + "[token: gh_abc123def456]", + ), + want: []byte( + "[token: ***]", + ), + secrets: sVals, + }, + { // double secret + log: []byte( + "echo ${GITHUB_TOKEN}${SUPER_SECRET}\ngh_abc123def456SUPERSECRETVALUE\n", + ), + want: []byte( + "echo ${GITHUB_TOKEN}${SUPER_SECRET}\n******\n", + ), secrets: sVals, }, { // empty secrets slice - want: []byte(s3), - log: []byte(s3), + log: []byte( + "echo hello\nhello\n", + ), + want: []byte( + "echo hello\nhello\n", + ), secrets: []string{}, }, } diff --git a/library/secret.go b/library/secret.go index 2566b4cd..04e12497 100644 --- a/library/secret.go +++ b/library/secret.go @@ -14,21 +14,22 @@ import ( // // swagger:model Secret type Secret struct { - ID *int64 `json:"id,omitempty"` - Org *string `json:"org,omitempty"` - Repo *string `json:"repo,omitempty"` - Team *string `json:"team,omitempty"` - Name *string `json:"name,omitempty"` - Value *string `json:"value,omitempty"` - Type *string `json:"type,omitempty"` - Images *[]string `json:"images,omitempty"` - Events *[]string `json:"events,omitempty"` - AllowEvents *Events `json:"allow_events,omitempty"` - AllowCommand *bool `json:"allow_command,omitempty"` - CreatedAt *int64 `json:"created_at,omitempty"` - CreatedBy *string `json:"created_by,omitempty"` - UpdatedAt *int64 `json:"updated_at,omitempty"` - UpdatedBy *string `json:"updated_by,omitempty"` + ID *int64 `json:"id,omitempty"` + Org *string `json:"org,omitempty"` + Repo *string `json:"repo,omitempty"` + Team *string `json:"team,omitempty"` + Name *string `json:"name,omitempty"` + Value *string `json:"value,omitempty"` + Type *string `json:"type,omitempty"` + Images *[]string `json:"images,omitempty"` + Events *[]string `json:"events,omitempty"` + AllowEvents *Events `json:"allow_events,omitempty"` + AllowCommand *bool `json:"allow_command,omitempty"` + AllowSubstitution *bool `json:"allow_substitution,omitempty"` + CreatedAt *int64 `json:"created_at,omitempty"` + CreatedBy *string `json:"created_by,omitempty"` + UpdatedAt *int64 `json:"updated_at,omitempty"` + UpdatedBy *string `json:"updated_by,omitempty"` } // Sanitize creates a duplicate of the Secret without the value. @@ -39,21 +40,22 @@ func (s *Secret) Sanitize() *Secret { value := constants.SecretMask return &Secret{ - ID: s.ID, - Org: s.Org, - Repo: s.Repo, - Team: s.Team, - Name: s.Name, - Value: &value, - Type: s.Type, - Images: s.Images, - Events: s.Events, - AllowEvents: s.AllowEvents, - AllowCommand: s.AllowCommand, - CreatedAt: s.CreatedAt, - CreatedBy: s.CreatedBy, - UpdatedAt: s.UpdatedAt, - UpdatedBy: s.UpdatedBy, + ID: s.ID, + Org: s.Org, + Repo: s.Repo, + Team: s.Team, + Name: s.Name, + Value: &value, + Type: s.Type, + Images: s.Images, + Events: s.Events, + AllowEvents: s.AllowEvents, + AllowCommand: s.AllowCommand, + AllowSubstitution: s.AllowSubstitution, + CreatedAt: s.CreatedAt, + CreatedBy: s.CreatedBy, + UpdatedAt: s.UpdatedAt, + UpdatedBy: s.UpdatedBy, } } @@ -69,6 +71,11 @@ func (s *Secret) Match(from *pipeline.Container) bool { return false } + // check if a custom entrypoint is utilized when not allowed + if !commands && len(from.Commands) == 0 && len(from.Entrypoint) > 0 { + return false + } + eACL = s.GetAllowEvents().Allowed( from.Environment["VELA_BUILD_EVENT"], from.Environment["VELA_BUILD_EVENT_ACTION"], @@ -237,6 +244,19 @@ func (s *Secret) GetAllowCommand() bool { return *s.AllowCommand } +// GetAllowSubstitution returns the AllowSubstitution field. +// +// When the provided Secret type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (s *Secret) GetAllowSubstitution() bool { + // return zero value if Secret type or AllowSubstitution field is nil + if s == nil || s.AllowSubstitution == nil { + return false + } + + return *s.AllowSubstitution +} + // GetCreatedAt returns the CreatedAt field. // // When the provided Secret type is nil, or the field within @@ -432,6 +452,19 @@ func (s *Secret) SetAllowCommand(v bool) { s.AllowCommand = &v } +// SetAllowSubstitution sets the AllowSubstitution field. +// +// When the provided Secret type is nil, it +// will set nothing and immediately return. +func (s *Secret) SetAllowSubstitution(v bool) { + // return if Secret type is nil + if s == nil { + return + } + + s.AllowSubstitution = &v +} + // SetCreatedAt sets the CreatedAt field. // // When the provided Secret type is nil, it @@ -489,6 +522,7 @@ func (s *Secret) String() string { return fmt.Sprintf(`{ AllowCommand: %t, AllowEvents: %s, + AllowSubstitution: %t, Events: %s, ID: %d, Images: %s, @@ -505,6 +539,7 @@ func (s *Secret) String() string { }`, s.GetAllowCommand(), s.GetAllowEvents().List(), + s.GetAllowSubstitution(), s.GetEvents(), s.GetID(), s.GetImages(), diff --git a/library/secret_test.go b/library/secret_test.go index 591c1ac5..ebe14549 100644 --- a/library/secret_test.go +++ b/library/secret_test.go @@ -354,6 +354,27 @@ func TestLibrary_Secret_Match(t *testing.T) { }, want: false, }, + { + name: "no commands allowed - entrypoint provided", + step: &pipeline.Container{ + Image: "alpine:latest", + Environment: map[string]string{"VELA_BUILD_EVENT": "push"}, + Ruleset: pipeline.Ruleset{ + If: pipeline.Rules{ + Event: []string{"push"}, + }, + }, + Entrypoint: []string{"sh", "-c", "echo hi"}, + }, + sec: &Secret{ + Name: &v, + Value: &v, + Images: &[]string{"alpine"}, + AllowEvents: testEvents, + AllowCommand: &fBool, + }, + want: false, + }, } // run tests @@ -428,6 +449,10 @@ func TestLibrary_Secret_Getters(t *testing.T) { t.Errorf("GetAllowCommand is %v, want %v", test.secret.GetAllowCommand(), test.want.GetAllowCommand()) } + if test.secret.GetAllowSubstitution() != test.want.GetAllowSubstitution() { + t.Errorf("GetAllowSubstitution is %v, want %v", test.secret.GetAllowSubstitution(), test.want.GetAllowSubstitution()) + } + if test.secret.GetCreatedAt() != test.want.GetCreatedAt() { t.Errorf("GetCreatedAt is %v, want %v", test.secret.GetCreatedAt(), test.want.GetCreatedAt()) } @@ -478,6 +503,7 @@ func TestLibrary_Secret_Setters(t *testing.T) { test.secret.SetEvents(test.want.GetEvents()) test.secret.SetAllowEvents(test.want.GetAllowEvents()) test.secret.SetAllowCommand(test.want.GetAllowCommand()) + test.secret.SetAllowSubstitution(test.want.GetAllowSubstitution()) test.secret.SetCreatedAt(test.want.GetCreatedAt()) test.secret.SetCreatedBy(test.want.GetCreatedBy()) test.secret.SetUpdatedAt(test.want.GetUpdatedAt()) @@ -527,6 +553,10 @@ func TestLibrary_Secret_Setters(t *testing.T) { t.Errorf("SetAllowCommand is %v, want %v", test.secret.GetAllowCommand(), test.want.GetAllowCommand()) } + if test.secret.GetAllowSubstitution() != test.want.GetAllowSubstitution() { + t.Errorf("SetAllowSubstitution is %v, want %v", test.secret.GetAllowSubstitution(), test.want.GetAllowSubstitution()) + } + if test.secret.GetCreatedAt() != test.want.GetCreatedAt() { t.Errorf("SetCreatedAt is %v, want %v", test.secret.GetCreatedAt(), test.want.GetCreatedAt()) } @@ -552,6 +582,7 @@ func TestLibrary_Secret_String(t *testing.T) { want := fmt.Sprintf(`{ AllowCommand: %t, AllowEvents: %v, + AllowSubstitution: %t, Events: %s, ID: %d, Images: %s, @@ -568,6 +599,7 @@ func TestLibrary_Secret_String(t *testing.T) { }`, s.GetAllowCommand(), s.GetAllowEvents().List(), + s.GetAllowSubstitution(), s.GetEvents(), s.GetID(), s.GetImages(), @@ -610,6 +642,7 @@ func testSecret() *Secret { s.SetEvents([]string{"push", "tag", "deployment"}) s.SetAllowEvents(NewEventsFromMask(1)) s.SetAllowCommand(true) + s.SetAllowSubstitution(true) s.SetCreatedAt(tsCreate) s.SetCreatedBy("octocat") s.SetUpdatedAt(tsUpdate) From 09a256b4c64941ce2144998d526533f346cc7a14 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:18:26 -0500 Subject: [PATCH 02/18] chore(deps): update all non-major dependencies (#359) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/reviewdog.yml | 4 ++-- .github/workflows/test.yml | 2 +- go.mod | 2 +- go.sum | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 112ec365..0cd1c7b9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,7 +47,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/init@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -58,7 +58,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/autobuild@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -72,4 +72,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + uses: github/codeql-action/analyze@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index b9eb09c0..5ccd8653 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -23,7 +23,7 @@ jobs: check-latest: true - name: golangci-lint - uses: reviewdog/action-golangci-lint@8e1117c7d327bbfb1eb7ec8dc2d895d13e6e17c3 # v2.6.0 + uses: reviewdog/action-golangci-lint@00311c26a97213f93f2fd3a3524d66762e956ae0 # v2.6.1 with: github_token: ${{ secrets.github_token }} golangci_lint_flags: "--config=.golangci.yml" @@ -47,7 +47,7 @@ jobs: check-latest: true - name: golangci-lint - uses: reviewdog/action-golangci-lint@8e1117c7d327bbfb1eb7ec8dc2d895d13e6e17c3 # v2.6.0 + uses: reviewdog/action-golangci-lint@00311c26a97213f93f2fd3a3524d66762e956ae0 # v2.6.1 with: github_token: ${{ secrets.github_token }} golangci_lint_flags: "--config=.golangci.yml" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5970250f..ff6dc9b7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: go test -race -covermode=atomic -coverprofile=coverage.out ./... - name: coverage - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4.0.1 + uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0 with: token: ${{ secrets.CODECOV_TOKEN }} file: coverage.out diff --git a/go.mod b/go.mod index 1f0790df..fe0ced70 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/go-vela/types go 1.21 require ( - github.com/adhocore/gronx v1.6.7 + github.com/adhocore/gronx v1.8.0 github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3 github.com/drone/envsubst v1.0.3 github.com/ghodss/yaml v1.0.0 diff --git a/go.sum b/go.sum index f2cbb47e..bfcde40c 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/adhocore/gronx v1.6.7 h1:yE/AKQP/yhjMRqV943XiPqBdmUwIF8VHJwm6KZhnk48= -github.com/adhocore/gronx v1.6.7/go.mod h1:7oUY1WAU8rEJWmAxXR2DN0JaO4gi9khSgKjiRypqteg= +github.com/adhocore/gronx v1.8.0 h1:BHgzaGyS7zPmuMVqiIxyAwvKpwAX+bR7bCxDVacfhuo= +github.com/adhocore/gronx v1.8.0/go.mod h1:7oUY1WAU8rEJWmAxXR2DN0JaO4gi9khSgKjiRypqteg= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3 h1:q+sMKdA6L8LyGVudTkpGoC73h6ak2iWSPFiFo/pFOU8= From b1970b932c9aabdc8ff1a29f002f177bd425d3af Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Thu, 14 Mar 2024 09:16:20 -0400 Subject: [PATCH 03/18] fix(ci): address all outstanding linter feedback (#363) --- database/schedule_test.go | 2 ++ library/schedule_test.go | 41 +++++++++++++++++++++++++++++---------- raw/map_test.go | 1 + 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/database/schedule_test.go b/database/schedule_test.go index d7ff78aa..068f324a 100644 --- a/database/schedule_test.go +++ b/database/schedule_test.go @@ -155,8 +155,10 @@ func TestDatabase_Schedule_Validate(t *testing.T) { if err == nil { t.Errorf("Validate should have returned err") } + return } + if err != nil { t.Errorf("Validate returned err: %v", err) } diff --git a/library/schedule_test.go b/library/schedule_test.go index b2f8db54..8e325c5b 100644 --- a/library/schedule_test.go +++ b/library/schedule_test.go @@ -37,33 +37,43 @@ func TestLibrary_Schedule_Getters(t *testing.T) { if test.schedule.GetID() != test.want.GetID() { t.Errorf("GetID is %v, want %v", test.schedule.GetID(), test.want.GetID()) } + if test.schedule.GetRepoID() != test.want.GetRepoID() { t.Errorf("GetRepoID is %v, want %v", test.schedule.GetRepoID(), test.want.GetRepoID()) } + if test.schedule.GetActive() != test.want.GetActive() { t.Errorf("GetActive is %v, want %v", test.schedule.GetActive(), test.want.GetActive()) } + if test.schedule.GetName() != test.want.GetName() { t.Errorf("GetName is %v, want %v", test.schedule.GetName(), test.want.GetName()) } + if test.schedule.GetEntry() != test.want.GetEntry() { t.Errorf("GetEntry is %v, want %v", test.schedule.GetEntry(), test.want.GetEntry()) } + if test.schedule.GetCreatedAt() != test.want.GetCreatedAt() { t.Errorf("GetCreatedAt is %v, want %v", test.schedule.GetCreatedAt(), test.want.GetCreatedAt()) } + if test.schedule.GetCreatedBy() != test.want.GetCreatedBy() { t.Errorf("GetCreatedBy is %v, want %v", test.schedule.GetCreatedBy(), test.want.GetCreatedBy()) } + if test.schedule.GetUpdatedAt() != test.want.GetUpdatedAt() { t.Errorf("GetUpdatedAt is %v, want %v", test.schedule.GetUpdatedAt(), test.want.GetUpdatedAt()) } + if test.schedule.GetUpdatedBy() != test.want.GetUpdatedBy() { t.Errorf("GetUpdatedBy is %v, want %v", test.schedule.GetUpdatedBy(), test.want.GetUpdatedBy()) } + if test.schedule.GetScheduledAt() != test.want.GetScheduledAt() { t.Errorf("GetScheduledAt is %v, want %v", test.schedule.GetScheduledAt(), test.want.GetScheduledAt()) } + if test.schedule.GetBranch() != test.want.GetBranch() { t.Errorf("GetBranch is %v, want %v", test.schedule.GetBranch(), test.want.GetBranch()) } @@ -98,46 +108,57 @@ func TestLibrary_Schedule_Setters(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { test.schedule.SetID(test.want.GetID()) + test.schedule.SetRepoID(test.want.GetRepoID()) + test.schedule.SetActive(test.want.GetActive()) + test.schedule.SetName(test.want.GetName()) + test.schedule.SetEntry(test.want.GetEntry()) + test.schedule.SetCreatedAt(test.want.GetCreatedAt()) + test.schedule.SetCreatedBy(test.want.GetCreatedBy()) + test.schedule.SetUpdatedAt(test.want.GetUpdatedAt()) + test.schedule.SetUpdatedBy(test.want.GetUpdatedBy()) + test.schedule.SetScheduledAt(test.want.GetScheduledAt()) + test.schedule.SetBranch(test.want.GetBranch()) + if test.schedule.GetID() != test.want.GetID() { t.Errorf("SetID is %v, want %v", test.schedule.GetID(), test.want.GetID()) } - test.schedule.SetRepoID(test.want.GetRepoID()) + if test.schedule.GetRepoID() != test.want.GetRepoID() { t.Errorf("SetRepoID is %v, want %v", test.schedule.GetRepoID(), test.want.GetRepoID()) } - test.schedule.SetActive(test.want.GetActive()) + if test.schedule.GetActive() != test.want.GetActive() { t.Errorf("SetActive is %v, want %v", test.schedule.GetActive(), test.want.GetActive()) } - test.schedule.SetName(test.want.GetName()) + if test.schedule.GetName() != test.want.GetName() { t.Errorf("SetName is %v, want %v", test.schedule.GetName(), test.want.GetName()) } - test.schedule.SetEntry(test.want.GetEntry()) + if test.schedule.GetEntry() != test.want.GetEntry() { t.Errorf("SetEntry is %v, want %v", test.schedule.GetEntry(), test.want.GetEntry()) } - test.schedule.SetCreatedAt(test.want.GetCreatedAt()) + if test.schedule.GetCreatedAt() != test.want.GetCreatedAt() { t.Errorf("SetCreatedAt is %v, want %v", test.schedule.GetCreatedAt(), test.want.GetCreatedAt()) } - test.schedule.SetCreatedBy(test.want.GetCreatedBy()) + if test.schedule.GetCreatedBy() != test.want.GetCreatedBy() { t.Errorf("SetCreatedBy is %v, want %v", test.schedule.GetCreatedBy(), test.want.GetCreatedBy()) } - test.schedule.SetUpdatedAt(test.want.GetUpdatedAt()) + if test.schedule.GetUpdatedAt() != test.want.GetUpdatedAt() { t.Errorf("SetUpdatedAt is %v, want %v", test.schedule.GetUpdatedAt(), test.want.GetUpdatedAt()) } - test.schedule.SetUpdatedBy(test.want.GetUpdatedBy()) + if test.schedule.GetUpdatedBy() != test.want.GetUpdatedBy() { t.Errorf("SetUpdatedBy is %v, want %v", test.schedule.GetUpdatedBy(), test.want.GetUpdatedBy()) } - test.schedule.SetScheduledAt(test.want.GetScheduledAt()) + if test.schedule.GetScheduledAt() != test.want.GetScheduledAt() { t.Errorf("SetScheduledAt is %v, want %v", test.schedule.GetScheduledAt(), test.want.GetScheduledAt()) } - test.schedule.SetBranch(test.want.GetBranch()) + if test.schedule.GetBranch() != test.want.GetBranch() { t.Errorf("SetBranch is %v, want %v", test.schedule.GetBranch(), test.want.GetBranch()) } diff --git a/raw/map_test.go b/raw/map_test.go index aec603f4..0494c8ed 100644 --- a/raw/map_test.go +++ b/raw/map_test.go @@ -165,6 +165,7 @@ func TestStringSliceMap_Value(t *testing.T) { t.Errorf("StringSliceMap.Value() error = %v, wantErr %v", err, tt.wantErr) return } + if !reflect.DeepEqual(got, tt.want) { t.Errorf("StringSliceMap.Value() = %v, want %v", got, tt.want) } From e9cd33aaba610598fe582605048533cf78b224ea Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:33:52 -0400 Subject: [PATCH 04/18] enhance(events): add NewEventsFromSlice method (#366) * enhance(events): add NewEventsFromSlice method * linter overlord --- constants/action.go | 3 ++ constants/event.go | 8 ++++ library/events.go | 53 +++++++++++++++++++++++ library/events_test.go | 96 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+) diff --git a/constants/action.go b/constants/action.go index f1e18c6e..802ddf79 100644 --- a/constants/action.go +++ b/constants/action.go @@ -30,4 +30,7 @@ const ( // ActionTag defines the action for deleting a tag. ActionTag = "tag" + + // ActionRun defines the action for running a schedule. + ActionRun = "run" ) diff --git a/constants/event.go b/constants/event.go index 9d59f7e5..c2ec26aa 100644 --- a/constants/event.go +++ b/constants/event.go @@ -27,4 +27,12 @@ const ( // EventTag defines the event type for build and repo tag events. EventTag = "tag" + + // Alternates for common user inputs that do not match our set constants. + + // EventPullAlternate defines the alternate event type for build and repo pull_request events. + EventPullAlternate = "pull" + + // EventDeployAlternate defines the alternate event type for build and repo deployment events. + EventDeployAlternate = "deploy" ) diff --git a/library/events.go b/library/events.go index 88074d80..45f1f908 100644 --- a/library/events.go +++ b/library/events.go @@ -37,6 +37,59 @@ func NewEventsFromMask(mask int64) *Events { return e } +// NewEventsFromSlice is an instantiation function for the Events type that +// takes in a slice of event strings and populates the nested Events struct. +func NewEventsFromSlice(events []string) *Events { + mask := int64(0) + + // iterate through all events provided + for _, event := range events { + switch event { + // push actions + case constants.EventPush, constants.EventPush + ":branch": + mask = mask | constants.AllowPushBranch + case constants.EventTag, constants.EventPush + ":" + constants.EventTag: + mask = mask | constants.AllowPushTag + case constants.EventDelete + ":" + constants.ActionBranch: + mask = mask | constants.AllowPushDeleteBranch + case constants.EventDelete + ":" + constants.ActionTag: + mask = mask | constants.AllowPushDeleteTag + case constants.EventDelete: + mask = mask | constants.AllowPushDeleteBranch | constants.AllowPushDeleteTag + + // pull_request actions + case constants.EventPull, constants.EventPullAlternate: + mask = mask | constants.AllowPullOpen | constants.AllowPullSync | constants.AllowPullReopen + case constants.EventPull + ":" + constants.ActionOpened: + mask = mask | constants.AllowPullOpen + case constants.EventPull + ":" + constants.ActionEdited: + mask = mask | constants.AllowPullEdit + case constants.EventPull + ":" + constants.ActionSynchronize: + mask = mask | constants.AllowPullSync + case constants.EventPull + ":" + constants.ActionReopened: + mask = mask | constants.AllowPullReopen + + // deployment actions + case constants.EventDeploy, constants.EventDeployAlternate, constants.EventDeploy + ":" + constants.ActionCreated: + mask = mask | constants.AllowDeployCreate + + // comment actions + case constants.EventComment: + mask = mask | constants.AllowCommentCreate | constants.AllowCommentEdit + case constants.EventComment + ":" + constants.ActionCreated: + mask = mask | constants.AllowCommentCreate + case constants.EventComment + ":" + constants.ActionEdited: + mask = mask | constants.AllowCommentEdit + + // schedule actions + case constants.EventSchedule, constants.EventSchedule + ":" + constants.ActionRun: + mask = mask | constants.AllowSchedule + } + } + + return NewEventsFromMask(mask) +} + // Allowed determines whether or not an event + action is allowed based on whether // its event:action is set to true in the Events struct. func (e *Events) Allowed(event, action string) bool { diff --git a/library/events_test.go b/library/events_test.go index a26cc4dc..ef60257b 100644 --- a/library/events_test.go +++ b/library/events_test.go @@ -194,6 +194,102 @@ func TestLibrary_Events_NewEventsFromMask_ToDatabase(t *testing.T) { } } +func Test_NewEventsFromSlice(t *testing.T) { + // setup types + tBool := true + fBool := false + + e1, e2 := testEvents() + + // setup tests + tests := []struct { + name string + events []string + want *Events + }{ + { + name: "action specific events to e1", + events: []string{"push:branch", "push:tag", "delete:branch", "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", "comment:created", "schedule:run"}, + want: e1, + }, + { + name: "action specific events to e2", + events: []string{"delete:tag", "pull_request:edited", "deployment:created", "comment:edited"}, + want: e2, + }, + { + name: "general events", + events: []string{"push", "pull", "deploy", "comment", "schedule", "tag", "delete"}, + want: &Events{ + Push: &actions.Push{ + Branch: &tBool, + Tag: &tBool, + DeleteBranch: &tBool, + DeleteTag: &tBool, + }, + PullRequest: &actions.Pull{ + Opened: &tBool, + Reopened: &tBool, + Edited: &fBool, + Synchronize: &tBool, + }, + Deployment: &actions.Deploy{ + Created: &tBool, + }, + Comment: &actions.Comment{ + Created: &tBool, + Edited: &tBool, + }, + Schedule: &actions.Schedule{ + Run: &tBool, + }, + }, + }, + { + name: "double events", + events: []string{"push", "push:branch", "pull_request", "pull_request:opened"}, + want: &Events{ + Push: &actions.Push{ + Branch: &tBool, + Tag: &fBool, + DeleteBranch: &fBool, + DeleteTag: &fBool, + }, + PullRequest: &actions.Pull{ + Opened: &tBool, + Reopened: &tBool, + Edited: &fBool, + Synchronize: &tBool, + }, + Deployment: &actions.Deploy{ + Created: &fBool, + }, + Comment: &actions.Comment{ + Created: &fBool, + Edited: &fBool, + }, + Schedule: &actions.Schedule{ + Run: &fBool, + }, + }, + }, + { + name: "empty events", + events: []string{}, + want: NewEventsFromMask(0), + }, + } + + // run tests + for _, test := range tests { + got := NewEventsFromSlice(test.events) + + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("PopulateEvents failed for %s mismatch (-want +got):\n%s", test.name, diff) + } + } +} + func TestLibrary_Events_Allowed(t *testing.T) { // setup types eventsOne, eventsTwo := testEvents() From a7d60dfaa326f04f794cabf74131e83c8c02fe83 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 12:48:07 -0500 Subject: [PATCH 05/18] fix(deps): update all non-major dependencies (#364) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0cd1c7b9..ca4a3929 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,7 +47,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + uses: github/codeql-action/init@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -58,7 +58,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + uses: github/codeql-action/autobuild@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -72,4 +72,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7 + uses: github/codeql-action/analyze@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 diff --git a/go.mod b/go.mod index fe0ced70..14587f80 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/go-vela/types go 1.21 require ( - github.com/adhocore/gronx v1.8.0 + github.com/adhocore/gronx v1.8.1 github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3 github.com/drone/envsubst v1.0.3 github.com/ghodss/yaml v1.0.0 diff --git a/go.sum b/go.sum index bfcde40c..00c3fd42 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/adhocore/gronx v1.8.0 h1:BHgzaGyS7zPmuMVqiIxyAwvKpwAX+bR7bCxDVacfhuo= -github.com/adhocore/gronx v1.8.0/go.mod h1:7oUY1WAU8rEJWmAxXR2DN0JaO4gi9khSgKjiRypqteg= +github.com/adhocore/gronx v1.8.1 h1:F2mLTG5sB11z7vplwD4iydz3YCEjstSfYmCrdSm3t6A= +github.com/adhocore/gronx v1.8.1/go.mod h1:7oUY1WAU8rEJWmAxXR2DN0JaO4gi9khSgKjiRypqteg= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3 h1:q+sMKdA6L8LyGVudTkpGoC73h6ak2iWSPFiFo/pFOU8= From 476edfa844f0dc306d1a4c8f78e2da71362969bc Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:15:42 -0400 Subject: [PATCH 06/18] adding some fields (#367) Co-authored-by: David May <49894298+wass3rw3rk@users.noreply.github.com> --- constants/limit.go | 3 +++ database/step.go | 9 +++++++++ database/step_test.go | 4 ++++ library/step.go | 40 +++++++++++++++++++++++++++++++++++++- library/step_test.go | 21 +++++++++++++++++--- pipeline/container.go | 4 +++- pipeline/container_test.go | 1 + yaml/step.go | 2 ++ yaml/step_test.go | 9 ++++++--- yaml/testdata/step.yml | 1 + 10 files changed, 86 insertions(+), 8 deletions(-) diff --git a/constants/limit.go b/constants/limit.go index c6f2532c..c1a4ac95 100644 --- a/constants/limit.go +++ b/constants/limit.go @@ -33,4 +33,7 @@ const ( // DeployBuildsMaxSize defines the maximum size in characters for deployment builds. DeployBuildsMaxSize = 500 + + // ReportStepStatusLimit defines the maximum number of steps in a pipeline that may report their status to the SCM. + ReportStepStatusLimit = 10 ) diff --git a/database/step.go b/database/step.go index 318407e1..34304168 100644 --- a/database/step.go +++ b/database/step.go @@ -49,6 +49,7 @@ type Step struct { Host sql.NullString `sql:"host"` Runtime sql.NullString `sql:"runtime"` Distribution sql.NullString `sql:"distribution"` + ReportAs sql.NullString `sql:"report_as"` } // Nullify ensures the valid flag for @@ -142,6 +143,11 @@ func (s *Step) Nullify() *Step { s.Distribution.Valid = false } + // check if the ReportAs field should be false + if len(s.ReportAs.String) == 0 { + s.ReportAs.Valid = false + } + return s } @@ -166,6 +172,7 @@ func (s *Step) ToLibrary() *library.Step { step.SetHost(s.Host.String) step.SetRuntime(s.Runtime.String) step.SetDistribution(s.Distribution.String) + step.SetReportAs(s.ReportAs.String) return step } @@ -209,6 +216,7 @@ func (s *Step) Validate() error { s.Host = sql.NullString{String: sanitize(s.Host.String), Valid: s.Host.Valid} s.Runtime = sql.NullString{String: sanitize(s.Runtime.String), Valid: s.Runtime.Valid} s.Distribution = sql.NullString{String: sanitize(s.Distribution.String), Valid: s.Distribution.Valid} + s.ReportAs = sql.NullString{String: sanitize(s.ReportAs.String), Valid: s.ReportAs.Valid} return nil } @@ -233,6 +241,7 @@ func StepFromLibrary(s *library.Step) *Step { Host: sql.NullString{String: s.GetHost(), Valid: true}, Runtime: sql.NullString{String: s.GetRuntime(), Valid: true}, Distribution: sql.NullString{String: s.GetDistribution(), Valid: true}, + ReportAs: sql.NullString{String: s.GetReportAs(), Valid: true}, } return step.Nullify() diff --git a/database/step_test.go b/database/step_test.go index 90d10a51..270f939b 100644 --- a/database/step_test.go +++ b/database/step_test.go @@ -31,6 +31,7 @@ func TestDatabase_Step_Nullify(t *testing.T) { Host: sql.NullString{String: "", Valid: false}, Runtime: sql.NullString{String: "", Valid: false}, Distribution: sql.NullString{String: "", Valid: false}, + ReportAs: sql.NullString{String: "", Valid: false}, } // setup tests @@ -82,6 +83,7 @@ func TestDatabase_Step_ToLibrary(t *testing.T) { want.SetHost("example.company.com") want.SetRuntime("docker") want.SetDistribution("linux") + want.SetReportAs("test") // run test got := testStep().ToLibrary() @@ -191,6 +193,7 @@ func TestDatabase_StepFromLibrary(t *testing.T) { s.SetHost("example.company.com") s.SetRuntime("docker") s.SetDistribution("linux") + s.SetReportAs("test") want := testStep() @@ -222,5 +225,6 @@ func testStep() *Step { Host: sql.NullString{String: "example.company.com", Valid: true}, Runtime: sql.NullString{String: "docker", Valid: true}, Distribution: sql.NullString{String: "linux", Valid: true}, + ReportAs: sql.NullString{String: "test", Valid: true}, } } diff --git a/library/step.go b/library/step.go index 5dfa8aee..bf33ae5c 100644 --- a/library/step.go +++ b/library/step.go @@ -31,6 +31,7 @@ type Step struct { Host *string `json:"host,omitempty"` Runtime *string `json:"runtime,omitempty"` Distribution *string `json:"distribution,omitempty"` + ReportAs *string `json:"report_as,omitempty"` } // Duration calculates and returns the total amount of @@ -78,6 +79,7 @@ func (s *Step) Environment() map[string]string { "VELA_STEP_STAGE": ToString(s.GetStage()), "VELA_STEP_STARTED": ToString(s.GetStarted()), "VELA_STEP_STATUS": ToString(s.GetStatus()), + "VELA_STEP_REPORT_AS": ToString(s.GetReportAs()), } } @@ -289,6 +291,19 @@ func (s *Step) GetDistribution() string { return *s.Distribution } +// GetReportAs returns the ReportAs field. +// +// When the provided Step type is nil, or the field within +// the type is nil, it returns the zero value for the field. +func (s *Step) GetReportAs() string { + // return zero value if Step type or ReportAs field is nil + if s == nil || s.ReportAs == nil { + return "" + } + + return *s.ReportAs +} + // SetID sets the ID field. // // When the provided Step type is nil, it @@ -484,7 +499,7 @@ func (s *Step) SetRuntime(v string) { s.Runtime = &v } -// SetDistribution sets the Runtime field. +// SetDistribution sets the Distribution field. // // When the provided Step type is nil, it // will set nothing and immediately return. @@ -497,6 +512,19 @@ func (s *Step) SetDistribution(v string) { s.Distribution = &v } +// SetReportAs sets the ReportAs field. +// +// When the provided Step type is nil, it +// will set nothing and immediately return. +func (s *Step) SetReportAs(v string) { + // return if Step type is nil + if s == nil { + return + } + + s.ReportAs = &v +} + // String implements the Stringer interface for the Step type. func (s *Step) String() string { return fmt.Sprintf(`{ @@ -512,6 +540,7 @@ func (s *Step) String() string { Name: %s, Number: %d, RepoID: %d, + ReportAs: %s, Runtime: %s, Stage: %s, Started: %d, @@ -529,6 +558,7 @@ func (s *Step) String() string { s.GetName(), s.GetNumber(), s.GetRepoID(), + s.GetReportAs(), s.GetRuntime(), s.GetStage(), s.GetStarted(), @@ -558,6 +588,7 @@ func StepFromBuildContainer(build *Build, ctn *pipeline.Container) *Step { s.SetName(ctn.Name) s.SetNumber(ctn.Number) s.SetImage(ctn.Image) + s.SetReportAs(ctn.ReportAs) // check if the VELA_STEP_STAGE environment variable exists value, ok := ctn.Environment["VELA_STEP_STAGE"] @@ -609,6 +640,13 @@ func StepFromContainerEnvironment(ctn *pipeline.Container) *Step { s.SetName(value) } + // check if the VELA_STEP_REPORT_AS environment variable exists + value, ok = ctn.Environment["VELA_STEP_REPORT_AS"] + if ok { + // set the ReportAs field to the value from environment variable + s.SetReportAs(value) + } + // check if the VELA_STEP_RUNTIME environment variable exists value, ok = ctn.Environment["VELA_STEP_RUNTIME"] if ok { diff --git a/library/step_test.go b/library/step_test.go index 60446d4e..ba73dc6e 100644 --- a/library/step_test.go +++ b/library/step_test.go @@ -55,6 +55,7 @@ func TestLibrary_Step_Environment(t *testing.T) { "VELA_STEP_IMAGE": "target/vela-git:v0.3.0", "VELA_STEP_NAME": "clone", "VELA_STEP_NUMBER": "1", + "VELA_STEP_REPORT_AS": "test", "VELA_STEP_RUNTIME": "docker", "VELA_STEP_STAGE": "", "VELA_STEP_STARTED": "1563474078", @@ -150,6 +151,10 @@ func TestLibrary_Step_Getters(t *testing.T) { if test.step.GetDistribution() != test.want.GetDistribution() { t.Errorf("GetDistribution is %v, want %v", test.step.GetDistribution(), test.want.GetDistribution()) } + + if test.step.GetReportAs() != test.want.GetReportAs() { + t.Errorf("GetReportAs is %v, want %v", test.step.GetReportAs(), test.want.GetReportAs()) + } } } @@ -190,6 +195,7 @@ func TestLibrary_Step_Setters(t *testing.T) { test.step.SetHost(test.want.GetHost()) test.step.SetRuntime(test.want.GetRuntime()) test.step.SetDistribution(test.want.GetDistribution()) + test.step.SetReportAs(test.want.GetReportAs()) if test.step.GetID() != test.want.GetID() { t.Errorf("SetID is %v, want %v", test.step.GetID(), test.want.GetID()) @@ -254,6 +260,10 @@ func TestLibrary_Step_Setters(t *testing.T) { if test.step.GetDistribution() != test.want.GetDistribution() { t.Errorf("SetDistribution is %v, want %v", test.step.GetDistribution(), test.want.GetDistribution()) } + + if test.step.GetReportAs() != test.want.GetReportAs() { + t.Errorf("SetReportAs is %v, want %v", test.step.GetReportAs(), test.want.GetReportAs()) + } } } @@ -274,6 +284,7 @@ func TestLibrary_Step_String(t *testing.T) { Name: %s, Number: %d, RepoID: %d, + ReportAs: %s, Runtime: %s, Stage: %s, Started: %d, @@ -291,6 +302,7 @@ func TestLibrary_Step_String(t *testing.T) { s.GetName(), s.GetNumber(), s.GetRepoID(), + s.GetReportAs(), s.GetRuntime(), s.GetStage(), s.GetStarted(), @@ -363,9 +375,10 @@ func TestLibrary_StepFromBuildContainer(t *testing.T) { { name: "container with build", container: &pipeline.Container{ - Name: s.GetName(), - Number: s.GetNumber(), - Image: s.GetImage(), + Name: s.GetName(), + Number: s.GetNumber(), + Image: s.GetImage(), + ReportAs: s.GetReportAs(), Environment: map[string]string{ "VELA_STEP_STAGE": "clone", }, @@ -423,6 +436,7 @@ func TestLibrary_StepFromContainerEnvironment(t *testing.T) { "VELA_STEP_IMAGE": "target/vela-git:v0.3.0", "VELA_STEP_NAME": "clone", "VELA_STEP_NUMBER": "1", + "VELA_STEP_REPORT_AS": "test", "VELA_STEP_RUNTIME": "docker", "VELA_STEP_STAGE": "clone", "VELA_STEP_STARTED": "1563474078", @@ -462,6 +476,7 @@ func testStep() *Step { s.SetHost("example.company.com") s.SetRuntime("docker") s.SetDistribution("linux") + s.SetReportAs("test") return s } diff --git a/pipeline/container.go b/pipeline/container.go index 3ada27a0..fcd12080 100644 --- a/pipeline/container.go +++ b/pipeline/container.go @@ -51,6 +51,7 @@ type ( Ulimits UlimitSlice `json:"ulimits,omitempty" yaml:"ulimits,omitempty"` Volumes VolumeSlice `json:"volumes,omitempty" yaml:"volumes,omitempty"` User string `json:"user,omitempty" yaml:"user,omitempty"` + ReportAs string `json:"report_as,omitempty" yaml:"report_as,omitempty"` } ) @@ -133,7 +134,8 @@ func (c *Container) Empty() bool { len(c.Secrets) == 0 && len(c.Ulimits) == 0 && len(c.Volumes) == 0 && - len(c.User) == 0 { + len(c.User) == 0 && + len(c.ReportAs) == 0 { return true } diff --git a/pipeline/container_test.go b/pipeline/container_test.go index 2f814ba7..ba08cd2b 100644 --- a/pipeline/container_test.go +++ b/pipeline/container_test.go @@ -917,6 +917,7 @@ func testContainers() *ContainerSlice { Name: "echo", Number: 3, Pull: "always", + ReportAs: "echo-step", Ruleset: Ruleset{ If: Rules{Event: []string{"push"}}, Operator: "and", diff --git a/yaml/step.go b/yaml/step.go index 82232143..396a3b74 100644 --- a/yaml/step.go +++ b/yaml/step.go @@ -34,6 +34,7 @@ type ( Detach bool `yaml:"detach,omitempty" json:"detach,omitempty" jsonschema:"description=Run the container in a detached (headless) state.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-detach-tag"` Privileged bool `yaml:"privileged,omitempty" json:"privileged,omitempty" jsonschema:"description=Run the container with extra privileges.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-privileged-tag"` User string `yaml:"user,omitempty" json:"user,omitempty" jsonschema:"description=Set the user for the container.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-user-tag"` + ReportAs string `yaml:"report_as,omitempty" json:"report_as,omitempty" jsonschema:"description=Set the name of the step to report as.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-report_as-tag"` } ) @@ -60,6 +61,7 @@ func (s *StepSlice) ToPipeline() *pipeline.ContainerSlice { Ulimits: *step.Ulimits.ToPipeline(), Volumes: *step.Volumes.ToPipeline(), User: step.User, + ReportAs: step.ReportAs, }) } diff --git a/yaml/step_test.go b/yaml/step_test.go index e1cead4c..2d0b6034 100644 --- a/yaml/step_test.go +++ b/yaml/step_test.go @@ -30,6 +30,7 @@ func TestYaml_StepSlice_ToPipeline(t *testing.T) { Name: "echo", Privileged: false, Pull: "not_present", + ReportAs: "my-step", Ruleset: Ruleset{ If: Rules{ Branch: []string{"main"}, @@ -86,6 +87,7 @@ func TestYaml_StepSlice_ToPipeline(t *testing.T) { Name: "echo", Privileged: false, Pull: "not_present", + ReportAs: "my-step", Ruleset: pipeline.Ruleset{ If: pipeline.Rules{ Branch: []string{"main"}, @@ -187,9 +189,10 @@ func TestYaml_StepSlice_UnmarshalYAML(t *testing.T) { Pull: "always", }, { - Name: "docker_build", - Image: "plugins/docker:18.09", - Pull: "always", + Name: "docker_build", + Image: "plugins/docker:18.09", + Pull: "always", + ReportAs: "docker", Parameters: map[string]interface{}{ "registry": "index.docker.io", "repo": "github/octocat", diff --git a/yaml/testdata/step.yml b/yaml/testdata/step.yml index 5dd49e3e..1d6d9cc9 100644 --- a/yaml/testdata/step.yml +++ b/yaml/testdata/step.yml @@ -28,6 +28,7 @@ - name: docker_build image: plugins/docker:18.09 + report_as: docker parameters: registry: index.docker.io repo: github/octocat From 9b43c701ab32de45621c489ecc9afcc694f0cd2e Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Mon, 1 Apr 2024 09:22:28 -0400 Subject: [PATCH 07/18] chore: delete legacy allow event fields and methods (#362) --- database/repo.go | 15 ---- database/repo_test.go | 15 ---- database/secret.go | 9 -- database/secret_test.go | 3 - item_test.go | 8 -- library/repo.go | 179 +++------------------------------------- library/repo_test.go | 126 +++++++--------------------- library/secret.go | 30 ------- library/secret_test.go | 12 --- 9 files changed, 40 insertions(+), 357 deletions(-) diff --git a/database/repo.go b/database/repo.go index 8fde8286..03a3d22c 100644 --- a/database/repo.go +++ b/database/repo.go @@ -61,11 +61,6 @@ type Repo struct { Private sql.NullBool `sql:"private"` Trusted sql.NullBool `sql:"trusted"` Active sql.NullBool `sql:"active"` - AllowPull sql.NullBool `sql:"allow_pull"` - AllowPush sql.NullBool `sql:"allow_push"` - AllowDeploy sql.NullBool `sql:"allow_deploy"` - AllowTag sql.NullBool `sql:"allow_tag"` - AllowComment sql.NullBool `sql:"allow_comment"` AllowEvents sql.NullInt64 `sql:"allow_events"` PipelineType sql.NullString `sql:"pipeline_type"` PreviousName sql.NullString `sql:"previous_name"` @@ -235,11 +230,6 @@ func (r *Repo) ToLibrary() *library.Repo { repo.SetPrivate(r.Private.Bool) repo.SetTrusted(r.Trusted.Bool) repo.SetActive(r.Active.Bool) - repo.SetAllowPull(r.AllowPull.Bool) - repo.SetAllowPush(r.AllowPush.Bool) - repo.SetAllowDeploy(r.AllowDeploy.Bool) - repo.SetAllowTag(r.AllowTag.Bool) - repo.SetAllowComment(r.AllowComment.Bool) repo.SetAllowEvents(library.NewEventsFromMask(r.AllowEvents.Int64)) repo.SetPipelineType(r.PipelineType.String) repo.SetPreviousName(r.PreviousName.String) @@ -332,11 +322,6 @@ func RepoFromLibrary(r *library.Repo) *Repo { Private: sql.NullBool{Bool: r.GetPrivate(), Valid: true}, Trusted: sql.NullBool{Bool: r.GetTrusted(), Valid: true}, Active: sql.NullBool{Bool: r.GetActive(), Valid: true}, - AllowPull: sql.NullBool{Bool: r.GetAllowPull(), Valid: true}, - AllowPush: sql.NullBool{Bool: r.GetAllowPush(), Valid: true}, - AllowDeploy: sql.NullBool{Bool: r.GetAllowDeploy(), Valid: true}, - AllowTag: sql.NullBool{Bool: r.GetAllowTag(), Valid: true}, - AllowComment: sql.NullBool{Bool: r.GetAllowComment(), Valid: true}, AllowEvents: sql.NullInt64{Int64: r.GetAllowEvents().ToDatabase(), Valid: true}, PipelineType: sql.NullString{String: r.GetPipelineType(), Valid: true}, PreviousName: sql.NullString{String: r.GetPreviousName(), Valid: true}, diff --git a/database/repo_test.go b/database/repo_test.go index 3aa63fca..22dbed0d 100644 --- a/database/repo_test.go +++ b/database/repo_test.go @@ -175,11 +175,6 @@ func TestDatabase_Repo_ToLibrary(t *testing.T) { want.SetPrivate(false) want.SetTrusted(false) want.SetActive(true) - want.SetAllowPull(false) - want.SetAllowPush(true) - want.SetAllowDeploy(false) - want.SetAllowTag(false) - want.SetAllowComment(false) want.SetAllowEvents(e) want.SetPipelineType("yaml") want.SetPreviousName("oldName") @@ -332,11 +327,6 @@ func TestDatabase_RepoFromLibrary(t *testing.T) { r.SetPrivate(false) r.SetTrusted(false) r.SetActive(true) - r.SetAllowPull(false) - r.SetAllowPush(true) - r.SetAllowDeploy(false) - r.SetAllowTag(false) - r.SetAllowComment(false) r.SetAllowEvents(e) r.SetPipelineType("yaml") r.SetPreviousName("oldName") @@ -373,11 +363,6 @@ func testRepo() *Repo { Private: sql.NullBool{Bool: false, Valid: true}, Trusted: sql.NullBool{Bool: false, Valid: true}, Active: sql.NullBool{Bool: true, Valid: true}, - AllowPull: sql.NullBool{Bool: false, Valid: true}, - AllowPush: sql.NullBool{Bool: true, Valid: true}, - AllowDeploy: sql.NullBool{Bool: false, Valid: true}, - AllowTag: sql.NullBool{Bool: false, Valid: true}, - AllowComment: sql.NullBool{Bool: false, Valid: true}, AllowEvents: sql.NullInt64{Int64: 1, Valid: true}, PipelineType: sql.NullString{String: "yaml", Valid: true}, PreviousName: sql.NullString{String: "oldName", Valid: true}, diff --git a/database/secret.go b/database/secret.go index a8e6c0e7..1c93cf85 100644 --- a/database/secret.go +++ b/database/secret.go @@ -50,7 +50,6 @@ type Secret struct { Value sql.NullString `sql:"value"` Type sql.NullString `sql:"type"` Images pq.StringArray `sql:"images" gorm:"type:varchar(1000)"` - Events pq.StringArray `sql:"events" gorm:"type:varchar(1000)"` AllowEvents sql.NullInt64 `sql:"allow_events"` AllowCommand sql.NullBool `sql:"allow_command"` AllowSubstitution sql.NullBool `sql:"allow_substitution"` @@ -194,7 +193,6 @@ func (s *Secret) ToLibrary() *library.Secret { secret.SetValue(s.Value.String) secret.SetType(s.Type.String) secret.SetImages(s.Images) - secret.SetEvents(s.Events) secret.SetAllowEvents(library.NewEventsFromMask(s.AllowEvents.Int64)) secret.SetAllowCommand(s.AllowCommand.Bool) secret.SetAllowSubstitution(s.AllowSubstitution.Bool) @@ -261,12 +259,6 @@ func (s *Secret) Validate() error { s.Images[i] = sanitize(v) } - // ensure that all Events are sanitized - // to avoid unsafe HTML content - for i, v := range s.Events { - s.Events[i] = sanitize(v) - } - return nil } @@ -282,7 +274,6 @@ func SecretFromLibrary(s *library.Secret) *Secret { Value: sql.NullString{String: s.GetValue(), Valid: true}, Type: sql.NullString{String: s.GetType(), Valid: true}, Images: pq.StringArray(s.GetImages()), - Events: pq.StringArray(s.GetEvents()), AllowEvents: sql.NullInt64{Int64: s.GetAllowEvents().ToDatabase(), Valid: true}, AllowCommand: sql.NullBool{Bool: s.GetAllowCommand(), Valid: true}, AllowSubstitution: sql.NullBool{Bool: s.GetAllowSubstitution(), Valid: true}, diff --git a/database/secret_test.go b/database/secret_test.go index 6c61ec44..d44a1265 100644 --- a/database/secret_test.go +++ b/database/secret_test.go @@ -168,7 +168,6 @@ func TestDatabase_Secret_ToLibrary(t *testing.T) { want.SetValue("bar") want.SetType("repo") want.SetImages([]string{"alpine"}) - want.SetEvents([]string{"push", "tag", "deployment"}) want.SetAllowEvents(library.NewEventsFromMask(1)) want.SetAllowCommand(true) want.SetAllowSubstitution(true) @@ -293,7 +292,6 @@ func TestDatabase_SecretFromLibrary(t *testing.T) { s.SetValue("bar") s.SetType("repo") s.SetImages([]string{"alpine"}) - s.SetEvents([]string{"push", "tag", "deployment"}) s.SetAllowEvents(library.NewEventsFromMask(1)) s.SetAllowCommand(true) s.SetAllowSubstitution(true) @@ -324,7 +322,6 @@ func testSecret() *Secret { Value: sql.NullString{String: "bar", Valid: true}, Type: sql.NullString{String: "repo", Valid: true}, Images: []string{"alpine"}, - Events: []string{"push", "tag", "deployment"}, AllowEvents: sql.NullInt64{Int64: 1, Valid: true}, AllowCommand: sql.NullBool{Bool: true, Valid: true}, AllowSubstitution: sql.NullBool{Bool: true, Valid: true}, diff --git a/item_test.go b/item_test.go index 8643f3e1..245ebf95 100644 --- a/item_test.go +++ b/item_test.go @@ -55,10 +55,6 @@ func TestTypes_ToItem(t *testing.T) { Private: &booL, Trusted: &booL, Active: &booL, - AllowPull: &booL, - AllowPush: &booL, - AllowDeploy: &booL, - AllowTag: &booL, AllowEvents: e, } u := &library.User{ @@ -107,10 +103,6 @@ func TestTypes_ToItem(t *testing.T) { Private: &booL, Trusted: &booL, Active: &booL, - AllowPull: &booL, - AllowPush: &booL, - AllowDeploy: &booL, - AllowTag: &booL, AllowEvents: e, }, User: &library.User{ diff --git a/library/repo.go b/library/repo.go index 845028b9..0f82207b 100644 --- a/library/repo.go +++ b/library/repo.go @@ -28,11 +28,6 @@ type Repo struct { Private *bool `json:"private,omitempty"` Trusted *bool `json:"trusted,omitempty"` Active *bool `json:"active,omitempty"` - AllowPull *bool `json:"allow_pull,omitempty"` - AllowPush *bool `json:"allow_push,omitempty"` - AllowDeploy *bool `json:"allow_deploy,omitempty"` - AllowTag *bool `json:"allow_tag,omitempty"` - AllowComment *bool `json:"allow_comment,omitempty"` AllowEvents *Events `json:"allow_events,omitempty"` PipelineType *string `json:"pipeline_type,omitempty"` PreviousName *string `json:"previous_name,omitempty"` @@ -44,11 +39,6 @@ type Repo struct { func (r *Repo) Environment() map[string]string { return map[string]string{ "VELA_REPO_ACTIVE": ToString(r.GetActive()), - "VELA_REPO_ALLOW_COMMENT": ToString(r.GetAllowComment()), - "VELA_REPO_ALLOW_DEPLOY": ToString(r.GetAllowDeploy()), - "VELA_REPO_ALLOW_PULL": ToString(r.GetAllowPull()), - "VELA_REPO_ALLOW_PUSH": ToString(r.GetAllowPush()), - "VELA_REPO_ALLOW_TAG": ToString(r.GetAllowTag()), "VELA_REPO_ALLOW_EVENTS": strings.Join(r.GetAllowEvents().List()[:], ","), "VELA_REPO_BRANCH": ToString(r.GetBranch()), "VELA_REPO_TOPICS": strings.Join(r.GetTopics()[:], ","), @@ -66,23 +56,18 @@ func (r *Repo) Environment() map[string]string { "VELA_REPO_APPROVE_BUILD": ToString(r.GetApproveBuild()), // deprecated environment variables - "REPOSITORY_ACTIVE": ToString(r.GetActive()), - "REPOSITORY_ALLOW_COMMENT": ToString(r.GetAllowComment()), - "REPOSITORY_ALLOW_DEPLOY": ToString(r.GetAllowDeploy()), - "REPOSITORY_ALLOW_PULL": ToString(r.GetAllowPull()), - "REPOSITORY_ALLOW_PUSH": ToString(r.GetAllowPush()), - "REPOSITORY_ALLOW_TAG": ToString(r.GetAllowTag()), - "REPOSITORY_ALLOW_EVENTS": strings.Join(r.GetAllowEvents().List()[:], ","), - "REPOSITORY_BRANCH": ToString(r.GetBranch()), - "REPOSITORY_CLONE": ToString(r.GetClone()), - "REPOSITORY_FULL_NAME": ToString(r.GetFullName()), - "REPOSITORY_LINK": ToString(r.GetLink()), - "REPOSITORY_NAME": ToString(r.GetName()), - "REPOSITORY_ORG": ToString(r.GetOrg()), - "REPOSITORY_PRIVATE": ToString(r.GetPrivate()), - "REPOSITORY_TIMEOUT": ToString(r.GetTimeout()), - "REPOSITORY_TRUSTED": ToString(r.GetTrusted()), - "REPOSITORY_VISIBILITY": ToString(r.GetVisibility()), + "REPOSITORY_ACTIVE": ToString(r.GetActive()), + "REPOSITORY_ALLOW_EVENTS": strings.Join(r.GetAllowEvents().List()[:], ","), + "REPOSITORY_BRANCH": ToString(r.GetBranch()), + "REPOSITORY_CLONE": ToString(r.GetClone()), + "REPOSITORY_FULL_NAME": ToString(r.GetFullName()), + "REPOSITORY_LINK": ToString(r.GetLink()), + "REPOSITORY_NAME": ToString(r.GetName()), + "REPOSITORY_ORG": ToString(r.GetOrg()), + "REPOSITORY_PRIVATE": ToString(r.GetPrivate()), + "REPOSITORY_TIMEOUT": ToString(r.GetTimeout()), + "REPOSITORY_TRUSTED": ToString(r.GetTrusted()), + "REPOSITORY_VISIBILITY": ToString(r.GetVisibility()), } } @@ -307,71 +292,6 @@ func (r *Repo) GetActive() bool { return *r.Active } -// GetAllowPull returns the AllowPull field. -// -// When the provided Repo type is nil, or the field within -// the type is nil, it returns the zero value for the field. -func (r *Repo) GetAllowPull() bool { - // return zero value if Repo type or AllowPull field is nil - if r == nil || r.AllowPull == nil { - return false - } - - return *r.AllowPull -} - -// GetAllowPush returns the AllowPush field. -// -// When the provided Repo type is nil, or the field within -// the type is nil, it returns the zero value for the field. -func (r *Repo) GetAllowPush() bool { - // return zero value if Repo type or AllowPush field is nil - if r == nil || r.AllowPush == nil { - return false - } - - return *r.AllowPush -} - -// GetAllowDeploy returns the AllowDeploy field. -// -// When the provided Repo type is nil, or the field within -// the type is nil, it returns the zero value for the field. -func (r *Repo) GetAllowDeploy() bool { - // return zero value if Repo type or AllowDeploy field is nil - if r == nil || r.AllowDeploy == nil { - return false - } - - return *r.AllowDeploy -} - -// GetAllowTag returns the AllowTag field. -// -// When the provided Repo type is nil, or the field within -// the type is nil, it returns the zero value for the field. -func (r *Repo) GetAllowTag() bool { - // return zero value if Repo type or AllowTag field is nil - if r == nil || r.AllowTag == nil { - return false - } - - return *r.AllowTag -} - -// GetAllowComment returns the AllowComment field. -// -// When the provided Repo type is nil, or the field within -// the type is nil, it returns the zero value for the field. -func (r *Repo) GetAllowComment() bool { - // return zero value if Repo type or AllowComment field is nil - if r == nil || r.AllowComment == nil { - return false - } - - return *r.AllowComment -} - // GetAllowEvents returns the AllowEvents field. // // When the provided Repo type is nil, or the field within @@ -645,71 +565,6 @@ func (r *Repo) SetActive(v bool) { r.Active = &v } -// SetAllowPull sets the AllowPull field. -// -// When the provided Repo type is nil, it -// will set nothing and immediately return. -func (r *Repo) SetAllowPull(v bool) { - // return if Repo type is nil - if r == nil { - return - } - - r.AllowPull = &v -} - -// SetAllowPush sets the AllowPush field. -// -// When the provided Repo type is nil, it -// will set nothing and immediately return. -func (r *Repo) SetAllowPush(v bool) { - // return if Repo type is nil - if r == nil { - return - } - - r.AllowPush = &v -} - -// SetAllowDeploy sets the AllowDeploy field. -// -// When the provided Repo type is nil, it -// will set nothing and immediately return. -func (r *Repo) SetAllowDeploy(v bool) { - // return if Repo type is nil - if r == nil { - return - } - - r.AllowDeploy = &v -} - -// SetAllowTag sets the AllowTag field. -// -// When the provided Repo type is nil, it -// will set nothing and immediately return. -func (r *Repo) SetAllowTag(v bool) { - // return if Repo type is nil - if r == nil { - return - } - - r.AllowTag = &v -} - -// SetAllowComment sets the AllowComment field. -// -// When the provided Repo type is nil, it -// will set nothing and immediately return. -func (r *Repo) SetAllowComment(v bool) { - // return if Repo type is nil - if r == nil { - return - } - - r.AllowComment = &v -} - // SetAllowEvents sets the AllowEvents field. // // When the provided Repo type is nil, it @@ -768,11 +623,6 @@ func (r *Repo) SetApproveBuild(v string) { func (r *Repo) String() string { return fmt.Sprintf(`{ Active: %t, - AllowComment: %t, - AllowDeploy: %t, - AllowPull: %t, - AllowPush: %t, - AllowTag: %t, AllowEvents: %s, ApproveBuild: %s, Branch: %s, @@ -794,11 +644,6 @@ func (r *Repo) String() string { Visibility: %s, }`, r.GetActive(), - r.GetAllowComment(), - r.GetAllowDeploy(), - r.GetAllowPull(), - r.GetAllowPush(), - r.GetAllowTag(), r.GetAllowEvents().List(), r.GetApproveBuild(), r.GetBranch(), diff --git a/library/repo_test.go b/library/repo_test.go index 2f2684cd..de256a0e 100644 --- a/library/repo_test.go +++ b/library/repo_test.go @@ -14,44 +14,34 @@ import ( func TestLibrary_Repo_Environment(t *testing.T) { // setup types want := map[string]string{ - "VELA_REPO_ACTIVE": "true", - "VELA_REPO_ALLOW_COMMENT": "false", - "VELA_REPO_ALLOW_DEPLOY": "false", - "VELA_REPO_ALLOW_PULL": "false", - "VELA_REPO_ALLOW_PUSH": "true", - "VELA_REPO_ALLOW_TAG": "false", - "VELA_REPO_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,tag,comment:created,schedule,delete:branch", - "VELA_REPO_BRANCH": "main", - "VELA_REPO_TOPICS": "cloud,security", - "VELA_REPO_BUILD_LIMIT": "10", - "VELA_REPO_CLONE": "https://github.com/github/octocat.git", - "VELA_REPO_FULL_NAME": "github/octocat", - "VELA_REPO_LINK": "https://github.com/github/octocat", - "VELA_REPO_NAME": "octocat", - "VELA_REPO_ORG": "github", - "VELA_REPO_PRIVATE": "false", - "VELA_REPO_TIMEOUT": "30", - "VELA_REPO_TRUSTED": "false", - "VELA_REPO_VISIBILITY": "public", - "VELA_REPO_PIPELINE_TYPE": "", - "VELA_REPO_APPROVE_BUILD": "never", - "REPOSITORY_ACTIVE": "true", - "REPOSITORY_ALLOW_COMMENT": "false", - "REPOSITORY_ALLOW_DEPLOY": "false", - "REPOSITORY_ALLOW_PULL": "false", - "REPOSITORY_ALLOW_PUSH": "true", - "REPOSITORY_ALLOW_TAG": "false", - "REPOSITORY_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,tag,comment:created,schedule,delete:branch", - "REPOSITORY_BRANCH": "main", - "REPOSITORY_CLONE": "https://github.com/github/octocat.git", - "REPOSITORY_FULL_NAME": "github/octocat", - "REPOSITORY_LINK": "https://github.com/github/octocat", - "REPOSITORY_NAME": "octocat", - "REPOSITORY_ORG": "github", - "REPOSITORY_PRIVATE": "false", - "REPOSITORY_TIMEOUT": "30", - "REPOSITORY_TRUSTED": "false", - "REPOSITORY_VISIBILITY": "public", + "VELA_REPO_ACTIVE": "true", + "VELA_REPO_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,tag,comment:created,schedule,delete:branch", + "VELA_REPO_BRANCH": "main", + "VELA_REPO_TOPICS": "cloud,security", + "VELA_REPO_BUILD_LIMIT": "10", + "VELA_REPO_CLONE": "https://github.com/github/octocat.git", + "VELA_REPO_FULL_NAME": "github/octocat", + "VELA_REPO_LINK": "https://github.com/github/octocat", + "VELA_REPO_NAME": "octocat", + "VELA_REPO_ORG": "github", + "VELA_REPO_PRIVATE": "false", + "VELA_REPO_TIMEOUT": "30", + "VELA_REPO_TRUSTED": "false", + "VELA_REPO_VISIBILITY": "public", + "VELA_REPO_PIPELINE_TYPE": "", + "VELA_REPO_APPROVE_BUILD": "never", + "REPOSITORY_ACTIVE": "true", + "REPOSITORY_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,tag,comment:created,schedule,delete:branch", + "REPOSITORY_BRANCH": "main", + "REPOSITORY_CLONE": "https://github.com/github/octocat.git", + "REPOSITORY_FULL_NAME": "github/octocat", + "REPOSITORY_LINK": "https://github.com/github/octocat", + "REPOSITORY_NAME": "octocat", + "REPOSITORY_ORG": "github", + "REPOSITORY_PRIVATE": "false", + "REPOSITORY_TIMEOUT": "30", + "REPOSITORY_TRUSTED": "false", + "REPOSITORY_VISIBILITY": "public", } // run test @@ -144,26 +134,6 @@ func TestLibrary_Repo_Getters(t *testing.T) { t.Errorf("GetActive is %v, want %v", test.repo.GetActive(), test.want.GetActive()) } - if test.repo.GetAllowPull() != test.want.GetAllowPull() { - t.Errorf("GetAllowPull is %v, want %v", test.repo.GetAllowPull(), test.want.GetAllowPull()) - } - - if test.repo.GetAllowPush() != test.want.GetAllowPush() { - t.Errorf("GetAllowPush is %v, want %v", test.repo.GetAllowPush(), test.want.GetAllowPush()) - } - - if test.repo.GetAllowDeploy() != test.want.GetAllowDeploy() { - t.Errorf("GetAllowDeploy is %v, want %v", test.repo.GetAllowDeploy(), test.want.GetAllowDeploy()) - } - - if test.repo.GetAllowTag() != test.want.GetAllowTag() { - t.Errorf("GetAllowTag is %v, want %v", test.repo.GetAllowTag(), test.want.GetAllowTag()) - } - - if test.repo.GetAllowComment() != test.want.GetAllowComment() { - t.Errorf("GetAllowComment is %v, want %v", test.repo.GetAllowComment(), test.want.GetAllowComment()) - } - if !reflect.DeepEqual(test.repo.GetAllowEvents(), test.want.GetAllowEvents()) { t.Errorf("GetRepo is %v, want %v", test.repo.GetAllowEvents(), test.want.GetAllowEvents()) } @@ -220,11 +190,6 @@ func TestLibrary_Repo_Setters(t *testing.T) { test.repo.SetPrivate(test.want.GetPrivate()) test.repo.SetTrusted(test.want.GetTrusted()) test.repo.SetActive(test.want.GetActive()) - test.repo.SetAllowPull(test.want.GetAllowPull()) - test.repo.SetAllowPush(test.want.GetAllowPush()) - test.repo.SetAllowDeploy(test.want.GetAllowDeploy()) - test.repo.SetAllowTag(test.want.GetAllowTag()) - test.repo.SetAllowComment(test.want.GetAllowComment()) test.repo.SetAllowEvents(test.want.GetAllowEvents()) test.repo.SetPipelineType(test.want.GetPipelineType()) test.repo.SetPreviousName(test.want.GetPreviousName()) @@ -294,26 +259,6 @@ func TestLibrary_Repo_Setters(t *testing.T) { t.Errorf("SetActive is %v, want %v", test.repo.GetActive(), test.want.GetActive()) } - if test.repo.GetAllowPull() != test.want.GetAllowPull() { - t.Errorf("SetAllowPull is %v, want %v", test.repo.GetAllowPull(), test.want.GetAllowPull()) - } - - if test.repo.GetAllowPush() != test.want.GetAllowPush() { - t.Errorf("SetAllowPush is %v, want %v", test.repo.GetAllowPush(), test.want.GetAllowPush()) - } - - if test.repo.GetAllowDeploy() != test.want.GetAllowDeploy() { - t.Errorf("SetAllowDeploy is %v, want %v", test.repo.GetAllowDeploy(), test.want.GetAllowDeploy()) - } - - if test.repo.GetAllowTag() != test.want.GetAllowTag() { - t.Errorf("SetAllowTag is %v, want %v", test.repo.GetAllowTag(), test.want.GetAllowTag()) - } - - if test.repo.GetAllowComment() != test.want.GetAllowComment() { - t.Errorf("SetAllowComment is %v, want %v", test.repo.GetAllowComment(), test.want.GetAllowComment()) - } - if !reflect.DeepEqual(test.repo.GetAllowEvents(), test.want.GetAllowEvents()) { t.Errorf("GetRepo is %v, want %v", test.repo.GetAllowEvents(), test.want.GetAllowEvents()) } @@ -338,11 +283,6 @@ func TestLibrary_Repo_String(t *testing.T) { want := fmt.Sprintf(`{ Active: %t, - AllowComment: %t, - AllowDeploy: %t, - AllowPull: %t, - AllowPush: %t, - AllowTag: %t, AllowEvents: %s, ApproveBuild: %s, Branch: %s, @@ -364,11 +304,6 @@ func TestLibrary_Repo_String(t *testing.T) { Visibility: %s, }`, r.GetActive(), - r.GetAllowComment(), - r.GetAllowDeploy(), - r.GetAllowPull(), - r.GetAllowPush(), - r.GetAllowTag(), r.GetAllowEvents().List(), r.GetApproveBuild(), r.GetBranch(), @@ -420,11 +355,6 @@ func testRepo() *Repo { r.SetPrivate(false) r.SetTrusted(false) r.SetActive(true) - r.SetAllowPull(false) - r.SetAllowPush(true) - r.SetAllowDeploy(false) - r.SetAllowTag(false) - r.SetAllowComment(false) r.SetAllowEvents(e) r.SetPipelineType("") r.SetPreviousName("") diff --git a/library/secret.go b/library/secret.go index 04e12497..57aa3e84 100644 --- a/library/secret.go +++ b/library/secret.go @@ -22,7 +22,6 @@ type Secret struct { Value *string `json:"value,omitempty"` Type *string `json:"type,omitempty"` Images *[]string `json:"images,omitempty"` - Events *[]string `json:"events,omitempty"` AllowEvents *Events `json:"allow_events,omitempty"` AllowCommand *bool `json:"allow_command,omitempty"` AllowSubstitution *bool `json:"allow_substitution,omitempty"` @@ -48,7 +47,6 @@ func (s *Secret) Sanitize() *Secret { Value: &value, Type: s.Type, Images: s.Images, - Events: s.Events, AllowEvents: s.AllowEvents, AllowCommand: s.AllowCommand, AllowSubstitution: s.AllowSubstitution, @@ -205,19 +203,6 @@ func (s *Secret) GetImages() []string { return *s.Images } -// GetEvents returns the Events field. -// -// When the provided Secret type is nil, or the field within -// the type is nil, it returns the zero value for the field. -func (s *Secret) GetEvents() []string { - // return zero value if Secret type or Events field is nil - if s == nil || s.Events == nil { - return []string{} - } - - return *s.Events -} - // GetAllowEvents returns the AllowEvents field. // // When the provided Secret type is nil, or the field within @@ -413,19 +398,6 @@ func (s *Secret) SetImages(v []string) { s.Images = &v } -// SetEvents sets the Events field. -// -// When the provided Secret type is nil, it -// will set nothing and immediately return. -func (s *Secret) SetEvents(v []string) { - // return if Secret type is nil - if s == nil { - return - } - - s.Events = &v -} - // SetAllowEvents sets the AllowEvents field. // // When the provided Secret type is nil, it @@ -523,7 +495,6 @@ func (s *Secret) String() string { AllowCommand: %t, AllowEvents: %s, AllowSubstitution: %t, - Events: %s, ID: %d, Images: %s, Name: %s, @@ -540,7 +511,6 @@ func (s *Secret) String() string { s.GetAllowCommand(), s.GetAllowEvents().List(), s.GetAllowSubstitution(), - s.GetEvents(), s.GetID(), s.GetImages(), s.GetName(), diff --git a/library/secret_test.go b/library/secret_test.go index ebe14549..ba0e3047 100644 --- a/library/secret_test.go +++ b/library/secret_test.go @@ -437,10 +437,6 @@ func TestLibrary_Secret_Getters(t *testing.T) { t.Errorf("GetImages is %v, want %v", test.secret.GetImages(), test.want.GetImages()) } - if !reflect.DeepEqual(test.secret.GetEvents(), test.want.GetEvents()) { - t.Errorf("GetEvents is %v, want %v", test.secret.GetEvents(), test.want.GetEvents()) - } - if !reflect.DeepEqual(test.secret.GetAllowEvents(), test.want.GetAllowEvents()) { t.Errorf("GetAllowEvents is %v, want %v", test.secret.GetAllowEvents(), test.want.GetAllowEvents()) } @@ -500,7 +496,6 @@ func TestLibrary_Secret_Setters(t *testing.T) { test.secret.SetValue(test.want.GetValue()) test.secret.SetType(test.want.GetType()) test.secret.SetImages(test.want.GetImages()) - test.secret.SetEvents(test.want.GetEvents()) test.secret.SetAllowEvents(test.want.GetAllowEvents()) test.secret.SetAllowCommand(test.want.GetAllowCommand()) test.secret.SetAllowSubstitution(test.want.GetAllowSubstitution()) @@ -541,10 +536,6 @@ func TestLibrary_Secret_Setters(t *testing.T) { t.Errorf("SetImages is %v, want %v", test.secret.GetImages(), test.want.GetImages()) } - if !reflect.DeepEqual(test.secret.GetEvents(), test.want.GetEvents()) { - t.Errorf("SetEvents is %v, want %v", test.secret.GetEvents(), test.want.GetEvents()) - } - if !reflect.DeepEqual(test.secret.GetAllowEvents(), test.want.GetAllowEvents()) { t.Errorf("SetAllowEvents is %v, want %v", test.secret.GetAllowEvents(), test.want.GetAllowEvents()) } @@ -583,7 +574,6 @@ func TestLibrary_Secret_String(t *testing.T) { AllowCommand: %t, AllowEvents: %v, AllowSubstitution: %t, - Events: %s, ID: %d, Images: %s, Name: %s, @@ -600,7 +590,6 @@ func TestLibrary_Secret_String(t *testing.T) { s.GetAllowCommand(), s.GetAllowEvents().List(), s.GetAllowSubstitution(), - s.GetEvents(), s.GetID(), s.GetImages(), s.GetName(), @@ -639,7 +628,6 @@ func testSecret() *Secret { s.SetValue("bar") s.SetType("repo") s.SetImages([]string{"alpine"}) - s.SetEvents([]string{"push", "tag", "deployment"}) s.SetAllowEvents(NewEventsFromMask(1)) s.SetAllowCommand(true) s.SetAllowSubstitution(true) From f16c3e4cb5fbbd200c302772c26d55626a43d447 Mon Sep 17 00:00:00 2001 From: Win San Date: Tue, 2 Apr 2024 10:37:26 -0500 Subject: [PATCH 08/18] feat(rulesets): add support for PR labeled events (#361) * Add support for PR label event 1. Add new action to the Pull struct 2. Update constants to reflect new event for the integer mask 3. Update YAML package to add new label rule 4. Update ruleset matching logic * Update test files related to PR event * Add support for PR unlabeled event 1. Add new action to the Pull struct 2. Update constants to reflect new event for the integer mask 3. Update YAML package to add new unlabeled rule 4. Update tests * Extend label rule to include other PR events * Fix linter warning --------- Co-authored-by: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Co-authored-by: dave vader <48764154+plyr4@users.noreply.github.com> --- constants/action.go | 6 + constants/allow_events.go | 3 +- library/actions/pull.go | 60 ++++++++++ library/actions/pull_test.go | 22 +++- library/actions/push_test.go | 1 + library/events.go | 16 +++ library/events_test.go | 18 ++- library/repo_test.go | 4 +- pipeline/container_test.go | 25 +++++ pipeline/ruleset.go | 211 ++++++++++++++++++----------------- pipeline/ruleset_test.go | 94 ++++++++++++---- webhook.go | 1 + yaml/ruleset.go | 5 + yaml/ruleset_test.go | 12 +- 14 files changed, 341 insertions(+), 137 deletions(-) diff --git a/constants/action.go b/constants/action.go index 802ddf79..da0a4449 100644 --- a/constants/action.go +++ b/constants/action.go @@ -22,6 +22,12 @@ const ( // ActionSynchronize defines the action for the synchronizing of pull requests. ActionSynchronize = "synchronize" + // ActionLabeled defines the action for the labeling of pull requests. + ActionLabeled = "labeled" + + // ActionUnlabeled defines the action for the unlabeling of pull requests. + ActionUnlabeled = "unlabeled" + // ActionTransferred defines the action for transferring repository ownership. ActionTransferred = "transferred" diff --git a/constants/allow_events.go b/constants/allow_events.go index 4a163a73..5df53926 100644 --- a/constants/allow_events.go +++ b/constants/allow_events.go @@ -11,7 +11,7 @@ const ( AllowPullSync _ // AllowPullAssigned - Not Implemented _ // AllowPullMilestoned - Not Implemented - _ // AllowPullLabel - Not Implemented + AllowPullLabel _ // AllowPullLocked - Not Implemented _ // AllowPullReady - Not Implemented AllowPullReopen @@ -23,4 +23,5 @@ const ( AllowSchedule AllowPushDeleteBranch AllowPushDeleteTag + AllowPullUnlabel ) diff --git a/library/actions/pull.go b/library/actions/pull.go index 609c6248..8e0063b1 100644 --- a/library/actions/pull.go +++ b/library/actions/pull.go @@ -12,6 +12,8 @@ type Pull struct { Edited *bool `json:"edited"` Synchronize *bool `json:"synchronize"` Reopened *bool `json:"reopened"` + Labeled *bool `json:"labeled"` + Unlabeled *bool `json:"unlabeled"` } // FromMask returns the Pull type resulting from the provided integer mask. @@ -20,6 +22,8 @@ func (a *Pull) FromMask(mask int64) *Pull { a.SetSynchronize(mask&constants.AllowPullSync > 0) a.SetEdited(mask&constants.AllowPullEdit > 0) a.SetReopened(mask&constants.AllowPullReopen > 0) + a.SetLabeled(mask&constants.AllowPullLabel > 0) + a.SetUnlabeled(mask&constants.AllowPullUnlabel > 0) return a } @@ -44,6 +48,14 @@ func (a *Pull) ToMask() int64 { mask = mask | constants.AllowPullReopen } + if a.GetLabeled() { + mask = mask | constants.AllowPullLabel + } + + if a.GetUnlabeled() { + mask = mask | constants.AllowPullUnlabel + } + return mask } @@ -91,6 +103,28 @@ func (a *Pull) GetReopened() bool { return *a.Reopened } +// GetLabeled returns the Labeled field from the provided Pull. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (a *Pull) GetLabeled() bool { + // return zero value if Pull type or Labeled field is nil + if a == nil || a.Labeled == nil { + return false + } + + return *a.Labeled +} + +// GetUnlabeled returns the Unlabeled field from the provided Pull. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (a *Pull) GetUnlabeled() bool { + // return zero value if Pull type or Unlabeled field is nil + if a == nil || a.Unlabeled == nil { + return false + } + + return *a.Unlabeled +} + // SetOpened sets the Pull Opened field. // // When the provided Pull type is nil, it @@ -142,3 +176,29 @@ func (a *Pull) SetReopened(v bool) { a.Reopened = &v } + +// SetLabeled sets the Pull Labeled field. +// +// When the provided Pull type is nil, it +// will set nothing and immediately return. +func (a *Pull) SetLabeled(v bool) { + // return if Pull type is nil + if a == nil { + return + } + + a.Labeled = &v +} + +// SetUnlabeled sets the Pull Unlabeled field. +// +// When the provided Pull type is nil, it +// will set nothing and immediately return. +func (a *Pull) SetUnlabeled(v bool) { + // return if Pull type is nil + if a == nil { + return + } + + a.Unlabeled = &v +} diff --git a/library/actions/pull_test.go b/library/actions/pull_test.go index 30b5ed8c..f4c815b5 100644 --- a/library/actions/pull_test.go +++ b/library/actions/pull_test.go @@ -42,6 +42,14 @@ func TestLibrary_Pull_Getters(t *testing.T) { if test.actions.GetReopened() != test.want.GetReopened() { t.Errorf("GetReopened is %v, want %v", test.actions.GetReopened(), test.want.GetReopened()) } + + if test.actions.GetLabeled() != test.want.GetLabeled() { + t.Errorf("GetLabeled is %v, want %v", test.actions.GetLabeled(), test.want.GetLabeled()) + } + + if test.actions.GetUnlabeled() != test.want.GetUnlabeled() { + t.Errorf("GetUnlabeled is %v, want %v", test.actions.GetUnlabeled(), test.want.GetUnlabeled()) + } } } @@ -70,6 +78,8 @@ func TestLibrary_Pull_Setters(t *testing.T) { test.actions.SetSynchronize(test.want.GetSynchronize()) test.actions.SetEdited(test.want.GetEdited()) test.actions.SetReopened(test.want.GetReopened()) + test.actions.SetLabeled(test.want.GetLabeled()) + test.actions.SetUnlabeled(test.want.GetUnlabeled()) if test.actions.GetOpened() != test.want.GetOpened() { t.Errorf("SetOpened is %v, want %v", test.actions.GetOpened(), test.want.GetOpened()) @@ -86,6 +96,14 @@ func TestLibrary_Pull_Setters(t *testing.T) { if test.actions.GetReopened() != test.want.GetReopened() { t.Errorf("SetReopened is %v, want %v", test.actions.GetReopened(), test.want.GetReopened()) } + + if test.actions.GetLabeled() != test.want.GetLabeled() { + t.Errorf("SetLabeled is %v, want %v", test.actions.GetLabeled(), test.want.GetLabeled()) + } + + if test.actions.GetUnlabeled() != test.want.GetUnlabeled() { + t.Errorf("SetUnlabeled is %v, want %v", test.actions.GetUnlabeled(), test.want.GetUnlabeled()) + } } } @@ -107,7 +125,7 @@ func TestLibrary_Pull_ToMask(t *testing.T) { // setup types actions := testPull() - want := int64(constants.AllowPullOpen | constants.AllowPullSync | constants.AllowPullReopen) + want := int64(constants.AllowPullOpen | constants.AllowPullSync | constants.AllowPullReopen | constants.AllowPullUnlabel) // run test got := actions.ToMask() @@ -123,6 +141,8 @@ func testPull() *Pull { pr.SetSynchronize(true) pr.SetEdited(false) pr.SetReopened(true) + pr.SetLabeled(false) + pr.SetUnlabeled(true) return pr } diff --git a/library/actions/push_test.go b/library/actions/push_test.go index 330444ba..b0cfba47 100644 --- a/library/actions/push_test.go +++ b/library/actions/push_test.go @@ -128,6 +128,7 @@ func testMask() int64 { constants.AllowPullOpen | constants.AllowPullSync | constants.AllowPullReopen | + constants.AllowPullUnlabel | constants.AllowDeployCreate | constants.AllowCommentCreate | constants.AllowSchedule, diff --git a/library/events.go b/library/events.go index 45f1f908..e93acb10 100644 --- a/library/events.go +++ b/library/events.go @@ -68,6 +68,10 @@ func NewEventsFromSlice(events []string) *Events { mask = mask | constants.AllowPullSync case constants.EventPull + ":" + constants.ActionReopened: mask = mask | constants.AllowPullReopen + case constants.EventPull + ":" + constants.ActionLabeled: + mask = mask | constants.AllowPullLabel + case constants.EventPull + ":" + constants.ActionUnlabeled: + mask = mask | constants.AllowPullUnlabel // deployment actions case constants.EventDeploy, constants.EventDeployAlternate, constants.EventDeploy + ":" + constants.ActionCreated: @@ -111,6 +115,10 @@ func (e *Events) Allowed(event, action string) bool { allowed = e.GetPullRequest().GetEdited() case constants.EventPull + ":" + constants.ActionReopened: allowed = e.GetPullRequest().GetReopened() + case constants.EventPull + ":" + constants.ActionLabeled: + allowed = e.GetPullRequest().GetLabeled() + case constants.EventPull + ":" + constants.ActionUnlabeled: + allowed = e.GetPullRequest().GetUnlabeled() case constants.EventTag: allowed = e.GetPush().GetTag() case constants.EventComment + ":" + constants.ActionCreated: @@ -155,6 +163,14 @@ func (e *Events) List() []string { eventSlice = append(eventSlice, constants.EventPull+":"+constants.ActionReopened) } + if e.GetPullRequest().GetLabeled() { + eventSlice = append(eventSlice, constants.EventPull+":"+constants.ActionLabeled) + } + + if e.GetPullRequest().GetUnlabeled() { + eventSlice = append(eventSlice, constants.EventPull+":"+constants.ActionUnlabeled) + } + if e.GetPush().GetTag() { eventSlice = append(eventSlice, constants.EventTag) } diff --git a/library/events_test.go b/library/events_test.go index ef60257b..79f6ee16 100644 --- a/library/events_test.go +++ b/library/events_test.go @@ -122,6 +122,7 @@ func TestLibrary_Events_List(t *testing.T) { "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", + "pull_request:unlabeled", "tag", "comment:created", "schedule", @@ -130,6 +131,7 @@ func TestLibrary_Events_List(t *testing.T) { wantTwo := []string{ "pull_request:edited", + "pull_request:labeled", "deployment", "comment:edited", "delete:tag", @@ -158,6 +160,7 @@ func TestLibrary_Events_NewEventsFromMask_ToDatabase(t *testing.T) { constants.AllowPullOpen | constants.AllowPullSync | constants.AllowPullReopen | + constants.AllowPullUnlabel | constants.AllowCommentCreate | constants.AllowSchedule, ) @@ -166,6 +169,7 @@ func TestLibrary_Events_NewEventsFromMask_ToDatabase(t *testing.T) { constants.AllowPushDeleteTag | constants.AllowPullEdit | constants.AllowCommentEdit | + constants.AllowPullLabel | constants.AllowDeployCreate, ) @@ -209,12 +213,12 @@ func Test_NewEventsFromSlice(t *testing.T) { }{ { name: "action specific events to e1", - events: []string{"push:branch", "push:tag", "delete:branch", "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", "comment:created", "schedule:run"}, + events: []string{"push:branch", "push:tag", "delete:branch", "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", "comment:created", "schedule:run", "pull_request:unlabeled"}, want: e1, }, { name: "action specific events to e2", - events: []string{"delete:tag", "pull_request:edited", "deployment:created", "comment:edited"}, + events: []string{"delete:tag", "pull_request:edited", "deployment:created", "comment:edited", "pull_request:labeled"}, want: e2, }, { @@ -232,6 +236,8 @@ func Test_NewEventsFromSlice(t *testing.T) { Reopened: &tBool, Edited: &fBool, Synchronize: &tBool, + Labeled: &fBool, + Unlabeled: &fBool, }, Deployment: &actions.Deploy{ Created: &tBool, @@ -260,6 +266,8 @@ func Test_NewEventsFromSlice(t *testing.T) { Reopened: &tBool, Edited: &fBool, Synchronize: &tBool, + Labeled: &fBool, + Unlabeled: &fBool, }, Deployment: &actions.Deploy{ Created: &fBool, @@ -306,6 +314,8 @@ func TestLibrary_Events_Allowed(t *testing.T) { {event: "pull_request", action: "synchronize", want: true}, {event: "pull_request", action: "edited", want: false}, {event: "pull_request", action: "reopened", want: true}, + {event: "pull_request", action: "labeled", want: false}, + {event: "pull_request", action: "unlabeled", want: true}, {event: "deployment", want: false}, {event: "comment", action: "created", want: true}, {event: "comment", action: "edited", want: false}, @@ -345,6 +355,8 @@ func testEvents() (*Events, *Events) { Synchronize: &tBool, Edited: &fBool, Reopened: &tBool, + Labeled: &fBool, + Unlabeled: &tBool, }, Deployment: &actions.Deploy{ Created: &fBool, @@ -370,6 +382,8 @@ func testEvents() (*Events, *Events) { Synchronize: &fBool, Edited: &tBool, Reopened: &fBool, + Labeled: &tBool, + Unlabeled: &fBool, }, Deployment: &actions.Deploy{ Created: &tBool, diff --git a/library/repo_test.go b/library/repo_test.go index de256a0e..f9eaba2b 100644 --- a/library/repo_test.go +++ b/library/repo_test.go @@ -15,7 +15,7 @@ func TestLibrary_Repo_Environment(t *testing.T) { // setup types want := map[string]string{ "VELA_REPO_ACTIVE": "true", - "VELA_REPO_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,tag,comment:created,schedule,delete:branch", + "VELA_REPO_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,pull_request:unlabeled,tag,comment:created,schedule,delete:branch", "VELA_REPO_BRANCH": "main", "VELA_REPO_TOPICS": "cloud,security", "VELA_REPO_BUILD_LIMIT": "10", @@ -31,7 +31,7 @@ func TestLibrary_Repo_Environment(t *testing.T) { "VELA_REPO_PIPELINE_TYPE": "", "VELA_REPO_APPROVE_BUILD": "never", "REPOSITORY_ACTIVE": "true", - "REPOSITORY_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,tag,comment:created,schedule,delete:branch", + "REPOSITORY_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,pull_request:reopened,pull_request:unlabeled,tag,comment:created,schedule,delete:branch", "REPOSITORY_BRANCH": "main", "REPOSITORY_CLONE": "https://github.com/github/octocat.git", "REPOSITORY_FULL_NAME": "github/octocat", diff --git a/pipeline/container_test.go b/pipeline/container_test.go index ba08cd2b..1e959cb5 100644 --- a/pipeline/container_test.go +++ b/pipeline/container_test.go @@ -202,6 +202,7 @@ func TestPipeline_Container_Execute(t *testing.T) { If: Rules{ Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -222,6 +223,7 @@ func TestPipeline_Container_Execute(t *testing.T) { If: Rules{ Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -241,6 +243,7 @@ func TestPipeline_Container_Execute(t *testing.T) { If: Rules{ Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -260,6 +263,7 @@ func TestPipeline_Container_Execute(t *testing.T) { If: Rules{ Status: []string{constants.StatusSuccess, constants.StatusFailure}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -279,6 +283,7 @@ func TestPipeline_Container_Execute(t *testing.T) { If: Rules{ Status: []string{constants.StatusSuccess, constants.StatusFailure}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -298,6 +303,7 @@ func TestPipeline_Container_Execute(t *testing.T) { If: Rules{ Status: []string{constants.StatusSuccess, constants.StatusFailure}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -318,6 +324,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Branch: []string{"main"}, Event: []string{constants.EventPush}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -338,6 +345,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Branch: []string{"main"}, Event: []string{constants.EventPush}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -359,6 +367,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Path: []string{"README.md"}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -380,6 +389,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Path: []string{"README.md"}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -401,6 +411,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Path: []string{"README.md"}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -422,6 +433,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventComment}, Comment: []string{"run vela"}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -443,6 +455,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventComment}, Comment: []string{"run vela"}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -464,6 +477,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventComment}, Comment: []string{"run vela"}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -485,6 +499,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -506,6 +521,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -527,6 +543,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -570,6 +587,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventTag}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -592,6 +610,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventTag}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -614,6 +633,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventTag}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -634,6 +654,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Unless: Rules{ Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -653,6 +674,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Unless: Rules{ Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -672,6 +694,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Unless: Rules{ Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -693,6 +716,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ @@ -714,6 +738,7 @@ func TestPipeline_Container_Execute(t *testing.T) { Event: []string{constants.EventPush}, Status: []string{constants.StatusSuccess}, }, + Operator: "and", }, }, ruleData: &RuleData{ diff --git a/pipeline/ruleset.go b/pipeline/ruleset.go index 04880d57..a27c8ea6 100644 --- a/pipeline/ruleset.go +++ b/pipeline/ruleset.go @@ -37,6 +37,7 @@ type ( Status Ruletype `json:"status,omitempty" yaml:"status,omitempty"` Tag Ruletype `json:"tag,omitempty" yaml:"tag,omitempty"` Target Ruletype `json:"target,omitempty" yaml:"target,omitempty"` + Label Ruletype `json:"label,omitempty" yaml:"label,omitempty"` Parallel bool `json:"-" yaml:"-"` } @@ -57,6 +58,7 @@ type ( Status string `json:"status,omitempty" yaml:"status,omitempty"` Tag string `json:"tag,omitempty" yaml:"tag,omitempty"` Target string `json:"target,omitempty" yaml:"target,omitempty"` + Label []string `json:"label,omitempty" yaml:"label,omitempty"` Parallel bool `json:"-" yaml:"-"` } ) @@ -111,7 +113,8 @@ func (r *Rules) Empty() bool { len(r.Repo) == 0 && len(r.Status) == 0 && len(r.Tag) == 0 && - len(r.Target) == 0 { + len(r.Target) == 0 && + len(r.Label) == 0 { return true } @@ -119,152 +122,152 @@ func (r *Rules) Empty() bool { return false } -// Match returns true for the or operator when one of the +// Match returns true for the `or` operator when one of the // ruletypes from the rules match the provided ruledata. -// Match returns true for the and operator when all of the +// Match returns true for the `and` operator when all of the // ruletypes from the rules match the provided ruledata. For // both operators, when none of the ruletypes from the rules // match the provided ruledata, the function returns false. func (r *Rules) Match(from *RuleData, matcher, op string) (bool, error) { - // if the path ruletype is provided - if len(from.Path) > 0 { - // if the "or" operator is provided in the ruleset - if strings.EqualFold(op, constants.OperatorOr) { - // iterate through each path in the ruletype - for _, p := range from.Path { - matches, err := matches(r, from, matcher, p, constants.OperatorOr) - if err != nil { - return false, err - } - - // return true if any ruletype matches the ruledata - if matches { - return true, nil - } - } - - // return false if no match is found - return false, nil - } - - // iterate through each path in the ruletype - for _, p := range from.Path { - matches, err := matches(r, from, matcher, p, constants.OperatorAnd) - if err != nil { - return false, err - } - - // return true if any ruletype matches the ruledata - if matches { - return true, nil - } - } - - // return false if no match is found - return false, nil - } - - // if the "or" operator is provided in the ruleset - if strings.EqualFold(op, constants.OperatorOr) { - // return true if any ruletype matches the ruledata - return matches(r, from, matcher, "", constants.OperatorOr) - } - - return matches(r, from, matcher, "", constants.OperatorAnd) -} - -// Match returns true when the provided ruletype -// matches the provided ruledata. When the provided -// ruletype is empty, the function returns true for -// the `and` operator and false for the `or` operator. -func (r *Ruletype) Match(data, matcher, logic string) (bool, error) { - // return true for `and`, false for `or` if an empty ruletype is provided - if len(*r) == 0 { - return strings.EqualFold(logic, constants.OperatorAnd), nil - } - - // iterate through each pattern in the ruletype - for _, pattern := range *r { - // handle the pattern based off the matcher provided - switch matcher { - case constants.MatcherRegex, "regex": - regExpPattern, err := regexp.Compile(pattern) - if err != nil { - return false, fmt.Errorf("error in regex pattern %s: %w", pattern, err) - } - - // return true if the regexp pattern matches the ruledata - if regExpPattern.MatchString(data) { - return true, nil - } - case constants.MatcherFilepath: - fallthrough - default: - // return true if the pattern matches the ruledata - ok, _ := filepath.Match(pattern, data) - if ok { - return true, nil - } - } - } - - // return false if no match is found - return false, nil -} - -// matches is a helper function which leverages the Match method for all rules -// and returns `true` if the ruleset is indeed a match. -func matches(r *Rules, from *RuleData, matcher, path, logic string) (bool, error) { status := true var err error if len(from.Status) != 0 { - status, err = r.Status.Match(from.Status, matcher, logic) + status, err = r.Status.MatchSingle(from.Status, matcher, op) if err != nil { return false, err } } - matchBranch, err := r.Branch.Match(from.Branch, matcher, logic) + matchBranch, err := r.Branch.MatchSingle(from.Branch, matcher, op) if err != nil { return false, err } - matchComment, err := r.Comment.Match(from.Comment, matcher, logic) + matchComment, err := r.Comment.MatchSingle(from.Comment, matcher, op) if err != nil { return false, err } - matchEvent, err := r.Event.Match(from.Event, matcher, logic) + matchEvent, err := r.Event.MatchSingle(from.Event, matcher, op) if err != nil { return false, err } - matchPath, err := r.Path.Match(path, matcher, logic) + matchPath, err := r.Path.MatchMultiple(from.Path, matcher, op) if err != nil { return false, err } - matchRepo, err := r.Repo.Match(from.Repo, matcher, logic) + matchRepo, err := r.Repo.MatchSingle(from.Repo, matcher, op) if err != nil { return false, err } - matchTag, err := r.Tag.Match(from.Tag, matcher, logic) + matchTag, err := r.Tag.MatchSingle(from.Tag, matcher, op) if err != nil { return false, err } - matchTarget, err := r.Target.Match(from.Target, matcher, logic) + matchTarget, err := r.Target.MatchSingle(from.Target, matcher, op) if err != nil { return false, err } - switch logic { - case constants.OperatorAnd: - return (matchBranch && matchComment && matchEvent && matchPath && matchRepo && matchTag && matchTarget && status), nil + matchLabel, err := r.Label.MatchMultiple(from.Label, matcher, op) + if err != nil { + return false, err + } + + switch op { + case constants.OperatorOr: + return (matchBranch || matchComment || matchEvent || matchPath || matchRepo || matchTag || matchTarget || matchLabel || status), nil + default: + return (matchBranch && matchComment && matchEvent && matchPath && matchRepo && matchTag && matchTarget && matchLabel && status), nil + } +} + +// MatchSingle returns true when the provided ruletype +// matches the provided ruledata. When the provided +// ruletype is empty, the function returns true for +// the `and` operator and false for the `or` operator. +func (r *Ruletype) MatchSingle(data, matcher, logic string) (bool, error) { + // return true for `and`, false for `or` if an empty ruletype is provided + if len(*r) == 0 { + return strings.EqualFold(logic, constants.OperatorAnd), nil + } + + // iterate through each pattern in the ruletype + for _, pattern := range *r { + match, err := match(data, matcher, pattern) + if err != nil { + return false, err + } + + if match { + return true, nil + } + } + + // return false if no match is found + return false, nil +} + +// MatchMultiple returns true when the provided ruletype +// matches the provided ruledata. When the provided +// ruletype is empty, the function returns true for +// the `and` operator and false for the `or` operator. +func (r *Ruletype) MatchMultiple(data []string, matcher, logic string) (bool, error) { + // return true for `and`, false for `or` if an empty ruletype is provided + if len(*r) == 0 { + return strings.EqualFold(logic, constants.OperatorAnd), nil + } + + // iterate through each pattern in the ruletype + for _, pattern := range *r { + for _, value := range data { + match, err := match(value, matcher, pattern) + if err != nil { + return false, err + } + + if match { + return true, nil + } + } + } + + // return false if no match is found + return false, nil +} + +// match is a helper function that compares data against a pattern +// and returns true if the data matches the pattern, depending on +// matcher specified. +func match(data, matcher, pattern string) (bool, error) { + // handle the pattern based off the matcher provided + switch matcher { + case constants.MatcherRegex, "regex": + regExpPattern, err := regexp.Compile(pattern) + if err != nil { + return false, fmt.Errorf("error in regex pattern %s: %w", pattern, err) + } + + // return true if the regexp pattern matches the ruledata + if regExpPattern.MatchString(data) { + return true, nil + } + case constants.MatcherFilepath: + fallthrough default: - return (matchBranch || matchComment || matchEvent || matchPath || matchRepo || matchTag || matchTarget || status), nil + // return true if the pattern matches the ruledata + ok, _ := filepath.Match(pattern, data) + if ok { + return true, nil + } } + + // return false if no match is found + return false, nil } diff --git a/pipeline/ruleset_test.go b/pipeline/ruleset_test.go index a310ed71..7ea87a31 100644 --- a/pipeline/ruleset_test.go +++ b/pipeline/ruleset_test.go @@ -20,62 +20,62 @@ func TestPipeline_Ruleset_Match(t *testing.T) { {ruleset: &Ruleset{}, data: &RuleData{Branch: "main"}, want: true}, // If with and operator { - ruleset: &Ruleset{If: Rules{Branch: []string{"main"}}}, + ruleset: &Ruleset{If: Rules{Branch: []string{"main"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: true, }, { - ruleset: &Ruleset{If: Rules{Branch: []string{"main"}}}, + ruleset: &Ruleset{If: Rules{Branch: []string{"main"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "rerun", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: false, }, { - ruleset: &Ruleset{If: Rules{Branch: []string{"main"}, Event: []string{"push"}}}, + ruleset: &Ruleset{If: Rules{Branch: []string{"main"}, Event: []string{"push"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: true, }, { - ruleset: &Ruleset{If: Rules{Branch: []string{"main"}, Event: []string{"push"}}}, + ruleset: &Ruleset{If: Rules{Branch: []string{"main"}, Event: []string{"push"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "pull_request", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: false, }, { - ruleset: &Ruleset{If: Rules{Path: []string{"foo.txt", "/foo/bar.txt"}}}, + ruleset: &Ruleset{If: Rules{Path: []string{"foo.txt", "/foo/bar.txt"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "pull_request", Path: []string{}, Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: false, }, { - ruleset: &Ruleset{If: Rules{Comment: []string{"rerun"}}}, + ruleset: &Ruleset{If: Rules{Comment: []string{"rerun"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "rerun", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: true, }, { - ruleset: &Ruleset{If: Rules{Comment: []string{"rerun"}}}, + ruleset: &Ruleset{If: Rules{Comment: []string{"rerun"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "ok to test", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: false, }, { - ruleset: &Ruleset{If: Rules{Event: []string{"deployment"}, Target: []string{"production"}}}, + ruleset: &Ruleset{If: Rules{Event: []string{"deployment"}, Target: []string{"production"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "", Event: "deployment", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: "production"}, want: true, }, { - ruleset: &Ruleset{If: Rules{Event: []string{"deployment"}, Target: []string{"production"}}}, + ruleset: &Ruleset{If: Rules{Event: []string{"deployment"}, Target: []string{"production"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "", Event: "deployment", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: "stage"}, want: false, }, { - ruleset: &Ruleset{If: Rules{Event: []string{"schedule"}, Target: []string{"weekly"}}}, + ruleset: &Ruleset{If: Rules{Event: []string{"schedule"}, Target: []string{"weekly"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "", Event: "schedule", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: "weekly"}, want: true, }, { - ruleset: &Ruleset{If: Rules{Event: []string{"schedule"}, Target: []string{"weekly"}}}, + ruleset: &Ruleset{If: Rules{Event: []string{"schedule"}, Target: []string{"weekly"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "", Event: "schedule", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: "nightly"}, want: false, }, { - ruleset: &Ruleset{If: Rules{Status: []string{"success", "failure"}}}, + ruleset: &Ruleset{If: Rules{Status: []string{"success", "failure"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "ok to test", Event: "push", Repo: "octocat/hello-world", Status: "failure", Tag: "refs/heads/main", Target: ""}, want: true, }, @@ -107,27 +107,27 @@ func TestPipeline_Ruleset_Match(t *testing.T) { }, // Unless with and operator { - ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}}}, + ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: false, }, { - ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}}}, + ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}}, Operator: "and"}, data: &RuleData{Branch: "dev", Comment: "rerun", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: true, }, { - ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}, Event: []string{"push"}}}, + ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}, Event: []string{"push"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: false, }, { - ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}, Event: []string{"push"}}}, + ruleset: &Ruleset{Unless: Rules{Branch: []string{"main"}, Event: []string{"push"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "pull_request", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: true, }, { - ruleset: &Ruleset{Unless: Rules{Path: []string{"foo.txt", "/foo/bar.txt"}}}, + ruleset: &Ruleset{Unless: Rules{Path: []string{"foo.txt", "/foo/bar.txt"}}, Operator: "and"}, data: &RuleData{Branch: "main", Comment: "rerun", Event: "pull_request", Path: []string{}, Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, want: true, }, @@ -425,16 +425,52 @@ func TestPipeline_Rules_Match(t *testing.T) { }, { rules: &Rules{Event: []string{"push", "pull_request"}, Tag: []string{"release/*"}}, - data: &RuleData{Branch: "main", Event: "push", Repo: "octocat/hello-world", Status: "pending", Tag: "release/*", Target: ""}, + data: &RuleData{Branch: "main", Event: "tag", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, operator: "or", + want: false, + }, + { + rules: &Rules{Event: []string{"pull_request:labeled"}, Label: []string{"enhancement", "documentation"}}, + data: &RuleData{Branch: "main", Event: "pull_request:labeled", Repo: "octocat/hello-world", Status: "pending", Label: []string{"documentation"}}, + operator: "and", want: true, }, { - rules: &Rules{Event: []string{"push", "pull_request"}, Tag: []string{"release/*"}}, - data: &RuleData{Branch: "main", Event: "tag", Repo: "octocat/hello-world", Status: "pending", Tag: "refs/heads/main", Target: ""}, - operator: "or", + rules: &Rules{Event: []string{"pull_request:labeled"}, Label: []string{"enhancement", "documentation"}}, + data: &RuleData{Branch: "main", Event: "pull_request:labeled", Repo: "octocat/hello-world", Status: "pending", Label: []string{"support"}}, + operator: "and", + want: false, + }, + { + rules: &Rules{Event: []string{"pull_request:unlabeled"}, Label: []string{"enhancement", "documentation"}}, + data: &RuleData{Branch: "main", Event: "pull_request:unlabeled", Repo: "octocat/hello-world", Status: "pending", Label: []string{"documentation"}}, + operator: "and", + want: true, + }, + { + rules: &Rules{Event: []string{"pull_request:unlabeled"}, Label: []string{"enhancement"}}, + data: &RuleData{Branch: "main", Event: "pull_request:unlabeled", Repo: "octocat/hello-world", Status: "pending", Label: []string{"documentation"}}, + operator: "and", want: false, }, + { + rules: &Rules{Event: []string{"push"}, Label: []string{"enhancement", "documentation"}}, + data: &RuleData{Branch: "main", Event: "push", Repo: "octocat/hello-world", Status: "pending", Label: []string{"documentation"}}, + operator: "and", + want: true, + }, + { + rules: &Rules{Event: []string{"push"}, Label: []string{"enhancement"}}, + data: &RuleData{Branch: "main", Event: "push", Repo: "octocat/hello-world", Status: "pending", Label: []string{"documentation"}}, + operator: "and", + want: false, + }, + { + rules: &Rules{Event: []string{"push"}, Label: []string{"enhancement"}}, + data: &RuleData{Branch: "main", Event: "push", Repo: "octocat/hello-world", Status: "pending", Label: []string{"documentation"}}, + operator: "or", + want: true, + }, } // run test @@ -490,6 +526,9 @@ func TestPipeline_Ruletype_MatchAnd(t *testing.T) { // Target with filepath matcher {matcher: "filepath", rule: []string{"production"}, pattern: "production", want: true}, {matcher: "filepath", rule: []string{"stage"}, pattern: "production", want: false}, + // Label with filepath matcher + {matcher: "filepath", rule: []string{"enhancement", "documentation"}, pattern: "documentation", want: true}, + {matcher: "filepath", rule: []string{"enhancement", "documentation"}, pattern: "question", want: false}, // Empty with regex matcher {matcher: "regexp", rule: []string{}, pattern: "main", want: true}, {matcher: "regexp", rule: []string{}, pattern: "push", want: true}, @@ -525,11 +564,14 @@ func TestPipeline_Ruletype_MatchAnd(t *testing.T) { // Target with regex matcher {matcher: "regexp", rule: []string{"production"}, pattern: "production", want: true}, {matcher: "regexp", rule: []string{"stage"}, pattern: "production", want: false}, + // Label with regexp matcher + {matcher: "regexp", rule: []string{"enhancement", "documentation"}, pattern: "documentation", want: true}, + {matcher: "regexp", rule: []string{"enhancement", "documentation"}, pattern: "question", want: false}, } // run test for _, test := range tests { - got, _ := test.rule.Match(test.pattern, test.matcher, constants.OperatorAnd) + got, _ := test.rule.MatchSingle(test.pattern, test.matcher, constants.OperatorAnd) if got != test.want { t.Errorf("MatchAnd for %s matcher is %v, want %v", test.matcher, got, test.want) @@ -572,6 +614,9 @@ func TestPipeline_Ruletype_MatchOr(t *testing.T) { // Target with filepath matcher {matcher: "filepath", rule: []string{"production"}, pattern: "production", want: true}, {matcher: "filepath", rule: []string{"stage"}, pattern: "production", want: false}, + // Label with filepath matcher + {matcher: "filepath", rule: []string{"enhancement", "documentation"}, pattern: "documentation", want: true}, + {matcher: "filepath", rule: []string{"enhancement", "documentation"}, pattern: "question", want: false}, // Empty with regexp matcher {matcher: "regexp", rule: []string{}, pattern: "main", want: false}, {matcher: "regexp", rule: []string{}, pattern: "push", want: false}, @@ -599,11 +644,14 @@ func TestPipeline_Ruletype_MatchOr(t *testing.T) { // Target with regexp matcher {matcher: "regexp", rule: []string{"production"}, pattern: "production", want: true}, {matcher: "regexp", rule: []string{"stage"}, pattern: "production", want: false}, + // Label with regexp matcher + {matcher: "regexp", rule: []string{"enhancement", "documentation"}, pattern: "documentation", want: true}, + {matcher: "regexp", rule: []string{"enhancement", "documentation"}, pattern: "question", want: false}, } // run test for _, test := range tests { - got, _ := test.rule.Match(test.pattern, test.matcher, constants.OperatorOr) + got, _ := test.rule.MatchSingle(test.pattern, test.matcher, constants.OperatorOr) if got != test.want { t.Errorf("MatchOr for %s matcher is %v, want %v", test.matcher, got, test.want) diff --git a/webhook.go b/webhook.go index 1941e38f..579e8230 100644 --- a/webhook.go +++ b/webhook.go @@ -19,6 +19,7 @@ type PullRequest struct { Comment string Number int IsFromFork bool + Labels []string } // Webhook defines a struct that is used to return diff --git a/yaml/ruleset.go b/yaml/ruleset.go index 7b8fc615..2fe23e16 100644 --- a/yaml/ruleset.go +++ b/yaml/ruleset.go @@ -30,6 +30,7 @@ type ( Status []string `yaml:"status,omitempty,flow" json:"status,omitempty" jsonschema:"enum=[failure],enum=[success],description=Limits the execution of a step to matching build statuses.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-tag"` Tag []string `yaml:"tag,omitempty,flow" json:"tag,omitempty" jsonschema:"description=Limits the execution of a step to matching build tag references.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-tag"` Target []string `yaml:"target,omitempty,flow" json:"target,omitempty" jsonschema:"description=Limits the execution of a step to matching build deployment targets.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-tag"` + Label []string `yaml:"label,omitempty,flow" json:"label,omitempty" jsonschema:"description=Limits step execution to match on pull requests labels.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-tag"` } ) @@ -84,6 +85,7 @@ func (r *Ruleset) UnmarshalYAML(unmarshal func(interface{}) error) error { advanced.If.Status = append(advanced.If.Status, simple.Status...) advanced.If.Tag = append(advanced.If.Tag, simple.Tag...) advanced.If.Target = append(advanced.If.Target, simple.Target...) + advanced.If.Label = append(advanced.If.Label, simple.Label...) // set ruleset `if` to advanced `if` rules r.If = advanced.If @@ -113,6 +115,7 @@ func (r *Rules) ToPipeline() *pipeline.Rules { Status: r.Status, Tag: r.Tag, Target: r.Target, + Label: r.Label, } } @@ -128,6 +131,7 @@ func (r *Rules) UnmarshalYAML(unmarshal func(interface{}) error) error { Status raw.StringSlice Tag raw.StringSlice Target raw.StringSlice + Label raw.StringSlice }) // attempt to unmarshal rules @@ -140,6 +144,7 @@ func (r *Rules) UnmarshalYAML(unmarshal func(interface{}) error) error { r.Status = rules.Status r.Tag = rules.Tag r.Target = rules.Target + r.Label = rules.Label // account for users who use non-scoped pull_request event events := []string{} diff --git a/yaml/ruleset_test.go b/yaml/ruleset_test.go index 762bb904..559395ba 100644 --- a/yaml/ruleset_test.go +++ b/yaml/ruleset_test.go @@ -22,12 +22,13 @@ func TestYaml_Ruleset_ToPipeline(t *testing.T) { If: Rules{ Branch: []string{"main"}, Comment: []string{"test comment"}, - Event: []string{"push"}, + Event: []string{"push", "pull_request:labeled"}, Path: []string{"foo.txt"}, Repo: []string{"github/octocat"}, Status: []string{"success"}, Tag: []string{"v0.1.0"}, Target: []string{"production"}, + Label: []string{"enhancement"}, }, Unless: Rules{ Branch: []string{"main"}, @@ -47,12 +48,13 @@ func TestYaml_Ruleset_ToPipeline(t *testing.T) { If: pipeline.Rules{ Branch: []string{"main"}, Comment: []string{"test comment"}, - Event: []string{"push"}, + Event: []string{"push", "pull_request:labeled"}, Path: []string{"foo.txt"}, Repo: []string{"github/octocat"}, Status: []string{"success"}, Tag: []string{"v0.1.0"}, Target: []string{"production"}, + Label: []string{"enhancement"}, }, Unless: pipeline.Rules{ Branch: []string{"main"}, @@ -167,22 +169,24 @@ func TestYaml_Rules_ToPipeline(t *testing.T) { rules: &Rules{ Branch: []string{"main"}, Comment: []string{"test comment"}, - Event: []string{"push"}, + Event: []string{"push", "pull_request:labeled"}, Path: []string{"foo.txt"}, Repo: []string{"github/octocat"}, Status: []string{"success"}, Tag: []string{"v0.1.0"}, Target: []string{"production"}, + Label: []string{"enhancement"}, }, want: &pipeline.Rules{ Branch: []string{"main"}, Comment: []string{"test comment"}, - Event: []string{"push"}, + Event: []string{"push", "pull_request:labeled"}, Path: []string{"foo.txt"}, Repo: []string{"github/octocat"}, Status: []string{"success"}, Tag: []string{"v0.1.0"}, Target: []string{"production"}, + Label: []string{"enhancement"}, }, }, } From f24f795ac0b7aef30fcf38a7bc41d337542654d3 Mon Sep 17 00:00:00 2001 From: dave vader <48764154+plyr4@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:55:48 -0500 Subject: [PATCH 09/18] enhance: return err in NewEventsFromSlice (#369) --- library/events.go | 9 +++++++-- library/events_test.go | 43 ++++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/library/events.go b/library/events.go index e93acb10..07095beb 100644 --- a/library/events.go +++ b/library/events.go @@ -3,6 +3,8 @@ package library import ( + "fmt" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library/actions" ) @@ -39,7 +41,7 @@ func NewEventsFromMask(mask int64) *Events { // NewEventsFromSlice is an instantiation function for the Events type that // takes in a slice of event strings and populates the nested Events struct. -func NewEventsFromSlice(events []string) *Events { +func NewEventsFromSlice(events []string) (*Events, error) { mask := int64(0) // iterate through all events provided @@ -88,10 +90,13 @@ func NewEventsFromSlice(events []string) *Events { // schedule actions case constants.EventSchedule, constants.EventSchedule + ":" + constants.ActionRun: mask = mask | constants.AllowSchedule + + default: + return nil, fmt.Errorf("invalid event provided: %s", event) } } - return NewEventsFromMask(mask) + return NewEventsFromMask(mask), nil } // Allowed determines whether or not an event + action is allowed based on whether diff --git a/library/events_test.go b/library/events_test.go index 79f6ee16..7356025c 100644 --- a/library/events_test.go +++ b/library/events_test.go @@ -207,19 +207,22 @@ func Test_NewEventsFromSlice(t *testing.T) { // setup tests tests := []struct { - name string - events []string - want *Events + name string + events []string + want *Events + failure bool }{ { - name: "action specific events to e1", - events: []string{"push:branch", "push:tag", "delete:branch", "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", "comment:created", "schedule:run", "pull_request:unlabeled"}, - want: e1, + name: "action specific events to e1", + events: []string{"push:branch", "push:tag", "delete:branch", "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", "comment:created", "schedule:run", "pull_request:unlabeled"}, + want: e1, + failure: false, }, { - name: "action specific events to e2", - events: []string{"delete:tag", "pull_request:edited", "deployment:created", "comment:edited", "pull_request:labeled"}, - want: e2, + name: "action specific events to e2", + events: []string{"delete:tag", "pull_request:edited", "deployment:created", "comment:edited", "pull_request:labeled"}, + want: e2, + failure: false, }, { name: "general events", @@ -250,6 +253,7 @@ func Test_NewEventsFromSlice(t *testing.T) { Run: &tBool, }, }, + failure: false, }, { name: "double events", @@ -280,17 +284,36 @@ func Test_NewEventsFromSlice(t *testing.T) { Run: &fBool, }, }, + failure: false, }, { name: "empty events", events: []string{}, want: NewEventsFromMask(0), }, + { + name: "invalid events", + events: []string{"foo:bar"}, + want: nil, + failure: true, + }, } // run tests for _, test := range tests { - got := NewEventsFromSlice(test.events) + got, err := NewEventsFromSlice(test.events) + + if test.failure { + if err == nil { + t.Errorf("NewEventsFromSlice should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("NewEventsFromSlice returned err: %v", err) + } if diff := cmp.Diff(test.want, got); diff != "" { t.Errorf("PopulateEvents failed for %s mismatch (-want +got):\n%s", test.name, diff) From cabbb617296d1cd2116070a3e0ec579a8c639088 Mon Sep 17 00:00:00 2001 From: dave vader <48764154+plyr4@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:19:12 -0500 Subject: [PATCH 10/18] fix(deployments): check for deployment created event action (#365) --- constants/action.go | 2 +- library/events.go | 2 +- library/events_test.go | 2 +- library/secret_test.go | 7 +++++-- yaml/ruleset.go | 3 +++ yaml/ruleset_test.go | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/constants/action.go b/constants/action.go index da0a4449..67e4e835 100644 --- a/constants/action.go +++ b/constants/action.go @@ -7,7 +7,7 @@ const ( // ActionOpened defines the action for opening pull requests. ActionOpened = "opened" - // ActionCreated defines the action for creating issue comments. + // ActionCreated defines the action for creating deployments or issue comments. ActionCreated = "created" // ActionEdited defines the action for the editing of pull requests or issue comments. diff --git a/library/events.go b/library/events.go index 07095beb..655b1b49 100644 --- a/library/events.go +++ b/library/events.go @@ -130,7 +130,7 @@ func (e *Events) Allowed(event, action string) bool { allowed = e.GetComment().GetCreated() case constants.EventComment + ":" + constants.ActionEdited: allowed = e.GetComment().GetEdited() - case constants.EventDeploy: + case constants.EventDeploy + ":" + constants.ActionCreated: allowed = e.GetDeployment().GetCreated() case constants.EventSchedule: allowed = e.GetSchedule().GetRun() diff --git a/library/events_test.go b/library/events_test.go index 7356025c..86771ea1 100644 --- a/library/events_test.go +++ b/library/events_test.go @@ -339,7 +339,7 @@ func TestLibrary_Events_Allowed(t *testing.T) { {event: "pull_request", action: "reopened", want: true}, {event: "pull_request", action: "labeled", want: false}, {event: "pull_request", action: "unlabeled", want: true}, - {event: "deployment", want: false}, + {event: "deployment", action: "created", want: false}, {event: "comment", action: "created", want: true}, {event: "comment", action: "edited", want: false}, {event: "schedule", want: true}, diff --git a/library/secret_test.go b/library/secret_test.go index ba0e3047..5074831f 100644 --- a/library/secret_test.go +++ b/library/secret_test.go @@ -112,8 +112,11 @@ func TestLibrary_Secret_Match(t *testing.T) { { name: "deployment", step: &pipeline.Container{ - Image: "alpine:latest", - Environment: map[string]string{"VELA_BUILD_EVENT": "deployment"}, + Image: "alpine:latest", + Environment: map[string]string{ + "VELA_BUILD_EVENT": "deployment", + "VELA_BUILD_EVENT_ACTION": "created", + }, }, sec: &Secret{ Name: &v, diff --git a/yaml/ruleset.go b/yaml/ruleset.go index 2fe23e16..4a6d87f7 100644 --- a/yaml/ruleset.go +++ b/yaml/ruleset.go @@ -159,6 +159,9 @@ func (r *Rules) UnmarshalYAML(unmarshal func(interface{}) error) error { constants.EventPull+":"+constants.ActionOpened, constants.EventPull+":"+constants.ActionSynchronize, constants.EventPull+":"+constants.ActionReopened) + case constants.EventDeploy: + events = append(events, + constants.EventDeploy+":"+constants.ActionCreated) case constants.EventComment: events = append(events, constants.EventComment+":"+constants.ActionCreated, diff --git a/yaml/ruleset_test.go b/yaml/ruleset_test.go index 559395ba..05a67ce1 100644 --- a/yaml/ruleset_test.go +++ b/yaml/ruleset_test.go @@ -116,7 +116,7 @@ func TestYaml_Ruleset_UnmarshalYAML(t *testing.T) { Tag: []string{"^refs/tags/(\\d+\\.)+\\d+$"}, }, Unless: Rules{ - Event: []string{"deployment", "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", "comment:created", "comment:edited", "schedule"}, + Event: []string{"deployment:created", "pull_request:opened", "pull_request:synchronize", "pull_request:reopened", "comment:created", "comment:edited", "schedule"}, Path: []string{"foo.txt", "/foo/bar.txt"}, }, Matcher: "regexp", From 6f3bf586c30b4d8d3158b3004951c161cbb7ddbe Mon Sep 17 00:00:00 2001 From: David May <49894298+wass3rw3rk@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:35:05 -0500 Subject: [PATCH 11/18] chore: pin go version; import order; linter setup (#371) to match https://github.com/go-vela/server/pull/1077, https://github.com/go-vela/server/pull/1101 --- .github/workflows/validate.yml | 5 +- .golangci.yml | 93 +++++++++++++++++++--------------- Makefile | 21 ++++++++ database/deployment.go | 3 +- database/deployment_test.go | 5 +- database/repo.go | 3 +- database/schedule.go | 1 + database/secret.go | 4 +- database/user.go | 3 +- database/worker.go | 3 +- go.mod | 2 +- library/actions/pull.go | 3 +- library/actions/push.go | 3 +- library/build_test.go | 3 +- library/events_test.go | 3 +- library/repo.go | 2 - library/repo_test.go | 3 +- library/secret_test.go | 3 +- yaml/build_test.go | 1 + yaml/ruleset_test.go | 1 + yaml/secret_test.go | 1 + yaml/service_test.go | 1 + yaml/stage.go | 4 +- yaml/stage_test.go | 4 +- yaml/step_test.go | 4 +- yaml/template_test.go | 1 + yaml/ulimit_test.go | 1 + yaml/volume_test.go | 1 + 28 files changed, 116 insertions(+), 66 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 0f039bfa..830e4166 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -33,4 +33,7 @@ jobs: # Check that go fmt ./... produces a zero diff; clean up any changes afterwards. go fmt ./... && git diff --exit-code; code=$?; git checkout -- .; (exit $code) # Check that go fix ./... produces a zero diff; clean up any changes afterwards. - go fix ./... && git diff --exit-code; code=$?; git checkout -- .; (exit $code) + # + # Renable this after https://github.com/golang/go/commit/7fd62ba821b1044e8e4077df052b0a1232672d57 + # has been released. + # go fix ./... && git diff --exit-code; code=$?; git checkout -- .; (exit $code) diff --git a/.golangci.yml b/.golangci.yml index ef42aeda..36e56668 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -32,6 +32,18 @@ linters-settings: lines: 160 statements: 70 + # https://github.com/daixiang0/gci + # ensure import order is consistent + # gci write --custom-order -s standard -s default -s blank -s dot -s "prefix(github.com/go-vela)" . + gci: + custom-order: true + sections: + - standard + - default + - blank + - dot + - prefix(github.com/go-vela) + # https://github.com/denis-tingaikin/go-header goheader: template: |- @@ -60,45 +72,46 @@ linters: # enable a specific set of linters to run enable: - - bidichk # checks for dangerous unicode character sequences - - bodyclose # checks whether HTTP response body is closed successfully - - contextcheck # check the function whether use a non-inherited context - - deadcode # finds unused code - - dupl # code clone detection - - errcheck # checks for unchecked errors - - errorlint # find misuses of errors - - exportloopref # check for exported loop vars - - funlen # detects long functions - - goconst # finds repeated strings that could be replaced by a constant - - gocyclo # computes and checks the cyclomatic complexity of functions - - godot # checks if comments end in a period - - gofmt # checks whether code was gofmt-ed - - goheader # checks is file header matches to pattern - - goimports # fixes imports and formats code in same style as gofmt - - gomoddirectives # manage the use of 'replace', 'retract', and 'excludes' directives in go.mod - - goprintffuncname # checks that printf-like functions are named with f at the end - - gosec # inspects code for security problems - - gosimple # linter that specializes in simplifying a code - - govet # reports suspicious constructs, ex. Printf calls whose arguments don't align with the format string - - ineffassign # detects when assignments to existing variables aren't used - - makezero # finds slice declarations with non-zero initial length - - misspell # finds commonly misspelled English words in comments - - nakedret # finds naked returns in functions greater than a specified function length - - nilerr # finds the code that returns nil even if it checks that the error is not nil - - noctx # noctx finds sending http request without context.Context - - nolintlint # reports ill-formed or insufficient nolint directives - - revive # linter for go - - staticcheck # applies static analysis checks, go vet on steroids - - structcheck # finds unused struct fields - - stylecheck # replacement for golint - - tenv # analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - typecheck # parses and type-checks go code, like the front-end of a go compiler - - unconvert # remove unnecessary type conversions - - unparam # reports unused function parameters - - unused # checks for unused constants, variables, functions and types - - varcheck # finds unused global variables and constants - - whitespace # detects leading and trailing whitespace - - wsl # forces code to use empty lines + - bidichk # checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - contextcheck # check the function whether use a non-inherited context + - deadcode # finds unused code + - dupl # code clone detection + - errcheck # checks for unchecked errors + - errorlint # find misuses of errors + - exportloopref # check for exported loop vars + - funlen # detects long functions + - gci # consistent import ordering + - goconst # finds repeated strings that could be replaced by a constant + - gocyclo # computes and checks the cyclomatic complexity of functions + - godot # checks if comments end in a period + - gofmt # checks whether code was gofmt-ed + - goheader # checks is file header matches to pattern + - goimports # fixes imports and formats code in same style as gofmt + - gomoddirectives # manage the use of 'replace', 'retract', and 'excludes' directives in go.mod + - goprintffuncname # checks that printf-like functions are named with f at the end + - gosec # inspects code for security problems + - gosimple # linter that specializes in simplifying a code + - govet # reports suspicious constructs, ex. Printf calls whose arguments don't align with the format string + - ineffassign # detects when assignments to existing variables aren't used + - makezero # finds slice declarations with non-zero initial length + - misspell # finds commonly misspelled English words in comments + - nakedret # finds naked returns in functions greater than a specified function length + - nilerr # finds the code that returns nil even if it checks that the error is not nil + - noctx # noctx finds sending http request without context.Context + - nolintlint # reports ill-formed or insufficient nolint directives + - revive # linter for go + - staticcheck # applies static analysis checks, go vet on steroids + - structcheck # finds unused struct fields + - stylecheck # replacement for golint + - tenv # analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + - typecheck # parses and type-checks go code, like the front-end of a go compiler + - unconvert # remove unnecessary type conversions + - unparam # reports unused function parameters + - unused # checks for unused constants, variables, functions and types + - varcheck # finds unused global variables and constants + - whitespace # detects leading and trailing whitespace + - wsl # forces code to use empty lines # static list of linters we know golangci can run but we've # chosen to leave disabled for now @@ -112,13 +125,13 @@ linters: # - exhaustivestruct - style preference # - forbidigo - unused # - forcetypeassert - unused - # - gci - use goimports # - gochecknoinits - unused # - gochecknoglobals - global variables allowed # - gocognit - unused complexity metric # - gocritic - style preference # - godox - to be used in the future # - goerr113 - to be used in the future + # - goimports - use gci # - golint - archived, replaced with revive # - gofumpt - use gofmt # - gomnd - get too many false-positives diff --git a/Makefile b/Makefile index 373dbb88..bd4d3e59 100644 --- a/Makefile +++ b/Makefile @@ -142,3 +142,24 @@ schema: @go get github.com/alecthomas/jsonschema @go get github.com/iancoleman/orderedmap @go run cmd/schema/main.go > schema.json + +# The `lint` target is intended to lint the +# Go source code with golangci-lint. +# +# Usage: `make lint` +.PHONY: lint +lint: + @echo + @echo "### Linting Go Code" + @golangci-lint run ./... + +# The `lintfix` target is intended to lint the +# Go source code with golangci-lint and apply +# any fixes that can be automatically applied. +# +# Usage: `make lintfix` +.PHONY: lintfix +lintfix: + @echo + @echo "### Fixing Go code with linter" + @golangci-lint run ./... --fix \ No newline at end of file diff --git a/database/deployment.go b/database/deployment.go index ba97ecdd..61a56136 100644 --- a/database/deployment.go +++ b/database/deployment.go @@ -7,10 +7,11 @@ import ( "errors" "fmt" + "github.com/lib/pq" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library" "github.com/go-vela/types/raw" - "github.com/lib/pq" ) var ( diff --git a/database/deployment_test.go b/database/deployment_test.go index 3a3c6f2f..e22b4481 100644 --- a/database/deployment_test.go +++ b/database/deployment_test.go @@ -6,10 +6,11 @@ import ( "database/sql" "testing" - "github.com/go-vela/types/library" - "github.com/go-vela/types/raw" "github.com/google/go-cmp/cmp" "github.com/lib/pq" + + "github.com/go-vela/types/library" + "github.com/go-vela/types/raw" ) func TestDatabase_Deployment_Nullify(t *testing.T) { diff --git a/database/repo.go b/database/repo.go index 03a3d22c..5c4f8c2c 100644 --- a/database/repo.go +++ b/database/repo.go @@ -7,9 +7,10 @@ import ( "encoding/base64" "errors" + "github.com/lib/pq" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library" - "github.com/lib/pq" ) var ( diff --git a/database/schedule.go b/database/schedule.go index 4f26b278..bd678b79 100644 --- a/database/schedule.go +++ b/database/schedule.go @@ -7,6 +7,7 @@ import ( "errors" "github.com/adhocore/gronx" + "github.com/go-vela/types/library" ) diff --git a/database/secret.go b/database/secret.go index 1c93cf85..33dcd800 100644 --- a/database/secret.go +++ b/database/secret.go @@ -8,10 +8,10 @@ import ( "errors" "strings" + "github.com/lib/pq" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library" - - "github.com/lib/pq" ) var ( diff --git a/database/user.go b/database/user.go index 1e312755..a5030bcc 100644 --- a/database/user.go +++ b/database/user.go @@ -8,9 +8,10 @@ import ( "errors" "regexp" + "github.com/lib/pq" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library" - "github.com/lib/pq" ) var ( diff --git a/database/worker.go b/database/worker.go index 59c2f343..45d76388 100644 --- a/database/worker.go +++ b/database/worker.go @@ -6,9 +6,10 @@ import ( "database/sql" "errors" + "github.com/lib/pq" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library" - "github.com/lib/pq" ) var ( diff --git a/go.mod b/go.mod index 14587f80..07d1e9ed 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/go-vela/types -go 1.21 +go 1.21.9 require ( github.com/adhocore/gronx v1.8.1 diff --git a/library/actions/pull.go b/library/actions/pull.go index 8e0063b1..b7d8f93c 100644 --- a/library/actions/pull.go +++ b/library/actions/pull.go @@ -1,6 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// -//nolint:dupl // similar code to push.go + package actions import "github.com/go-vela/types/constants" diff --git a/library/actions/push.go b/library/actions/push.go index ed19c48f..612b2cff 100644 --- a/library/actions/push.go +++ b/library/actions/push.go @@ -1,6 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// -//nolint:dupl // similar code to comment.go + package actions import "github.com/go-vela/types/constants" diff --git a/library/build_test.go b/library/build_test.go index 5c82c7a3..d9b810d7 100644 --- a/library/build_test.go +++ b/library/build_test.go @@ -8,8 +8,9 @@ import ( "testing" "time" - "github.com/go-vela/types/raw" "github.com/google/go-cmp/cmp" + + "github.com/go-vela/types/raw" ) func TestLibrary_Build_Duration(t *testing.T) { diff --git a/library/events_test.go b/library/events_test.go index 86771ea1..c224f989 100644 --- a/library/events_test.go +++ b/library/events_test.go @@ -6,9 +6,10 @@ import ( "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library/actions" - "github.com/google/go-cmp/cmp" ) func TestLibrary_Events_Getters(t *testing.T) { diff --git a/library/repo.go b/library/repo.go index 0f82207b..8755d524 100644 --- a/library/repo.go +++ b/library/repo.go @@ -618,8 +618,6 @@ func (r *Repo) SetApproveBuild(v string) { } // String implements the Stringer interface for the Repo type. -// -//nolint:dupl // ignore duplicate with test func func (r *Repo) String() string { return fmt.Sprintf(`{ Active: %t, diff --git a/library/repo_test.go b/library/repo_test.go index f9eaba2b..e102e103 100644 --- a/library/repo_test.go +++ b/library/repo_test.go @@ -7,8 +7,9 @@ import ( "reflect" "testing" - "github.com/go-vela/types/constants" "github.com/google/go-cmp/cmp" + + "github.com/go-vela/types/constants" ) func TestLibrary_Repo_Environment(t *testing.T) { diff --git a/library/secret_test.go b/library/secret_test.go index 5074831f..48655a7c 100644 --- a/library/secret_test.go +++ b/library/secret_test.go @@ -8,10 +8,11 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library/actions" "github.com/go-vela/types/pipeline" - "github.com/google/go-cmp/cmp" ) func TestLibrary_Secret_Sanitize(t *testing.T) { diff --git a/yaml/build_test.go b/yaml/build_test.go index 8da97c90..a1ca6cc3 100644 --- a/yaml/build_test.go +++ b/yaml/build_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/buildkite/yaml" + "github.com/go-vela/types/library" "github.com/go-vela/types/raw" ) diff --git a/yaml/ruleset_test.go b/yaml/ruleset_test.go index 05a67ce1..9b95f304 100644 --- a/yaml/ruleset_test.go +++ b/yaml/ruleset_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/buildkite/yaml" + "github.com/go-vela/types/pipeline" ) diff --git a/yaml/secret_test.go b/yaml/secret_test.go index f70637e6..9918b8cf 100644 --- a/yaml/secret_test.go +++ b/yaml/secret_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/buildkite/yaml" + "github.com/go-vela/types/pipeline" ) diff --git a/yaml/service_test.go b/yaml/service_test.go index d0404eef..1289095c 100644 --- a/yaml/service_test.go +++ b/yaml/service_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/buildkite/yaml" + "github.com/go-vela/types/pipeline" "github.com/go-vela/types/raw" ) diff --git a/yaml/stage.go b/yaml/stage.go index bfc0dffb..65943bd9 100644 --- a/yaml/stage.go +++ b/yaml/stage.go @@ -5,10 +5,10 @@ package yaml import ( "fmt" + "github.com/buildkite/yaml" + "github.com/go-vela/types/pipeline" "github.com/go-vela/types/raw" - - "github.com/buildkite/yaml" ) type ( diff --git a/yaml/stage_test.go b/yaml/stage_test.go index cf90ba48..5cad3cb7 100644 --- a/yaml/stage_test.go +++ b/yaml/stage_test.go @@ -7,9 +7,9 @@ import ( "reflect" "testing" - "github.com/go-vela/types/pipeline" - "github.com/buildkite/yaml" + + "github.com/go-vela/types/pipeline" ) func TestYaml_StageSlice_ToPipeline(t *testing.T) { diff --git a/yaml/step_test.go b/yaml/step_test.go index 2d0b6034..8136fcaf 100644 --- a/yaml/step_test.go +++ b/yaml/step_test.go @@ -7,10 +7,10 @@ import ( "reflect" "testing" + "github.com/buildkite/yaml" + "github.com/go-vela/types/pipeline" "github.com/go-vela/types/raw" - - "github.com/buildkite/yaml" ) func TestYaml_StepSlice_ToPipeline(t *testing.T) { diff --git a/yaml/template_test.go b/yaml/template_test.go index 39827760..e7f760cb 100644 --- a/yaml/template_test.go +++ b/yaml/template_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/buildkite/yaml" + "github.com/go-vela/types/library" ) diff --git a/yaml/ulimit_test.go b/yaml/ulimit_test.go index 46d28bde..dc6fdac6 100644 --- a/yaml/ulimit_test.go +++ b/yaml/ulimit_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/buildkite/yaml" + "github.com/go-vela/types/pipeline" ) diff --git a/yaml/volume_test.go b/yaml/volume_test.go index dc7d9513..837703ad 100644 --- a/yaml/volume_test.go +++ b/yaml/volume_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/buildkite/yaml" + "github.com/go-vela/types/pipeline" ) From c5cba4ecf5536a76637a3e0211fc60b4c6565486 Mon Sep 17 00:00:00 2001 From: David May <49894298+wass3rw3rk@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:11:25 -0500 Subject: [PATCH 12/18] chore(linter): remove goimports (#372) --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 36e56668..a369eb67 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -87,7 +87,6 @@ linters: - godot # checks if comments end in a period - gofmt # checks whether code was gofmt-ed - goheader # checks is file header matches to pattern - - goimports # fixes imports and formats code in same style as gofmt - gomoddirectives # manage the use of 'replace', 'retract', and 'excludes' directives in go.mod - goprintffuncname # checks that printf-like functions are named with f at the end - gosec # inspects code for security problems From fb4a95c30338777b10416ff3c6f1ed249eb8e9b7 Mon Sep 17 00:00:00 2001 From: dave vader <48764154+plyr4@users.noreply.github.com> Date: Wed, 17 Apr 2024 08:50:26 -0500 Subject: [PATCH 13/18] fix: allow events yaml unmarshal (#370) --- library/events.go | 25 +++++++++++++++++++++++++ library/repo.go | 21 ++++++++++++++++++++- library/secret.go | 21 ++++++++++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/library/events.go b/library/events.go index 655b1b49..48351517 100644 --- a/library/events.go +++ b/library/events.go @@ -3,10 +3,12 @@ package library import ( + "errors" "fmt" "github.com/go-vela/types/constants" "github.com/go-vela/types/library/actions" + "github.com/go-vela/types/raw" ) // Events is the library representation of the various events that generate a @@ -19,6 +21,29 @@ type Events struct { Schedule *actions.Schedule `json:"schedule"` } +// UnmarshalYAML implements the Unmarshaler interface for the Events type. +func (e *Events) UnmarshalYAML(unmarshal func(interface{}) error) error { + // string slice we try unmarshalling to + stringSlice := new(raw.StringSlice) + + // attempt to unmarshal as a string slice type + err := unmarshal(stringSlice) + if err == nil { + // create new events from string slice + evs, err := NewEventsFromSlice(*stringSlice) + if err != nil { + return err + } + + // overwrite existing Events + *e = *evs + + return nil + } + + return errors.New("failed to unmarshal Events") +} + // NewEventsFromMask is an instatiation function for the Events type that // takes in an event mask integer value and populates the nested Events struct. func NewEventsFromMask(mask int64) *Events { diff --git a/library/repo.go b/library/repo.go index 8755d524..46c87df7 100644 --- a/library/repo.go +++ b/library/repo.go @@ -28,12 +28,31 @@ type Repo struct { Private *bool `json:"private,omitempty"` Trusted *bool `json:"trusted,omitempty"` Active *bool `json:"active,omitempty"` - AllowEvents *Events `json:"allow_events,omitempty"` + AllowEvents *Events `json:"allow_events,omitempty" yaml:"allow_events"` PipelineType *string `json:"pipeline_type,omitempty"` PreviousName *string `json:"previous_name,omitempty"` ApproveBuild *string `json:"approve_build,omitempty"` } +// UnmarshalYAML implements the Unmarshaler interface for the Repo type. +// This allows custom fields in the Repo type to be read from a YAML file, like AllowEvents. +func (r *Repo) UnmarshalYAML(unmarshal func(interface{}) error) error { + // create an alias to perform a normal unmarshal and avoid an infinite loop + type jsonRepo Repo + + tmp := &jsonRepo{} + + err := unmarshal(tmp) + if err != nil { + return err + } + + // overwrite existing Repo + *r = Repo(*tmp) + + return nil +} + // Environment returns a list of environment variables // provided from the fields of the Repo type. func (r *Repo) Environment() map[string]string { diff --git a/library/secret.go b/library/secret.go index 57aa3e84..099efb55 100644 --- a/library/secret.go +++ b/library/secret.go @@ -22,7 +22,7 @@ type Secret struct { Value *string `json:"value,omitempty"` Type *string `json:"type,omitempty"` Images *[]string `json:"images,omitempty"` - AllowEvents *Events `json:"allow_events,omitempty"` + AllowEvents *Events `json:"allow_events,omitempty" yaml:"allow_events"` AllowCommand *bool `json:"allow_command,omitempty"` AllowSubstitution *bool `json:"allow_substitution,omitempty"` CreatedAt *int64 `json:"created_at,omitempty"` @@ -31,6 +31,25 @@ type Secret struct { UpdatedBy *string `json:"updated_by,omitempty"` } +// UnmarshalYAML implements the Unmarshaler interface for the Secret type. +// This allows custom fields in the Secret type to be read from a YAML file, like AllowEvents. +func (s *Secret) UnmarshalYAML(unmarshal func(interface{}) error) error { + // create an alias to perform a normal unmarshal and avoid an infinite loop + type jsonSecret Secret + + tmp := &jsonSecret{} + + err := unmarshal(tmp) + if err != nil { + return err + } + + // overwrite existing secret + *s = Secret(*tmp) + + return nil +} + // Sanitize creates a duplicate of the Secret without the value. func (s *Secret) Sanitize() *Secret { // create a variable since constants can not be addressable From 7c1c74175c5022dad77d6fe2a99e858be68bafc3 Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Tue, 7 May 2024 15:43:08 -0400 Subject: [PATCH 14/18] fix(ci): use intermediate env variable for PR title validator (#377) * fix(ci): use intermediate env var for PR title * use server exclaim pattern --- .github/workflows/pr-title-validate.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-title-validate.yml b/.github/workflows/pr-title-validate.yml index 223f7cdf..dc8c67be 100644 --- a/.github/workflows/pr-title-validate.yml +++ b/.github/workflows/pr-title-validate.yml @@ -13,5 +13,7 @@ jobs: steps: - name: validate title + env: + TITLE: ${{ github.event.pull_request.title }} run: | - echo "${{ github.event.pull_request.title }}" | grep -Eq '^(feat|fix|chore|refactor|enhance|test|docs)(\(.*\)|):\s.+$' && (echo "Pass"; exit 0) || (echo "Incorrect Format. Please see https://go-vela.github.io/docs/community/contributing_guidelines/#development-workflow"; exit 1) \ No newline at end of file + echo "$TITLE" | grep -Eq '^(feat|fix|chore|refactor|enhance|test|docs)(\(.*\)|)!?:\s.+$' && (echo "Pass"; exit 0) || (echo "Incorrect Format. Please see https://go-vela.github.io/docs/community/contributing_guidelines/#development-workflow"; exit 1) \ No newline at end of file From 88010b52190c9fc88c8d84aac2eb5a61721f6acc Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Wed, 8 May 2024 14:20:05 -0400 Subject: [PATCH 15/18] fix(ci): remove deprecated linter rules (#378) --- .golangci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a369eb67..4ae4c744 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -75,7 +75,6 @@ linters: - bidichk # checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - - deadcode # finds unused code - dupl # code clone detection - errcheck # checks for unchecked errors - errorlint # find misuses of errors @@ -101,14 +100,12 @@ linters: - nolintlint # reports ill-formed or insufficient nolint directives - revive # linter for go - staticcheck # applies static analysis checks, go vet on steroids - - structcheck # finds unused struct fields - stylecheck # replacement for golint - tenv # analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - typecheck # parses and type-checks go code, like the front-end of a go compiler - unconvert # remove unnecessary type conversions - unparam # reports unused function parameters - unused # checks for unused constants, variables, functions and types - - varcheck # finds unused global variables and constants - whitespace # detects leading and trailing whitespace - wsl # forces code to use empty lines From 57d6b8f77b1048998d02f23215fa85b26e9e1975 Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Thu, 16 May 2024 11:11:14 -0500 Subject: [PATCH 16/18] feat: Vela OIDC Provider (#375) * init commit * add tests --------- Co-authored-by: david may <1301201+wass3r@users.noreply.github.com> --- pipeline/container.go | 4 +++- pipeline/container_test.go | 1 + yaml/step.go | 2 ++ yaml/step_test.go | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pipeline/container.go b/pipeline/container.go index fcd12080..3d427cb0 100644 --- a/pipeline/container.go +++ b/pipeline/container.go @@ -52,6 +52,7 @@ type ( Volumes VolumeSlice `json:"volumes,omitempty" yaml:"volumes,omitempty"` User string `json:"user,omitempty" yaml:"user,omitempty"` ReportAs string `json:"report_as,omitempty" yaml:"report_as,omitempty"` + IDRequest string `json:"id_request,omitempty" yaml:"id_request,omitempty"` } ) @@ -135,7 +136,8 @@ func (c *Container) Empty() bool { len(c.Ulimits) == 0 && len(c.Volumes) == 0 && len(c.User) == 0 && - len(c.ReportAs) == 0 { + len(c.ReportAs) == 0 && + len(c.IDRequest) == 0 { return true } diff --git a/pipeline/container_test.go b/pipeline/container_test.go index 1e959cb5..3f5e3a45 100644 --- a/pipeline/container_test.go +++ b/pipeline/container_test.go @@ -932,6 +932,7 @@ func testContainers() *ContainerSlice { Name: "clone", Number: 2, Pull: "always", + IDRequest: "yes", }, { ID: "step_github/octocat._1_echo", diff --git a/yaml/step.go b/yaml/step.go index 396a3b74..feadb8a9 100644 --- a/yaml/step.go +++ b/yaml/step.go @@ -35,6 +35,7 @@ type ( Privileged bool `yaml:"privileged,omitempty" json:"privileged,omitempty" jsonschema:"description=Run the container with extra privileges.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-privileged-tag"` User string `yaml:"user,omitempty" json:"user,omitempty" jsonschema:"description=Set the user for the container.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-user-tag"` ReportAs string `yaml:"report_as,omitempty" json:"report_as,omitempty" jsonschema:"description=Set the name of the step to report as.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-report_as-tag"` + IDRequest string `yaml:"id_request,omitempty" json:"id_request,omitempty" jsonschema:"description=Request ID Request Token for the step.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-id_request-tag"` } ) @@ -62,6 +63,7 @@ func (s *StepSlice) ToPipeline() *pipeline.ContainerSlice { Volumes: *step.Volumes.ToPipeline(), User: step.User, ReportAs: step.ReportAs, + IDRequest: step.IDRequest, }) } diff --git a/yaml/step_test.go b/yaml/step_test.go index 8136fcaf..686631a6 100644 --- a/yaml/step_test.go +++ b/yaml/step_test.go @@ -31,6 +31,7 @@ func TestYaml_StepSlice_ToPipeline(t *testing.T) { Privileged: false, Pull: "not_present", ReportAs: "my-step", + IDRequest: "yes", Ruleset: Ruleset{ If: Rules{ Branch: []string{"main"}, @@ -88,6 +89,7 @@ func TestYaml_StepSlice_ToPipeline(t *testing.T) { Privileged: false, Pull: "not_present", ReportAs: "my-step", + IDRequest: "yes", Ruleset: pipeline.Ruleset{ If: pipeline.Rules{ Branch: []string{"main"}, From 8cf18f9fcd6290b6e31bb312338caedc87317504 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:13:32 -0500 Subject: [PATCH 17/18] chore(deps): bump golang.org/x/net from 0.17.0 to 0.23.0 (#374) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.17.0 to 0.23.0. - [Commits](https://github.com/golang/net/compare/v0.17.0...v0.23.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Easton Crupper <65553218+ecrupper@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 07d1e9ed..496f3ce4 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/gorilla/css v1.0.0 // indirect github.com/kr/pretty v0.2.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.23.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect ) diff --git a/go.sum b/go.sum index 00c3fd42..037bfbec 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From f69ce1273de4ec63d5691d9ce4a26e31ae8b3e3c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:15:02 -0500 Subject: [PATCH 18/18] chore(deps): update all non-major dependencies (#368) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 10 +++++----- .github/workflows/reviewdog.yml | 8 ++++---- .github/workflows/schema.yml | 4 ++-- .github/workflows/test.yml | 6 +++--- .github/workflows/validate.yml | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ca4a3929..7433661c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,10 +35,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: install go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: # use version from go.mod file go-version-file: 'go.mod' @@ -47,7 +47,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 + uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -58,7 +58,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 + uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -72,4 +72,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 + uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8 diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 5ccd8653..68ea470a 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -12,10 +12,10 @@ jobs: steps: - name: clone - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: install go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: # use version from go.mod file go-version-file: 'go.mod' @@ -36,10 +36,10 @@ jobs: steps: - name: clone - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: install go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: # use version from go.mod file go-version-file: 'go.mod' diff --git a/.github/workflows/schema.yml b/.github/workflows/schema.yml index 352fe0d4..57f62ac7 100644 --- a/.github/workflows/schema.yml +++ b/.github/workflows/schema.yml @@ -13,10 +13,10 @@ jobs: steps: - name: clone - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: install go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: # use version from go.mod file go-version-file: 'go.mod' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ff6dc9b7..60108803 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,10 +14,10 @@ jobs: steps: - name: clone - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: install go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: # use version from go.mod file go-version-file: 'go.mod' @@ -29,7 +29,7 @@ jobs: go test -race -covermode=atomic -coverprofile=coverage.out ./... - name: coverage - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0 + uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1 with: token: ${{ secrets.CODECOV_TOKEN }} file: coverage.out diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 830e4166..700684ba 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -14,10 +14,10 @@ jobs: steps: - name: clone - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: install go - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: # use version from go.mod file go-version-file: 'go.mod'