From 23c15858da2a56259b0cf6c2cf77aeb9e24d3f95 Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Fri, 8 Dec 2023 14:31:36 -0500 Subject: [PATCH 1/2] feat(repo)!: change `allow_` fields to an `AllowEvents` struct + DB use integer masking (#314) * iota * nested lib type * comments for getters and setters * feat(repo)change allow events fields to an AllowEvents struct * remove pull review event constant * create repo method for event allowed * linter * remove unused schedule actions struct * copyright lint changes * remove temp files used for debugging some tests * move event_actions into separate package * leave space for future implemented pull actions * add more PR actions and bring back legacy fields * Update constants/allow_events.go Co-authored-by: Kelly Merrick --------- Co-authored-by: David May <49894298+wass3rw3rk@users.noreply.github.com> Co-authored-by: Kelly Merrick --- constants/allow_events.go | 23 +++++ database/repo.go | 8 ++ database/repo_test.go | 8 ++ item_test.go | 4 + library/actions/comment.go | 84 +++++++++++++++ library/actions/comment_test.go | 108 ++++++++++++++++++++ library/actions/deploy.go | 53 ++++++++++ library/actions/deploy_test.go | 98 ++++++++++++++++++ library/actions/pull.go | 113 ++++++++++++++++++++ library/actions/pull_test.go | 118 +++++++++++++++++++++ library/actions/push.go | 84 +++++++++++++++ library/actions/push_test.go | 112 ++++++++++++++++++++ library/events.go | 176 ++++++++++++++++++++++++++++++++ library/events_test.go | 146 ++++++++++++++++++++++++++ library/repo.go | 65 ++++++++++++ library/repo_test.go | 51 +++++++++ 16 files changed, 1251 insertions(+) create mode 100644 constants/allow_events.go create mode 100644 library/actions/comment.go create mode 100644 library/actions/comment_test.go create mode 100644 library/actions/deploy.go create mode 100644 library/actions/deploy_test.go create mode 100644 library/actions/pull.go create mode 100644 library/actions/pull_test.go create mode 100644 library/actions/push.go create mode 100644 library/actions/push_test.go create mode 100644 library/events.go create mode 100644 library/events_test.go diff --git a/constants/allow_events.go b/constants/allow_events.go new file mode 100644 index 00000000..f6571b43 --- /dev/null +++ b/constants/allow_events.go @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 + +package constants + +// Allowed repo events. NOTE: these can NOT change order. New events must be added at the end. +const ( + AllowPushBranch = 1 << iota // 00000001 = 1 + AllowPushTag // 00000010 = 2 + AllowPullOpen // 00000100 = 4 + AllowPullEdit // ... + AllowPullSync + _ // AllowPullAssigned - Not Implemented + _ // AllowPullMilestoned - Not Implemented + _ // AllowPullLabel - Not Implemented + _ // AllowPullLocked - Not Implemented + _ // AllowPullReady - Not Implemented + _ // AllowPullReopen - Not Implemented + _ // AllowPullReviewRequest - Not Implemented + _ // AllowPullClosed - Not Implemented + AllowDeployCreate + AllowCommentCreate + AllowCommentEdit +) diff --git a/database/repo.go b/database/repo.go index 1c185b68..8fde8286 100644 --- a/database/repo.go +++ b/database/repo.go @@ -66,6 +66,7 @@ type Repo struct { 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"` ApproveBuild sql.NullString `sql:"approve_build"` @@ -184,6 +185,11 @@ func (r *Repo) Nullify() *Repo { r.Timeout.Valid = false } + // check if the AllowEvents field should be false + if r.AllowEvents.Int64 == 0 { + r.AllowEvents.Valid = false + } + // check if the Visibility field should be false if len(r.Visibility.String) == 0 { r.Visibility.Valid = false @@ -234,6 +240,7 @@ func (r *Repo) ToLibrary() *library.Repo { 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) repo.SetApproveBuild(r.ApproveBuild.String) @@ -330,6 +337,7 @@ func RepoFromLibrary(r *library.Repo) *Repo { 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}, ApproveBuild: sql.NullString{String: r.GetApproveBuild(), Valid: true}, diff --git a/database/repo_test.go b/database/repo_test.go index cf7d2436..3aa63fca 100644 --- a/database/repo_test.go +++ b/database/repo_test.go @@ -9,6 +9,7 @@ import ( "github.com/go-vela/types/constants" "github.com/go-vela/types/library" + "github.com/go-vela/types/library/actions" ) func TestDatabase_Repo_Decrypt(t *testing.T) { @@ -117,6 +118,7 @@ func TestDatabase_Repo_Nullify(t *testing.T) { Clone: sql.NullString{String: "", Valid: false}, Branch: sql.NullString{String: "", Valid: false}, Timeout: sql.NullInt64{Int64: 0, Valid: false}, + AllowEvents: sql.NullInt64{Int64: 0, Valid: false}, Visibility: sql.NullString{String: "", Valid: false}, PipelineType: sql.NullString{String: "", Valid: false}, ApproveBuild: sql.NullString{String: "", Valid: false}, @@ -154,6 +156,7 @@ func TestDatabase_Repo_Nullify(t *testing.T) { func TestDatabase_Repo_ToLibrary(t *testing.T) { // setup types want := new(library.Repo) + e := library.NewEventsFromMask(1) want.SetID(1) want.SetUserID(1) @@ -177,6 +180,7 @@ func TestDatabase_Repo_ToLibrary(t *testing.T) { want.SetAllowDeploy(false) want.SetAllowTag(false) want.SetAllowComment(false) + want.SetAllowEvents(e) want.SetPipelineType("yaml") want.SetPreviousName("oldName") want.SetApproveBuild(constants.ApproveNever) @@ -308,6 +312,8 @@ func TestDatabase_Repo_Validate(t *testing.T) { func TestDatabase_RepoFromLibrary(t *testing.T) { // setup types r := new(library.Repo) + e := new(library.Events) + e.SetPush(new(actions.Push).FromMask(1)) r.SetID(1) r.SetUserID(1) @@ -331,6 +337,7 @@ func TestDatabase_RepoFromLibrary(t *testing.T) { r.SetAllowDeploy(false) r.SetAllowTag(false) r.SetAllowComment(false) + r.SetAllowEvents(e) r.SetPipelineType("yaml") r.SetPreviousName("oldName") r.SetApproveBuild(constants.ApproveNever) @@ -371,6 +378,7 @@ func testRepo() *Repo { 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}, ApproveBuild: sql.NullString{String: constants.ApproveNever, Valid: true}, diff --git a/item_test.go b/item_test.go index 846463de..8643f3e1 100644 --- a/item_test.go +++ b/item_test.go @@ -15,6 +15,8 @@ func TestTypes_ToItem(t *testing.T) { num := 1 num64 := int64(num) str := "foo" + e := new(library.Events) + b := &library.Build{ ID: &num64, RepoID: &num64, @@ -57,6 +59,7 @@ func TestTypes_ToItem(t *testing.T) { AllowPush: &booL, AllowDeploy: &booL, AllowTag: &booL, + AllowEvents: e, } u := &library.User{ ID: &num64, @@ -108,6 +111,7 @@ func TestTypes_ToItem(t *testing.T) { AllowPush: &booL, AllowDeploy: &booL, AllowTag: &booL, + AllowEvents: e, }, User: &library.User{ ID: &num64, diff --git a/library/actions/comment.go b/library/actions/comment.go new file mode 100644 index 00000000..b221a132 --- /dev/null +++ b/library/actions/comment.go @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: Apache-2.0 +// +//nolint:dupl // ignore dup code +package actions + +import "github.com/go-vela/types/constants" + +// Comment is the library representation of the various actions associated +// with the comment event webhook from the SCM. +type Comment struct { + Created *bool `json:"created"` + Edited *bool `json:"edited"` +} + +// FromMask returns the Comment type resulting from the provided integer mask. +func (a *Comment) FromMask(mask int64) *Comment { + a.SetCreated(mask&constants.AllowCommentCreate > 0) + a.SetEdited(mask&constants.AllowCommentEdit > 0) + + return a +} + +// ToMask returns the integer mask of the values for the Comment set. +func (a *Comment) ToMask() int64 { + mask := int64(0) + + if a.GetCreated() { + mask = mask | constants.AllowCommentCreate + } + + if a.GetEdited() { + mask = mask | constants.AllowCommentEdit + } + + return mask +} + +// GetCreated returns the Created field from the provided Comment. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (a *Comment) GetCreated() bool { + // return zero value if Events type or Created field is nil + if a == nil || a.Created == nil { + return false + } + + return *a.Created +} + +// GetEdited returns the Edited field from the provided Comment. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (a *Comment) GetEdited() bool { + // return zero value if Events type or Edited field is nil + if a == nil || a.Edited == nil { + return false + } + + return *a.Edited +} + +// SetCreated sets the Comment Created field. +// +// When the provided Events type is nil, it +// will set nothing and immediately return. +func (a *Comment) SetCreated(v bool) { + // return if Events type is nil + if a == nil { + return + } + + a.Created = &v +} + +// SetEdited sets the Comment Edited field. +// +// When the provided Events type is nil, it +// will set nothing and immediately return. +func (a *Comment) SetEdited(v bool) { + // return if Events type is nil + if a == nil { + return + } + + a.Edited = &v +} diff --git a/library/actions/comment_test.go b/library/actions/comment_test.go new file mode 100644 index 00000000..3db6e4ba --- /dev/null +++ b/library/actions/comment_test.go @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: Apache-2.0 + +package actions + +import ( + "reflect" + "testing" + + "github.com/go-vela/types/constants" +) + +func TestLibrary_Comment_Getters(t *testing.T) { + // setup tests + tests := []struct { + actions *Comment + want *Comment + }{ + { + actions: testComment(), + want: testComment(), + }, + { + actions: new(Comment), + want: new(Comment), + }, + } + + // run tests + for _, test := range tests { + if test.actions.GetCreated() != test.want.GetCreated() { + t.Errorf("GetCreated is %v, want %v", test.actions.GetCreated(), test.want.GetCreated()) + } + + if test.actions.GetEdited() != test.want.GetEdited() { + t.Errorf("GetEdited is %v, want %v", test.actions.GetEdited(), test.want.GetEdited()) + } + } +} + +func TestLibrary_Comment_Setters(t *testing.T) { + // setup types + var a *Comment + + // setup tests + tests := []struct { + actions *Comment + want *Comment + }{ + { + actions: testComment(), + want: testComment(), + }, + { + actions: a, + want: new(Comment), + }, + } + + // run tests + for _, test := range tests { + test.actions.SetCreated(test.want.GetCreated()) + test.actions.SetEdited(test.want.GetEdited()) + + if test.actions.GetCreated() != test.want.GetCreated() { + t.Errorf("SetCreated is %v, want %v", test.actions.GetCreated(), test.want.GetCreated()) + } + + if test.actions.GetEdited() != test.want.GetEdited() { + t.Errorf("SetEdited is %v, want %v", test.actions.GetEdited(), test.want.GetEdited()) + } + } +} + +func TestLibrary_Comment_FromMask(t *testing.T) { + // setup types + mask := testMask() + + want := testComment() + + // run test + got := new(Comment).FromMask(mask) + + if !reflect.DeepEqual(got, want) { + t.Errorf("FromMask is %v, want %v", got, want) + } +} + +func TestLibrary_Comment_ToMask(t *testing.T) { + // setup types + actions := testComment() + + want := int64(constants.AllowCommentCreate) + + // run test + got := actions.ToMask() + + if want != got { + t.Errorf("ToMask is %v, want %v", got, want) + } +} + +func testComment() *Comment { + comment := new(Comment) + comment.SetCreated(true) + comment.SetEdited(false) + + return comment +} diff --git a/library/actions/deploy.go b/library/actions/deploy.go new file mode 100644 index 00000000..e2b663bf --- /dev/null +++ b/library/actions/deploy.go @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: Apache-2.0 + +package actions + +import "github.com/go-vela/types/constants" + +// Deploy is the library representation of the various actions associated +// with the deploy event webhook from the SCM. +type Deploy struct { + Created *bool `json:"created"` +} + +// FromMask returns the Deploy type resulting from the provided integer mask. +func (a *Deploy) FromMask(mask int64) *Deploy { + a.SetCreated(mask&constants.AllowDeployCreate > 0) + + return a +} + +// ToMask returns the integer mask of the values for the Deploy set. +func (a *Deploy) ToMask() int64 { + mask := int64(0) + + if a.GetCreated() { + mask = mask | constants.AllowDeployCreate + } + + return mask +} + +// GetCreated returns the Created field from the provided Deploy. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (a *Deploy) GetCreated() bool { + // return zero value if Deploy type or Created field is nil + if a == nil || a.Created == nil { + return false + } + + return *a.Created +} + +// SetCreated sets the Deploy Created field. +// +// When the provided Deploy type is nil, it +// will set nothing and immediately return. +func (a *Deploy) SetCreated(v bool) { + // return if Deploy type is nil + if a == nil { + return + } + + a.Created = &v +} diff --git a/library/actions/deploy_test.go b/library/actions/deploy_test.go new file mode 100644 index 00000000..008276d4 --- /dev/null +++ b/library/actions/deploy_test.go @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache-2.0 + +package actions + +import ( + "reflect" + "testing" + + "github.com/go-vela/types/constants" +) + +func TestLibrary_Deploy_Getters(t *testing.T) { + // setup tests + tests := []struct { + actions *Deploy + want *Deploy + }{ + { + actions: testDeploy(), + want: testDeploy(), + }, + { + actions: new(Deploy), + want: new(Deploy), + }, + } + + // run tests + for _, test := range tests { + if test.actions.GetCreated() != test.want.GetCreated() { + t.Errorf("GetCreated is %v, want %v", test.actions.GetCreated(), test.want.GetCreated()) + } + } +} + +func TestLibrary_Deploy_Setters(t *testing.T) { + // setup types + var a *Deploy + + // setup tests + tests := []struct { + actions *Deploy + want *Deploy + }{ + { + actions: testDeploy(), + want: testDeploy(), + }, + { + actions: a, + want: new(Deploy), + }, + } + + // run tests + for _, test := range tests { + test.actions.SetCreated(test.want.GetCreated()) + + if test.actions.GetCreated() != test.want.GetCreated() { + t.Errorf("SetCreated is %v, want %v", test.actions.GetCreated(), test.want.GetCreated()) + } + } +} + +func TestLibrary_Deploy_FromMask(t *testing.T) { + // setup types + mask := testMask() + + want := testDeploy() + + // run test + got := new(Deploy).FromMask(mask) + + if !reflect.DeepEqual(got, want) { + t.Errorf("FromMask is %v, want %v", got, want) + } +} + +func TestLibrary_Deploy_ToMask(t *testing.T) { + // setup types + actions := testDeploy() + + want := int64(constants.AllowDeployCreate) + + // run test + got := actions.ToMask() + + if want != got { + t.Errorf("ToMask is %v, want %v", got, want) + } +} + +func testDeploy() *Deploy { + deploy := new(Deploy) + deploy.SetCreated(true) + + return deploy +} diff --git a/library/actions/pull.go b/library/actions/pull.go new file mode 100644 index 00000000..d2d4100a --- /dev/null +++ b/library/actions/pull.go @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 + +package actions + +import "github.com/go-vela/types/constants" + +// Pull is the library representation of the various actions associated +// with the pull_request event webhook from the SCM. +type Pull struct { + Opened *bool `json:"opened"` + Edited *bool `json:"edited"` + Synchronize *bool `json:"synchronize"` +} + +// FromMask returns the Pull type resulting from the provided integer mask. +func (a *Pull) FromMask(mask int64) *Pull { + a.SetOpened(mask&constants.AllowPullOpen > 0) + a.SetSynchronize(mask&constants.AllowPullSync > 0) + a.SetEdited(mask&constants.AllowPullEdit > 0) + + return a +} + +// ToMask returns the integer mask of the values for the Pull set. +func (a *Pull) ToMask() int64 { + mask := int64(0) + + if a.GetOpened() { + mask = mask | constants.AllowPullOpen + } + + if a.GetSynchronize() { + mask = mask | constants.AllowPullSync + } + + if a.GetEdited() { + mask = mask | constants.AllowPullEdit + } + + return mask +} + +// GetOpened returns the Opened 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) GetOpened() bool { + // return zero value if Pull type or Opened field is nil + if a == nil || a.Opened == nil { + return false + } + + return *a.Opened +} + +// GetSynchronize returns the Synchronize 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) GetSynchronize() bool { + // return zero value if Pull type or Synchronize field is nil + if a == nil || a.Synchronize == nil { + return false + } + + return *a.Synchronize +} + +// GetEdited returns the Edited 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) GetEdited() bool { + // return zero value if Pull type or Edited field is nil + if a == nil || a.Edited == nil { + return false + } + + return *a.Edited +} + +// SetOpened sets the Pull Opened field. +// +// When the provided Pull type is nil, it +// will set nothing and immediately return. +func (a *Pull) SetOpened(v bool) { + // return if Pull type is nil + if a == nil { + return + } + + a.Opened = &v +} + +// SetSynchronize sets the Pull Synchronize field. +// +// When the provided Pull type is nil, it +// will set nothing and immediately return. +func (a *Pull) SetSynchronize(v bool) { + // return if Pull type is nil + if a == nil { + return + } + + a.Synchronize = &v +} + +// SetEdited sets the Pull Edited field. +// +// When the provided Pull type is nil, it +// will set nothing and immediately return. +func (a *Pull) SetEdited(v bool) { + // return if Pull type is nil + if a == nil { + return + } + + a.Edited = &v +} diff --git a/library/actions/pull_test.go b/library/actions/pull_test.go new file mode 100644 index 00000000..07b60563 --- /dev/null +++ b/library/actions/pull_test.go @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: Apache-2.0 + +package actions + +import ( + "reflect" + "testing" + + "github.com/go-vela/types/constants" +) + +func TestLibrary_Pull_Getters(t *testing.T) { + // setup tests + tests := []struct { + actions *Pull + want *Pull + }{ + { + actions: testPull(), + want: testPull(), + }, + { + actions: new(Pull), + want: new(Pull), + }, + } + + // run tests + for _, test := range tests { + if test.actions.GetOpened() != test.want.GetOpened() { + t.Errorf("GetOpened is %v, want %v", test.actions.GetOpened(), test.want.GetOpened()) + } + + if test.actions.GetSynchronize() != test.want.GetSynchronize() { + t.Errorf("GetSynchronize is %v, want %v", test.actions.GetSynchronize(), test.want.GetSynchronize()) + } + + if test.actions.GetEdited() != test.want.GetEdited() { + t.Errorf("GetEdited is %v, want %v", test.actions.GetEdited(), test.want.GetEdited()) + } + } +} + +func TestLibrary_Pull_Setters(t *testing.T) { + // setup types + var a *Pull + + // setup tests + tests := []struct { + actions *Pull + want *Pull + }{ + { + actions: testPull(), + want: testPull(), + }, + { + actions: a, + want: new(Pull), + }, + } + + // run tests + for _, test := range tests { + test.actions.SetOpened(test.want.GetOpened()) + test.actions.SetSynchronize(test.want.GetSynchronize()) + test.actions.SetEdited(test.want.GetEdited()) + + if test.actions.GetOpened() != test.want.GetOpened() { + t.Errorf("SetOpened is %v, want %v", test.actions.GetOpened(), test.want.GetOpened()) + } + + if test.actions.GetSynchronize() != test.want.GetSynchronize() { + t.Errorf("SetSynchronize is %v, want %v", test.actions.GetSynchronize(), test.want.GetSynchronize()) + } + + if test.actions.GetEdited() != test.want.GetEdited() { + t.Errorf("SetEdited is %v, want %v", test.actions.GetEdited(), test.want.GetEdited()) + } + } +} + +func TestLibrary_Pull_FromMask(t *testing.T) { + // setup types + mask := testMask() + + want := testPull() + + // run test + got := new(Pull).FromMask(mask) + + if !reflect.DeepEqual(got, want) { + t.Errorf("FromMask is %v, want %v", got, want) + } +} + +func TestLibrary_Pull_ToMask(t *testing.T) { + // setup types + actions := testPull() + + want := int64(constants.AllowPullOpen | constants.AllowPullSync) + + // run test + got := actions.ToMask() + + if want != got { + t.Errorf("ToMask is %v, want %v", got, want) + } +} + +func testPull() *Pull { + pr := new(Pull) + pr.SetOpened(true) + pr.SetSynchronize(true) + pr.SetEdited(false) + + return pr +} diff --git a/library/actions/push.go b/library/actions/push.go new file mode 100644 index 00000000..38b41866 --- /dev/null +++ b/library/actions/push.go @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: Apache-2.0 +// +//nolint:dupl // ignore dup code +package actions + +import "github.com/go-vela/types/constants" + +// Push is the library representation of the various actions associated +// with the push event webhook from the SCM. +type Push struct { + Branch *bool `json:"branch"` + Tag *bool `json:"tag"` +} + +// FromMask returns the Push type resulting from the provided integer mask. +func (a *Push) FromMask(mask int64) *Push { + a.SetBranch(mask&constants.AllowPushBranch > 0) + a.SetTag(mask&constants.AllowPushTag > 0) + + return a +} + +// ToMask returns the integer mask of the values for the Push set. +func (a *Push) ToMask() int64 { + mask := int64(0) + + if a.GetBranch() { + mask = mask | constants.AllowPushBranch + } + + if a.GetTag() { + mask = mask | constants.AllowPushTag + } + + return mask +} + +// GetBranch returns the Branch field from the provided Push. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (a *Push) GetBranch() bool { + // return zero value if Push type or Branch field is nil + if a == nil || a.Branch == nil { + return false + } + + return *a.Branch +} + +// GetTag returns the Tag field from the provided Push. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (a *Push) GetTag() bool { + // return zero value if Push type or Tag field is nil + if a == nil || a.Tag == nil { + return false + } + + return *a.Tag +} + +// SetBranch sets the Push Branch field. +// +// When the provided Push type is nil, it +// will set nothing and immediately return. +func (a *Push) SetBranch(v bool) { + // return if Events type is nil + if a == nil { + return + } + + a.Branch = &v +} + +// SetTag sets the Push Tag field. +// +// When the provided Push type is nil, it +// will set nothing and immediately return. +func (a *Push) SetTag(v bool) { + // return if Events type is nil + if a == nil { + return + } + + a.Tag = &v +} diff --git a/library/actions/push_test.go b/library/actions/push_test.go new file mode 100644 index 00000000..71502203 --- /dev/null +++ b/library/actions/push_test.go @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: Apache-2.0 + +package actions + +import ( + "reflect" + "testing" + + "github.com/go-vela/types/constants" +) + +func TestLibrary_Push_Getters(t *testing.T) { + // setup tests + tests := []struct { + actions *Push + want *Push + }{ + { + actions: testPush(), + want: testPush(), + }, + { + actions: new(Push), + want: new(Push), + }, + } + + // run tests + for _, test := range tests { + if test.actions.GetBranch() != test.want.GetBranch() { + t.Errorf("GetBranch is %v, want %v", test.actions.GetBranch(), test.want.GetBranch()) + } + + if test.actions.GetTag() != test.want.GetTag() { + t.Errorf("GetTag is %v, want %v", test.actions.GetTag(), test.want.GetTag()) + } + } +} + +func TestLibrary_Push_Setters(t *testing.T) { + // setup types + var a *Push + + // setup tests + tests := []struct { + actions *Push + want *Push + }{ + { + actions: testPush(), + want: testPush(), + }, + { + actions: a, + want: new(Push), + }, + } + + // run tests + for _, test := range tests { + test.actions.SetBranch(test.want.GetBranch()) + test.actions.SetTag(test.want.GetTag()) + + if test.actions.GetBranch() != test.want.GetBranch() { + t.Errorf("SetBranch is %v, want %v", test.actions.GetBranch(), test.want.GetBranch()) + } + + if test.actions.GetTag() != test.want.GetTag() { + t.Errorf("SetTag is %v, want %v", test.actions.GetTag(), test.want.GetTag()) + } + } +} + +func TestLibrary_Push_FromMask(t *testing.T) { + // setup types + mask := testMask() + + want := testPush() + + // run test + got := new(Push).FromMask(mask) + + if !reflect.DeepEqual(got, want) { + t.Errorf("FromMask is %v, want %v", got, want) + } +} + +func TestLibrary_Push_ToMask(t *testing.T) { + // setup types + actions := testPush() + + want := int64(constants.AllowPushBranch | constants.AllowPushTag) + + // run test + got := actions.ToMask() + + if want != got { + t.Errorf("ToMask is %v, want %v", got, want) + } +} + +func testPush() *Push { + push := new(Push) + push.SetBranch(true) + push.SetTag(true) + + return push +} + +func testMask() int64 { + return int64(constants.AllowPushBranch | constants.AllowPushTag | constants.AllowPullOpen | constants.AllowPullSync | constants.AllowDeployCreate | constants.AllowCommentCreate) +} diff --git a/library/events.go b/library/events.go new file mode 100644 index 00000000..ca84fed3 --- /dev/null +++ b/library/events.go @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: Apache-2.0 + +package library + +import ( + "github.com/go-vela/types/constants" + "github.com/go-vela/types/library/actions" +) + +// Events is the library representation of the various events that generate a +// webhook from the SCM. +type Events struct { + Push *actions.Push `json:"push"` + PullRequest *actions.Pull `json:"pull_request"` + Deployment *actions.Deploy `json:"deployment"` + Comment *actions.Comment `json:"comment"` +} + +// 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 { + pushActions := new(actions.Push).FromMask(mask) + pullActions := new(actions.Pull).FromMask(mask) + deployActions := new(actions.Deploy).FromMask(mask) + commentActions := new(actions.Comment).FromMask(mask) + + e := new(Events) + + e.SetPush(pushActions) + e.SetPullRequest(pullActions) + e.SetDeployment(deployActions) + e.SetComment(commentActions) + + return e +} + +// List is an Events method that generates a comma-separated list of event:action +// combinations that are allowed for the repo. +func (e *Events) List() []string { + eventSlice := []string{} + + if e.GetPush().GetBranch() { + eventSlice = append(eventSlice, constants.EventPush) + } + + if e.GetPullRequest().GetOpened() { + eventSlice = append(eventSlice, constants.EventPull+":"+constants.ActionOpened) + } + + if e.GetPullRequest().GetSynchronize() { + eventSlice = append(eventSlice, constants.EventPull+":"+constants.ActionSynchronize) + } + + if e.GetPullRequest().GetEdited() { + eventSlice = append(eventSlice, constants.EventPull+":"+constants.ActionEdited) + } + + if e.GetPush().GetTag() { + eventSlice = append(eventSlice, constants.EventTag) + } + + if e.GetDeployment().GetCreated() { + eventSlice = append(eventSlice, constants.EventDeploy) + } + + if e.GetComment().GetCreated() { + eventSlice = append(eventSlice, constants.EventComment+":"+constants.ActionCreated) + } + + if e.GetComment().GetEdited() { + eventSlice = append(eventSlice, constants.EventComment+":"+constants.ActionEdited) + } + + return eventSlice +} + +// ToDatabase is an Events method that converts a nested Events struct into an integer event mask. +func (e *Events) ToDatabase() int64 { + return 0 | e.GetPush().ToMask() | e.GetPullRequest().ToMask() | e.GetComment().ToMask() | e.GetDeployment().ToMask() +} + +// GetPush returns the Push field from the provided Events. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (e *Events) GetPush() *actions.Push { + // return zero value if Events type or Push field is nil + if e == nil || e.Push == nil { + return new(actions.Push) + } + + return e.Push +} + +// GetPullRequest returns the PullRequest field from the provided Events. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (e *Events) GetPullRequest() *actions.Pull { + // return zero value if Events type or PullRequest field is nil + if e == nil || e.PullRequest == nil { + return new(actions.Pull) + } + + return e.PullRequest +} + +// GetDeployment returns the Deployment field from the provided Events. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (e *Events) GetDeployment() *actions.Deploy { + // return zero value if Events type or Deployment field is nil + if e == nil || e.Deployment == nil { + return new(actions.Deploy) + } + + return e.Deployment +} + +// GetComment returns the Comment field from the provided Events. If the object is nil, +// or the field within the object is nil, it returns the zero value instead. +func (e *Events) GetComment() *actions.Comment { + // return zero value if Events type or Comment field is nil + if e == nil || e.Comment == nil { + return new(actions.Comment) + } + + return e.Comment +} + +// SetPush sets the Events Push field. +// +// When the provided Events type is nil, it +// will set nothing and immediately return. +func (e *Events) SetPush(v *actions.Push) { + // return if Events type is nil + if e == nil { + return + } + + e.Push = v +} + +// SetPullRequest sets the Events PullRequest field. +// +// When the provided Events type is nil, it +// will set nothing and immediately return. +func (e *Events) SetPullRequest(v *actions.Pull) { + // return if Events type is nil + if e == nil { + return + } + + e.PullRequest = v +} + +// SetDeployment sets the Events Deployment field. +// +// When the provided Events type is nil, it +// will set nothing and immediately return. +func (e *Events) SetDeployment(v *actions.Deploy) { + // return if Events type is nil + if e == nil { + return + } + + e.Deployment = v +} + +// SetComment sets the Events Comment field. +// +// When the provided Events type is nil, it +// will set nothing and immediately return. +func (e *Events) SetComment(v *actions.Comment) { + // return if Events type is nil + if e == nil { + return + } + + e.Comment = v +} diff --git a/library/events_test.go b/library/events_test.go new file mode 100644 index 00000000..cebf3d63 --- /dev/null +++ b/library/events_test.go @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: Apache-2.0 + +package library + +import ( + "reflect" + "testing" + + "github.com/go-vela/types/constants" + "github.com/go-vela/types/library/actions" +) + +func TestLibrary_Events_Getters(t *testing.T) { + // setup tests + tests := []struct { + events *Events + want *Events + }{ + { + events: testEvents(), + want: testEvents(), + }, + { + events: new(Events), + want: new(Events), + }, + } + + // run tests + for _, test := range tests { + if !reflect.DeepEqual(test.events.GetPush(), test.want.GetPush()) { + t.Errorf("GetPush is %v, want %v", test.events.GetPush(), test.want.GetPush()) + } + + if !reflect.DeepEqual(test.events.GetPullRequest(), test.want.GetPullRequest()) { + t.Errorf("GetPullRequest is %v, want %v", test.events.GetPush(), test.want.GetPush()) + } + + if !reflect.DeepEqual(test.events.GetDeployment(), test.want.GetDeployment()) { + t.Errorf("GetDeployment is %v, want %v", test.events.GetPush(), test.want.GetPush()) + } + + if !reflect.DeepEqual(test.events.GetComment(), test.want.GetComment()) { + t.Errorf("GetComment is %v, want %v", test.events.GetPush(), test.want.GetPush()) + } + } +} + +func TestLibrary_Events_Setters(t *testing.T) { + // setup types + var e *Events + + // setup tests + tests := []struct { + events *Events + want *Events + }{ + { + events: testEvents(), + want: testEvents(), + }, + { + events: e, + want: new(Events), + }, + } + + // run tests + for _, test := range tests { + test.events.SetPush(test.want.GetPush()) + test.events.SetPullRequest(test.want.GetPullRequest()) + test.events.SetDeployment(test.want.GetDeployment()) + test.events.SetComment(test.want.GetComment()) + + if !reflect.DeepEqual(test.events.GetPush(), test.want.GetPush()) { + t.Errorf("SetPush is %v, want %v", test.events.GetPush(), test.want.GetPush()) + } + + if !reflect.DeepEqual(test.events.GetPullRequest(), test.want.GetPullRequest()) { + t.Errorf("SetPullRequest is %v, want %v", test.events.GetPullRequest(), test.want.GetPullRequest()) + } + + if !reflect.DeepEqual(test.events.GetDeployment(), test.want.GetDeployment()) { + t.Errorf("SetDeployment is %v, want %v", test.events.GetDeployment(), test.want.GetDeployment()) + } + + if !reflect.DeepEqual(test.events.GetComment(), test.want.GetComment()) { + t.Errorf("SetComment is %v, want %v", test.events.GetComment(), test.want.GetComment()) + } + } +} + +func TestLibrary_Events_List(t *testing.T) { + // setup types + e := testEvents() + + want := []string{"push", "pull_request:opened", "pull_request:synchronize", "tag"} + + // run test + got := e.List() + + if !reflect.DeepEqual(got, want) { + t.Errorf("List is %v, want %v", got, want) + } +} + +func TestLibrary_Events_NewEventsFromMask(t *testing.T) { + // setup mask + mask := int64(constants.AllowPushBranch | constants.AllowPushTag | constants.AllowPullOpen | constants.AllowPullSync) + + want := testEvents() + + // run test + got := NewEventsFromMask(mask) + + if !reflect.DeepEqual(got, want) { + t.Errorf("NewEventsFromMask is %v, want %v", got, want) + } +} + +func testEvents() *Events { + e := new(Events) + + pr := new(actions.Pull) + pr.SetOpened(true) + pr.SetSynchronize(true) + pr.SetEdited(false) + + push := new(actions.Push) + push.SetBranch(true) + push.SetTag(true) + + deploy := new(actions.Deploy) + deploy.SetCreated(false) + + comment := new(actions.Comment) + comment.SetCreated(false) + comment.SetEdited(false) + + e.SetPush(push) + e.SetPullRequest(pr) + e.SetDeployment(deploy) + e.SetComment(comment) + + return e +} diff --git a/library/repo.go b/library/repo.go index 054316a1..b5bd13c1 100644 --- a/library/repo.go +++ b/library/repo.go @@ -5,6 +5,8 @@ package library import ( "fmt" "strings" + + "github.com/go-vela/types/constants" ) // Repo is the library representation of a repo. @@ -33,6 +35,7 @@ type Repo struct { 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"` ApproveBuild *string `json:"approve_build,omitempty"` @@ -48,6 +51,7 @@ func (r *Repo) Environment() map[string]string { "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()[:], ","), "VELA_REPO_BUILD_LIMIT": ToString(r.GetBuildLimit()), @@ -70,6 +74,7 @@ func (r *Repo) Environment() map[string]string { "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()), @@ -369,6 +374,19 @@ func (r *Repo) GetAllowComment() bool { return *r.AllowComment } +// GetAllowEvents returns the AllowEvents 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) GetAllowEvents() *Events { + // return zero value if Repo type or AllowPull field is nil + if r == nil || r.AllowEvents == nil { + return new(Events) + } + + return r.AllowEvents +} + // GetPipelineType returns the PipelineType field. // // When the provided Repo type is nil, or the field within @@ -694,6 +712,19 @@ func (r *Repo) SetAllowComment(v bool) { r.AllowComment = &v } +// SetAllowEvents sets the AllowEvents field. +// +// When the provided Repo type is nil, it +// will set nothing and immediately return. +func (r *Repo) SetAllowEvents(v *Events) { + // return if Repo type is nil + if r == nil { + return + } + + r.AllowEvents = v +} + // SetPipelineType sets the PipelineType field. // // When the provided Repo type is nil, it @@ -733,7 +764,39 @@ func (r *Repo) SetApproveBuild(v string) { r.ApproveBuild = &v } +// EventAllowed determines whether or not an event is allowed based on the repository settings. +func (r *Repo) EventAllowed(event, action string) (allowed bool) { + allowed = false + + if len(action) > 0 { + event = event + ":" + action + } + + switch event { + case constants.EventPush: + allowed = r.GetAllowEvents().GetPush().GetBranch() + case constants.EventPull + ":" + constants.ActionOpened: + allowed = r.GetAllowEvents().GetPullRequest().GetOpened() + case constants.EventPull + ":" + constants.ActionSynchronize: + allowed = r.GetAllowEvents().GetPullRequest().GetSynchronize() + case constants.EventPull + ":" + constants.ActionEdited: + allowed = r.GetAllowEvents().GetPullRequest().GetEdited() + case constants.EventTag: + allowed = r.GetAllowEvents().GetPush().GetTag() + case constants.EventComment + ":" + constants.ActionCreated: + allowed = r.GetAllowEvents().GetComment().GetCreated() + case constants.EventComment + ":" + constants.ActionEdited: + allowed = r.GetAllowEvents().GetComment().GetEdited() + case constants.EventDeploy: + allowed = r.GetAllowEvents().GetDeployment().GetCreated() + } + + return +} + // 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, @@ -742,6 +805,7 @@ func (r *Repo) String() string { AllowPull: %t, AllowPush: %t, AllowTag: %t, + AllowEvents: %s, ApproveBuild: %s, Branch: %s, BuildLimit: %d, @@ -767,6 +831,7 @@ func (r *Repo) String() string { r.GetAllowPull(), r.GetAllowPush(), r.GetAllowTag(), + r.GetAllowEvents().List(), r.GetApproveBuild(), r.GetBranch(), r.GetBuildLimit(), diff --git a/library/repo_test.go b/library/repo_test.go index e1b38afd..1da2db4a 100644 --- a/library/repo_test.go +++ b/library/repo_test.go @@ -19,6 +19,7 @@ func TestLibrary_Repo_Environment(t *testing.T) { "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,tag", "VELA_REPO_BRANCH": "main", "VELA_REPO_TOPICS": "cloud,security", "VELA_REPO_BUILD_LIMIT": "10", @@ -39,6 +40,7 @@ func TestLibrary_Repo_Environment(t *testing.T) { "REPOSITORY_ALLOW_PULL": "false", "REPOSITORY_ALLOW_PUSH": "true", "REPOSITORY_ALLOW_TAG": "false", + "REPOSITORY_ALLOW_EVENTS": "push,pull_request:opened,pull_request:synchronize,tag", "REPOSITORY_BRANCH": "main", "REPOSITORY_CLONE": "https://github.com/github/octocat.git", "REPOSITORY_FULL_NAME": "github/octocat", @@ -161,6 +163,10 @@ func TestLibrary_Repo_Getters(t *testing.T) { 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()) + } + if test.repo.GetPipelineType() != test.want.GetPipelineType() { t.Errorf("GetPipelineType is %v, want %v", test.repo.GetPipelineType(), test.want.GetPipelineType()) } @@ -218,6 +224,7 @@ func TestLibrary_Repo_Setters(t *testing.T) { 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()) test.repo.SetApproveBuild(test.want.GetApproveBuild()) @@ -306,6 +313,10 @@ func TestLibrary_Repo_Setters(t *testing.T) { 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()) + } + if test.repo.GetPipelineType() != test.want.GetPipelineType() { t.Errorf("SetPipelineType is %v, want %v", test.repo.GetPipelineType(), test.want.GetPipelineType()) } @@ -320,6 +331,41 @@ func TestLibrary_Repo_Setters(t *testing.T) { } } +func TestLibrary_Repo_EventAllowed(t *testing.T) { + // setup tests + tests := []struct { + repo *Repo + event string + action string + want bool + }{ + { + repo: testRepo(), + event: "pull_request", + action: "opened", + want: true, + }, + { + repo: testRepo(), + event: "deployment", + want: false, + }, + { + repo: new(Repo), + event: "push", + want: false, + }, + } + + for _, test := range tests { + got := test.repo.EventAllowed(test.event, test.action) + + if got != test.want { + t.Errorf("EventAllowed is %v, want %v", got, test.want) + } + } +} + func TestLibrary_Repo_String(t *testing.T) { // setup types r := testRepo() @@ -331,6 +377,7 @@ func TestLibrary_Repo_String(t *testing.T) { AllowPull: %t, AllowPush: %t, AllowTag: %t, + AllowEvents: %s, ApproveBuild: %s, Branch: %s, BuildLimit: %d, @@ -356,6 +403,7 @@ func TestLibrary_Repo_String(t *testing.T) { r.GetAllowPull(), r.GetAllowPush(), r.GetAllowTag(), + r.GetAllowEvents().List(), r.GetApproveBuild(), r.GetBranch(), r.GetBuildLimit(), @@ -389,6 +437,8 @@ func TestLibrary_Repo_String(t *testing.T) { func testRepo() *Repo { r := new(Repo) + e := testEvents() + r.SetID(1) r.SetOrg("github") r.SetName("octocat") @@ -409,6 +459,7 @@ func testRepo() *Repo { r.SetAllowDeploy(false) r.SetAllowTag(false) r.SetAllowComment(false) + r.SetAllowEvents(e) r.SetPipelineType("") r.SetPreviousName("") r.SetApproveBuild(constants.ApproveNever) From 1eae2f5e371bed7918c5d66e9507798f36ce4953 Mon Sep 17 00:00:00 2001 From: Easton Crupper <65553218+ecrupper@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:33:29 -0500 Subject: [PATCH 2/2] fix(repo_events): add support for reopen (#337) --- constants/allow_events.go | 2 +- library/actions/pull.go | 30 ++++++++++++++++++++++++++++++ library/actions/pull_test.go | 12 +++++++++++- library/actions/push_test.go | 10 +++++++++- library/events_test.go | 9 ++++++++- yaml/ruleset.go | 3 ++- 6 files changed, 61 insertions(+), 5 deletions(-) diff --git a/constants/allow_events.go b/constants/allow_events.go index f6571b43..60d6d88c 100644 --- a/constants/allow_events.go +++ b/constants/allow_events.go @@ -14,7 +14,7 @@ const ( _ // AllowPullLabel - Not Implemented _ // AllowPullLocked - Not Implemented _ // AllowPullReady - Not Implemented - _ // AllowPullReopen - Not Implemented + AllowPullReopen _ // AllowPullReviewRequest - Not Implemented _ // AllowPullClosed - Not Implemented AllowDeployCreate diff --git a/library/actions/pull.go b/library/actions/pull.go index d2d4100a..9a134a6f 100644 --- a/library/actions/pull.go +++ b/library/actions/pull.go @@ -10,6 +10,7 @@ type Pull struct { Opened *bool `json:"opened"` Edited *bool `json:"edited"` Synchronize *bool `json:"synchronize"` + Reopened *bool `json:"reopened"` } // FromMask returns the Pull type resulting from the provided integer mask. @@ -17,6 +18,7 @@ func (a *Pull) FromMask(mask int64) *Pull { a.SetOpened(mask&constants.AllowPullOpen > 0) a.SetSynchronize(mask&constants.AllowPullSync > 0) a.SetEdited(mask&constants.AllowPullEdit > 0) + a.SetReopened(mask&constants.AllowPullReopen > 0) return a } @@ -37,6 +39,10 @@ func (a *Pull) ToMask() int64 { mask = mask | constants.AllowPullEdit } + if a.GetReopened() { + mask = mask | constants.AllowPullReopen + } + return mask } @@ -73,6 +79,17 @@ func (a *Pull) GetEdited() bool { return *a.Edited } +// GetReopened returns the Reopened 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) GetReopened() bool { + // return zero value if Pull type or Reopened field is nil + if a == nil || a.Reopened == nil { + return false + } + + return *a.Reopened +} + // SetOpened sets the Pull Opened field. // // When the provided Pull type is nil, it @@ -111,3 +128,16 @@ func (a *Pull) SetEdited(v bool) { a.Edited = &v } + +// SetReopened sets the Pull Reopened field. +// +// When the provided Pull type is nil, it +// will set nothing and immediately return. +func (a *Pull) SetReopened(v bool) { + // return if Pull type is nil + if a == nil { + return + } + + a.Reopened = &v +} diff --git a/library/actions/pull_test.go b/library/actions/pull_test.go index 07b60563..30b5ed8c 100644 --- a/library/actions/pull_test.go +++ b/library/actions/pull_test.go @@ -38,6 +38,10 @@ func TestLibrary_Pull_Getters(t *testing.T) { if test.actions.GetEdited() != test.want.GetEdited() { t.Errorf("GetEdited is %v, want %v", test.actions.GetEdited(), test.want.GetEdited()) } + + if test.actions.GetReopened() != test.want.GetReopened() { + t.Errorf("GetReopened is %v, want %v", test.actions.GetReopened(), test.want.GetReopened()) + } } } @@ -65,6 +69,7 @@ func TestLibrary_Pull_Setters(t *testing.T) { test.actions.SetOpened(test.want.GetOpened()) test.actions.SetSynchronize(test.want.GetSynchronize()) test.actions.SetEdited(test.want.GetEdited()) + test.actions.SetReopened(test.want.GetReopened()) if test.actions.GetOpened() != test.want.GetOpened() { t.Errorf("SetOpened is %v, want %v", test.actions.GetOpened(), test.want.GetOpened()) @@ -77,6 +82,10 @@ func TestLibrary_Pull_Setters(t *testing.T) { if test.actions.GetEdited() != test.want.GetEdited() { t.Errorf("SetEdited is %v, want %v", test.actions.GetEdited(), test.want.GetEdited()) } + + if test.actions.GetReopened() != test.want.GetReopened() { + t.Errorf("SetReopened is %v, want %v", test.actions.GetReopened(), test.want.GetReopened()) + } } } @@ -98,7 +107,7 @@ func TestLibrary_Pull_ToMask(t *testing.T) { // setup types actions := testPull() - want := int64(constants.AllowPullOpen | constants.AllowPullSync) + want := int64(constants.AllowPullOpen | constants.AllowPullSync | constants.AllowPullReopen) // run test got := actions.ToMask() @@ -113,6 +122,7 @@ func testPull() *Pull { pr.SetOpened(true) pr.SetSynchronize(true) pr.SetEdited(false) + pr.SetReopened(true) return pr } diff --git a/library/actions/push_test.go b/library/actions/push_test.go index 71502203..181d0112 100644 --- a/library/actions/push_test.go +++ b/library/actions/push_test.go @@ -108,5 +108,13 @@ func testPush() *Push { } func testMask() int64 { - return int64(constants.AllowPushBranch | constants.AllowPushTag | constants.AllowPullOpen | constants.AllowPullSync | constants.AllowDeployCreate | constants.AllowCommentCreate) + return int64( + constants.AllowPushBranch | + constants.AllowPushTag | + constants.AllowPullOpen | + constants.AllowPullSync | + constants.AllowPullReopen | + constants.AllowDeployCreate | + constants.AllowCommentCreate, + ) } diff --git a/library/events_test.go b/library/events_test.go index cebf3d63..2023c46b 100644 --- a/library/events_test.go +++ b/library/events_test.go @@ -106,7 +106,13 @@ func TestLibrary_Events_List(t *testing.T) { func TestLibrary_Events_NewEventsFromMask(t *testing.T) { // setup mask - mask := int64(constants.AllowPushBranch | constants.AllowPushTag | constants.AllowPullOpen | constants.AllowPullSync) + mask := int64( + constants.AllowPushBranch | + constants.AllowPushTag | + constants.AllowPullOpen | + constants.AllowPullSync | + constants.AllowPullReopen, + ) want := testEvents() @@ -125,6 +131,7 @@ func testEvents() *Events { pr.SetOpened(true) pr.SetSynchronize(true) pr.SetEdited(false) + pr.SetReopened(true) push := new(actions.Push) push.SetBranch(true) diff --git a/yaml/ruleset.go b/yaml/ruleset.go index b62ebe28..7b8fc615 100644 --- a/yaml/ruleset.go +++ b/yaml/ruleset.go @@ -146,7 +146,8 @@ func (r *Rules) UnmarshalYAML(unmarshal func(interface{}) error) error { for _, e := range rules.Event { switch e { - // backwards compatibility - pull_request = pull_request:opened + pull_request:synchronize + // backwards compatibility + // pull_request = pull_request:opened + pull_request:synchronize + pull_request:reopened // comment = comment:created + comment:edited case constants.EventPull: events = append(events,