diff --git a/docs/docs/ref/proto.mdx b/docs/docs/ref/proto.mdx
index 2fd42324b6..5e843da9eb 100644
--- a/docs/docs/ref/proto.mdx
+++ b/docs/docs/ref/proto.mdx
@@ -2766,6 +2766,7 @@ Definition defines the rule type. It encompases the schema and the data evaluati
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| review_message | string | | |
+| action | string | | |
diff --git a/internal/engine/actions/alert/pull_request_comment/pull_request_comment.go b/internal/engine/actions/alert/pull_request_comment/pull_request_comment.go
index c5748dd95b..04c3c710e5 100644
--- a/internal/engine/actions/alert/pull_request_comment/pull_request_comment.go
+++ b/internal/engine/actions/alert/pull_request_comment/pull_request_comment.go
@@ -141,9 +141,15 @@ func (alert *Alert) run(ctx context.Context, params *paramsPR, cmd interfaces.Ac
switch cmd {
// Create a review
case interfaces.ActionCmdOn:
+
+ event := "COMMENT"
+ if alert.reviewCfg.GetAction() == "request_changes" {
+ event = "REQUEST_CHANGES"
+ }
+
review := &github.PullRequestReviewRequest{
CommitID: github.String(params.CommitSha),
- Event: github.String("COMMENT"),
+ Event: github.String(event),
Body: github.String(params.Comment),
}
diff --git a/internal/engine/actions/alert/pull_request_comment/pull_request_comment_test.go b/internal/engine/actions/alert/pull_request_comment/pull_request_comment_test.go
index 7499d93ad7..8c5d8e0a2e 100644
--- a/internal/engine/actions/alert/pull_request_comment/pull_request_comment_test.go
+++ b/internal/engine/actions/alert/pull_request_comment/pull_request_comment_test.go
@@ -43,6 +43,7 @@ func TestPullRequestCommentAlert(t *testing.T) {
actionType engif.ActionType
cmd engif.ActionCmd
reviewMsg string
+ cfgAction string
inputMetadata *json.RawMessage
mockSetup func(*mockghclient.MockGitHub)
expectedErr error
@@ -52,6 +53,7 @@ func TestPullRequestCommentAlert(t *testing.T) {
name: "create a PR comment",
actionType: TestActionTypeValid,
reviewMsg: "This is a constant review message",
+ cfgAction: "comment",
cmd: engif.ActionCmdOn,
mockSetup: func(mockGitHub *mockghclient.MockGitHub) {
mockGitHub.EXPECT().
@@ -64,6 +66,7 @@ func TestPullRequestCommentAlert(t *testing.T) {
name: "create a PR comment with eval error details template",
actionType: TestActionTypeValid,
reviewMsg: "{{ .EvalErrorDetails }}",
+ cfgAction: "comment",
cmd: engif.ActionCmdOn,
mockSetup: func(mockGitHub *mockghclient.MockGitHub) {
mockGitHub.EXPECT().
@@ -76,6 +79,7 @@ func TestPullRequestCommentAlert(t *testing.T) {
name: "create a PR comment with eval result output template",
actionType: TestActionTypeValid,
reviewMsg: "{{ .EvalResultOutput.ViolationMsg }}",
+ cfgAction: "comment",
cmd: engif.ActionCmdOn,
mockSetup: func(mockGitHub *mockghclient.MockGitHub) {
mockGitHub.EXPECT().
@@ -88,6 +92,7 @@ func TestPullRequestCommentAlert(t *testing.T) {
name: "error from provider creating PR comment",
actionType: TestActionTypeValid,
reviewMsg: "This is a constant review message",
+ cfgAction: "comment",
cmd: engif.ActionCmdOn,
mockSetup: func(mockGitHub *mockghclient.MockGitHub) {
mockGitHub.EXPECT().
@@ -100,6 +105,7 @@ func TestPullRequestCommentAlert(t *testing.T) {
name: "dismiss PR comment",
actionType: TestActionTypeValid,
reviewMsg: "This is a constant review message",
+ cfgAction: "comment",
cmd: engif.ActionCmdOff,
inputMetadata: &successfulRunMetadata,
mockSetup: func(mockGitHub *mockghclient.MockGitHub) {
@@ -109,6 +115,24 @@ func TestPullRequestCommentAlert(t *testing.T) {
},
expectedErr: enginerr.ErrActionTurnedOff,
},
+ {
+ name: "create a PR review with request_changes action",
+ actionType: TestActionTypeValid,
+ reviewMsg: "Security block: please remove binaries",
+ cfgAction: "request_changes",
+ cmd: engif.ActionCmdOn,
+ mockSetup: func(mockGitHub *mockghclient.MockGitHub) {
+ mockGitHub.EXPECT().
+ CreateReview(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
+ DoAndReturn(func(_ context.Context, _, _ string, _ int, review *github.PullRequestReviewRequest) (*github.PullRequestReview, error) {
+ if review.GetEvent() != "REQUEST_CHANGES" {
+ return nil, fmt.Errorf("expected event REQUEST_CHANGES, got %s", review.GetEvent())
+ }
+ return &github.PullRequestReview{ID: &reviewID}, nil
+ })
+ },
+ expectedMetadata: json.RawMessage(fmt.Sprintf(`{"review_id":"%s"}`, reviewIDStr)),
+ },
}
for _, tt := range tests {
@@ -123,6 +147,7 @@ func TestPullRequestCommentAlert(t *testing.T) {
prCommentCfg := pb.RuleType_Definition_Alert_AlertTypePRComment{
ReviewMessage: tt.reviewMsg,
+ Action: tt.cfgAction,
}
mockClient := mockghclient.NewMockGitHub(ctrl)
diff --git a/pkg/api/openapi/minder/v1/minder.swagger.json b/pkg/api/openapi/minder/v1/minder.swagger.json
index c3fbcc8f72..25fbdaaff6 100644
--- a/pkg/api/openapi/minder/v1/minder.swagger.json
+++ b/pkg/api/openapi/minder/v1/minder.swagger.json
@@ -3448,6 +3448,9 @@
"properties": {
"reviewMessage": {
"type": "string"
+ },
+ "action": {
+ "type": "string"
}
},
"required": [
diff --git a/pkg/api/protobuf/go/minder/v1/minder.pb.go b/pkg/api/protobuf/go/minder/v1/minder.pb.go
index 1a21604a64..e6a4a7c2c8 100644
--- a/pkg/api/protobuf/go/minder/v1/minder.pb.go
+++ b/pkg/api/protobuf/go/minder/v1/minder.pb.go
@@ -14253,6 +14253,7 @@ func (x *RuleType_Definition_Alert_AlertTypeSA) GetSeverity() string {
type RuleType_Definition_Alert_AlertTypePRComment struct {
state protoimpl.MessageState `protogen:"open.v1"`
ReviewMessage string `protobuf:"bytes,1,opt,name=review_message,json=reviewMessage,proto3" json:"review_message,omitempty"`
+ Action string `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -14294,6 +14295,13 @@ func (x *RuleType_Definition_Alert_AlertTypePRComment) GetReviewMessage() string
return ""
}
+func (x *RuleType_Definition_Alert_AlertTypePRComment) GetAction() string {
+ if x != nil {
+ return x.Action
+ }
+ return ""
+}
+
// Rule defines the individual call of a certain rule type.
type Profile_Rule struct {
state protoimpl.MessageState `protogen:"open.v1"`
@@ -15333,7 +15341,7 @@ const file_minder_v1_minder_proto_rawDesc = "" +
"\xea\xdc\x14\x06medium\x12\x18\n" +
"\n" +
"VALUE_HIGH\x10\x05\x1a\b\xea\xdc\x14\x04high\x12 \n" +
- "\x0eVALUE_CRITICAL\x10\x06\x1a\f\xea\xdc\x14\bcritical\"\x81$\n" +
+ "\x0eVALUE_CRITICAL\x10\x06\x1a\f\xea\xdc\x14\bcritical\"\xbe$\n" +
"\bRuleType\x12&\n" +
"\aversion\x18\v \x01(\tB\f\xbaH\tr\a2\x05^v\\d$R\aversion\x12$\n" +
"\x04type\x18\f \x01(\tB\x10\xbaH\rr\v2\trule-typeR\x04type\x12\x1d\n" +
@@ -15347,7 +15355,7 @@ const file_minder_v1_minder_proto_rawDesc = "" +
"\vdescription\x18\x05 \x01(\tB\r\xe0A\x02\xbaH\ar\x05\x10\x01\x18\xdc\vR\vdescription\x12)\n" +
"\bguidance\x18\x06 \x01(\tB\r\xe0A\x02\xbaH\ar\x05\x10\x01\x18\xe8\aR\bguidance\x12/\n" +
"\bseverity\x18\a \x01(\v2\x13.minder.v1.SeverityR\bseverity\x12D\n" +
- "\rrelease_phase\x18\t \x01(\x0e2\x1f.minder.v1.RuleTypeReleasePhaseR\freleasePhase\x1a\xff\x1e\n" +
+ "\rrelease_phase\x18\t \x01(\x0e2\x1f.minder.v1.RuleTypeReleasePhaseR\freleasePhase\x1a\xbc\x1f\n" +
"\n" +
"Definition\x12;\n" +
"\tin_entity\x18\x01 \x01(\tB\x1e\xbaH\x1br\x19\x10\x01\x18\xc8\x012\x12^[a-z]+(_[a-z]+)*$R\binEntity\x128\n" +
@@ -15433,15 +15441,16 @@ const file_minder_v1_minder_proto_rawDesc = "" +
"\x1e_actions_replace_tags_with_shaB\a\n" +
"\x05_restB\x17\n" +
"\x15_gh_branch_protectionB\x0f\n" +
- "\r_pull_request\x1a\xfd\x03\n" +
+ "\r_pull_request\x1a\xba\x04\n" +
"\x05Alert\x12E\n" +
"\x04type\x18\x01 \x01(\tB1\xbaH.\xd8\x01\x01r)R\x11security_advisoryR\x14pull_request_commentR\x04type\x12b\n" +
"\x11security_advisory\x18\x02 \x01(\v20.minder.v1.RuleType.Definition.Alert.AlertTypeSAH\x00R\x10securityAdvisory\x88\x01\x01\x12n\n" +
"\x14pull_request_comment\x18\x03 \x01(\v27.minder.v1.RuleType.Definition.Alert.AlertTypePRCommentH\x01R\x12pullRequestComment\x88\x01\x01\x1a_\n" +
"\vAlertTypeSA\x12P\n" +
- "\bseverity\x18\x01 \x01(\tB4\xbaH1\xd8\x01\x01r,R\aunknownR\x04infoR\x03lowR\x06mediumR\x04highR\bcriticalR\bseverity\x1aI\n" +
+ "\bseverity\x18\x01 \x01(\tB4\xbaH1\xd8\x01\x01r,R\aunknownR\x04infoR\x03lowR\x06mediumR\x04highR\bcriticalR\bseverity\x1a\x85\x01\n" +
"\x12AlertTypePRComment\x123\n" +
- "\x0ereview_message\x18\x01 \x01(\tB\f\xe0A\x02\xbaH\x06r\x04\x18\x80\x80\x04R\rreviewMessageB\x14\n" +
+ "\x0ereview_message\x18\x01 \x01(\tB\f\xe0A\x02\xbaH\x06r\x04\x18\x80\x80\x04R\rreviewMessage\x12:\n" +
+ "\x06action\x18\x02 \x01(\tB\"\xbaH\x1f\xd8\x01\x01r\x1aR\acommentR\x0frequest_changesR\x06actionB\x14\n" +
"\x12_security_advisoryB\x17\n" +
"\x15_pull_request_commentB\x0f\n" +
"\r_param_schemaB\x05\n" +
diff --git a/proto/minder/v1/minder.proto b/proto/minder/v1/minder.proto
index 8760ccd017..75c5d840e7 100644
--- a/proto/minder/v1/minder.proto
+++ b/proto/minder/v1/minder.proto
@@ -2933,6 +2933,12 @@ message RuleType {
},
(google.api.field_behavior) = REQUIRED
];
+ string action = 2 [
+ (buf.validate.field).string = {
+ in: ["comment", "request_changes"],
+ },
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
+ ];
}
optional AlertTypePRComment pull_request_comment = 3;
}