Decouple PR feedback actions from GitHub-specific provider#6262
Decouple PR feedback actions from GitHub-specific provider#6262krrish175-byte wants to merge 11 commits intomindersec:mainfrom
Conversation
b8f287f to
1f1c470
Compare
Add generic CommitStatusPublisher and ReviewPublisher interfaces to pkg/providers/v1 so that commit_status alert and pull_request_comment alert/remediate actions are no longer hardcoded to provinfv1.GitHub. Previously both actions fell back silently to NoopAlert/NoopRemediate with a misleading log message when used with any non-GitHub provider. This change replaces the GitHub-specific type assertions with generic interface casts, improving extensibility for future VCS providers. Changes: - Define CommitStatus and Review DTOs in pkg/providers/v1 - Define CommitStatusPublisher and ReviewPublisher interfaces - Implement PublishCommitStatus, PublishReview, DismissPublishedReview on the GitHub client as adapter methods - Add compile-time interface assertions on the GitHub client struct - Refactor commit_status action to cast to CommitStatusPublisher - Refactor pull_request_comment action to cast to ReviewPublisher - Update alert.go and remediate.go to use the new generic interfaces - Regenerate mocks and update unit tests to MockCommitStatusPublisher and MockReviewPublisher
1f1c470 to
134f096
Compare
evankanderson
left a comment
There was a problem hiding this comment.
The commit_status isn't used yet, correct? I thought in #6261 we were trying to decide between "commit status" and "check runs" APIs.
evankanderson
left a comment
There was a problem hiding this comment.
Thanks for starting this! Can we have this PR just focus on pull_request_comment? I've made a few suggestions that may be scope creep (templating in body and event); feel free to separate them out into their own PR.
| string type = 1 [ | ||
| (buf.validate.field).string = { | ||
| in: ["rest", "gh_branch_protection", "pull_request"], | ||
| in: ["rest", "gh_branch_protection", "pull_request", "pull_request_comment"], |
| review, | ||
| ) | ||
| if err != nil { | ||
| if err := alert.gh.PublishReview(ctx, params.Owner, params.Repo, params.Number, |
There was a problem hiding this comment.
It would be great to have this action work like the Trusty / OSV reviews:
- If the rule hasn't commented on the PR before, publish a comment.
- If the rule has commented on the PR before, update the existing comment.
- If the rule is passing, delete the previous comment on the PR for that rule
(Yes, this is a bit more complex than the current logic -- feel free to defer that to another issue, but I think the ReviewPublisher interface should support that.)
We should also allow the remediation to use at least the REQUEST_CHANGES or COMMENT events (defaulting to COMMENT). There should be some way to wire in output from the rule to both body and event. In the future, we should figure out how to populate the comments array from outputs as well, but I think we can hold that for another PR.
Narrow the scope of PR feedback to pull request comments by removing commit statuses. Refactor provider interfaces to use standard GitHub methods and implement create-or-update/dismiss logic for Minder reviews. Co-Authored-By: Antigravity <noreply@google.com>
|
Thanks for the detailed feedback. I have updated the PR to address your suggestions: Narrowed Scope: I have removed the commit_status alert type from the engine and protobuf definitions. The focus is now exclusively on enhancing pull_request_comment as the primary standard feedback mechanism. Refactored Provider Interfaces: Hoisted standard GitHub API methods (ListReviews, CreateReview, UpdateReview, DismissReview, and GetPullRequest) directly into the ReviewPublisher interface in pkg/providers/v1/providers.go. Refactored CommitStatusPublisher to reuse the existing SetCommitStatus method from the GitHub trait. Removed redundant DTO-based wrapper methods (PublishReview, DismissPublishedReview) to align with your suggestion of reusing the standard GitHub API patterns. Advanced PR Review Lifecycle: Implemented a "create-or-update" mechanism in pull_request_comment.go. Minder now uses a magic comment () to uniquely identify reviews it has created for a specific rule. If a review for a rule already exists, Minder will now update it rather than posting a new comment. AlertTypePRComment, supporting both COMMENT (default) and REQUEST_CHANGES. Verification: Updated unit tests in pull_request_comment_test.go to cover the new lifecycle and event configurations. Looking forward to your thoughts! |
Ran 'make bootstrap' to install buf, sqlc, mockgen, then 'make gen' to regenerate all files from source. This ensures generated artifacts match exactly what CI produces, resolving uncommitted changes checks.
evankanderson
left a comment
There was a problem hiding this comment.
Will review more tomorrow, this is about +1500 LOC, and that's not all auto-generated.
There was a problem hiding this comment.
This is an accidental include, right? I generally try to put this type of output to /tmp or ~/tmp to avoid accidentally including it with e.g. git add .
There was a problem hiding this comment.
Ahh, my bad. Yep, I accidentally added this txt file. Thanks for the solution
evankanderson
left a comment
There was a problem hiding this comment.
Sorry for the delay. This looks promising; there's one test error due to an empty _test.go file, and then a few API comments, but this looks like a nice addition!
| github.com/alexdrl/zerowater v0.0.3 | ||
| github.com/aws/aws-sdk-go-v2 v1.41.2 | ||
| github.com/aws/aws-sdk-go-v2/config v1.32.7 | ||
| github.com/aws/aws-sdk-go-v2/config v1.32.5 |
There was a problem hiding this comment.
It looks like you tried to do a rebase here and ended up losing changes to go mod. I'd suggest simply reverting these files via git checkout upstream/main go.* and then running go mod tidy.
| }, | ||
| (google.api.field_behavior) = REQUIRED | ||
| ]; | ||
| // review_event is the event to use for the PR review (COMMENT or REQUEST_CHANGES). |
There was a problem hiding this comment.
I feel like "review event" is a bit of a weird name. What about block_commit or something along those lines?
Also, our other string-as-enum values are lowercase. Rather than directly mirroring the GitHub API (which might be different for e.g. GitLab in the future), let's name things based on the intent.
pull_request_comment:
review_message: "..."
block_commit: "advise-only" # or "require-changes"I'm not attached to the exact wording, but it should be clear looking at the YAML what the result of the alert / remediation will be.
| case pull_request_comment.AlertType: | ||
| client, err := provinfv1.As[provinfv1.ReviewPublisher](provider) | ||
| if err != nil { | ||
| return nil, errors.New("provider does not support publishing pull request reviews") |
There was a problem hiding this comment.
Given the regularity of the other error messages, let's call this the "pull_request_comment trait":
| return nil, errors.New("provider does not support publishing pull request reviews") | |
| return nil, errors.New("provider does not implement pull_request_comment trait") |
(Alternatively, we could call it the pr-review trait; I'd simply say "review", but that feels a bit too broad as a name to be clear.)
There was a problem hiding this comment.
This empty file is producing an error (which screws up the test reporting):
# github.com/mindersec/minder/internal/engine/actions/alert/commit_status
internal/engine/actions/alert/commit_status/commit_status_test.go:1:1: expected 'package', found 'EOF'
FAIL github.com/mindersec/minder/internal/engine/actions/alert/commit_status [setup failed]
| } else { | ||
| req := &github.PullRequestReviewRequest{ | ||
| Body: github.String(params.Comment), | ||
| Event: github.String(params.Event), |
There was a problem hiding this comment.
IMO, we should translate from our API to the GitHub constants here, rather than leaking GitHub's constants into the API.
There was a problem hiding this comment.
(It's interesting that you can't change the event from REQUEST_CHANGES to COMMENT after posting.)
| newMeta, err := json.Marshal(alertMetadata{ | ||
| ReviewID: strconv.FormatInt(r.GetID(), 10), | ||
| SubmittedAt: r.SubmittedAt.GetTime(), | ||
| PullRequestUrl: r.PullRequestURL, |
There was a problem hiding this comment.
Why did we remove PullRequestUrl?
| - Repository Permissions: | ||
|
|
||
| - Administration (read and write) | ||
| - Commit statuses (read and write) |
There was a problem hiding this comment.
We don't need this until we add commit status or check runs, right?
|
(This looks like it needs to be merged up to date and a few comments addressed.) |
Summary
This PR introduces provider-agnostic CommitStatusPublisher and ReviewPublisher interfaces in
pkg/providers/v1, decoupling thecommit_statusalert action andpull_request_commentalert/remediate action from the hardcodedprovinfv1.GitHubinterface.Previously, both actions had a silent fallback to
NoopAlert/NoopRemediatewith the misleading log message"provider is not a GitHub provider"when used with any non-GitHub provider. This change replaces the GitHub-specific type assertions with generic interface casts, improving extensibility for future VCS providers (e.g. GitLab).Key changes:
CommitStatusandReviewprovider-agnostic DTOs topkg/providers/v1CommitStatusPublisherandReviewPublisherinterfacesPublishCommitStatus,PublishReview, andDismissPublishedReviewadapter methods on the GitHub clientcommit_statusandpull_request_commentactions to cast to the new generic interfacesalert.goandremediate.goto use the new interfaces with accurate error messagesMockCommitStatusPublisher/MockReviewPublisherTesting
go build ./...— builds cleanly with no errorsgo test ./internal/engine/actions/...— all 8 packages pass:alert/commit_statusalert/pull_request_commentalert/security_advisoryremediateand all sub-packagesvar _ provifv1.CommitStatusPublisher = (*GitHub)(nil)) fail at compile time if the methods are missing — they pass, confirming correct implementationvulncheck,homoglyphs,trusty) that useGitHub.CreateReview/GitHub.SetCommitStatusdirectly are fully unaffected