feat(vcs): add CommitID to ReviewRequest (#115) #118

Merged
aweiker merged 5 commits from review-bot-issue-115 into feature/github-support 2026-05-14 01:49:33 +00:00
4 changed files with 75 additions and 2 deletions
Showing only changes of commit d606d0a202 - Show all commits
+1 -1
View File
@@ -485,7 +485,7 @@ func main() {
reviewReq := vcs.ReviewRequest{
Body: reviewBody,
Event: event,
CommitID: pr.Head.SHA,
CommitID: evaluatedSHA,
Review

[NIT] Inline comments are built with CommitID set from pr.Head.SHA earlier, while the review-level CommitID now uses evaluatedSHA. For consistency, consider using evaluatedSHA for inline comment CommitID as well. Functionally this is fine due to the stale-head check, but aligning both to evaluatedSHA reduces any chance of mismatch if refetch fails.

**[NIT]** Inline comments are built with CommitID set from pr.Head.SHA earlier, while the review-level CommitID now uses evaluatedSHA. For consistency, consider using evaluatedSHA for inline comment CommitID as well. Functionally this is fine due to the stale-head check, but aligning both to evaluatedSHA reduces any chance of mismatch if refetch fails.
Comments: inlineComments,
}
posted, err := client.PostReview(ctx, owner, repoName, prNumber, reviewReq)
+34
View File
@@ -214,6 +214,40 @@ func TestAdapter_PostReview_EventTranslation(t *testing.T) {
}
Review

[NIT] TestAdapter_PostReview_CommitID and TestAdapter_PostReview_CommitID_Threading (added later in the file) both test largely the same behaviour — that req.CommitID is forwarded to the underlying client and echoed back in the returned review. Having two tests for the same assertion is minor duplication; one could be removed or merged.

**[NIT]** TestAdapter_PostReview_CommitID and TestAdapter_PostReview_CommitID_Threading (added later in the file) both test largely the same behaviour — that req.CommitID is forwarded to the underlying client and echoed back in the returned review. Having two tests for the same assertion is minor duplication; one could be removed or merged.
}
func TestAdapter_PostReview_CommitID(t *testing.T) {
var gotCommitID string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var payload struct {
CommitID string `json:"commit_id"`
}
json.NewDecoder(r.Body).Decode(&payload)
gotCommitID = payload.CommitID
json.NewEncoder(w).Encode(map[string]any{
"id": 1,
"body": "test",
"user": map[string]any{"login": "bot"},
"commit_id": payload.CommitID,
})
}))
defer server.Close()
client := gitea.NewClient(server.URL, "token")
adapter := gitea.NewAdapter(client)
_, err := adapter.PostReview(context.Background(), "owner", "repo", 1, vcs.ReviewRequest{
Body: "test",
Event: vcs.ReviewEventApprove,
CommitID: "sha256abc",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if gotCommitID != "sha256abc" {
t.Errorf("expected commit_id %q forwarded to client, got %q", "sha256abc", gotCommitID)
}
}
func TestAdapter_PostReview_WithComments_PositionTranslation(t *testing.T) {
diff := `diff --git a/main.go b/main.go
Outdated
Review

[NIT] Missing blank line between TestAdapter_PostReview_CommitID and TestAdapter_PostReview_WithComments_PositionTranslation. Minor style inconsistency — all other test functions in the file have a blank line separator.

**[NIT]** Missing blank line between `TestAdapter_PostReview_CommitID` and `TestAdapter_PostReview_WithComments_PositionTranslation`. Minor style inconsistency — all other test functions in the file have a blank line separator.
--- a/main.go
Outdated
Review

[NIT] Double blank line between TestAdapter_PostReview_EventTranslation and TestAdapter_PostReview_CommitID. Go convention (enforced by gofmt) uses a single blank line between top-level declarations. This also appears at the end of the TestPostReview_EmptyCommitID_OmittedFromPayload function in gitea/client_test.go (double blank before TestGetPullRequest_Non200).

**[NIT]** Double blank line between `TestAdapter_PostReview_EventTranslation` and `TestAdapter_PostReview_CommitID`. Go convention (enforced by gofmt) uses a single blank line between top-level declarations. This also appears at the end of the `TestPostReview_EmptyCommitID_OmittedFromPayload` function in `gitea/client_test.go` (double blank before `TestGetPullRequest_Non200`).
+40
View File
@@ -147,6 +147,46 @@ func TestPostReview(t *testing.T) {
}
Review

[NIT] TestPostReview_CommitID uses io.ReadAll(r.Body) then json.Unmarshal, while the existing TestPostReview uses json.NewDecoder(r.Body).Decode. Inconsistent style within the same file, though not a correctness issue. Consider using the decoder pattern to match the surrounding tests.

**[NIT]** TestPostReview_CommitID uses `io.ReadAll(r.Body)` then `json.Unmarshal`, while the existing TestPostReview uses `json.NewDecoder(r.Body).Decode`. Inconsistent style within the same file, though not a correctness issue. Consider using the decoder pattern to match the surrounding tests.
}
func TestPostReview_CommitID(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Fatalf("expected POST, got %s", r.Method)
}
body, _ := io.ReadAll(r.Body)
var payload struct {
Body string `json:"body"`
Event string `json:"event"`
CommitID string `json:"commit_id"`
}
if err := json.Unmarshal(body, &payload); err != nil {
t.Fatalf("unmarshal payload: %v", err)
}
if payload.CommitID != "deadbeef123" {
t.Errorf("expected commit_id %q, got %q", "deadbeef123", payload.CommitID)
}
if payload.Event != "APPROVED" {
t.Errorf("expected event APPROVED, got %q", payload.Event)
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"id":101,"user":{"login":"review-bot"},"state":"APPROVED","stale":false,"commit_id":"deadbeef123"}`))
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
review, err := client.PostReview(context.Background(), "owner", "repo", 3, "APPROVED", "LGTM", "deadbeef123", nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if review.ID != 101 {
t.Errorf("expected review ID 101, got %d", review.ID)
}
if review.CommitID != "deadbeef123" {
t.Errorf("expected commit_id %q, got %q", "deadbeef123", review.CommitID)
}
}
func TestGetPullRequest_Non200(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
-1
View File
3
@@ -98,6 +98,5 @@ type ReviewRequest struct {
// If empty, the platform defaults to the current PR head.
// Adapters use this as the primary commit anchor for the review submission.
Outdated
Review

[NIT] Minor inconsistent alignment: CommitID string has extra whitespace padding (string ) before the json tag compared to the other fields. This is a gofmt style deviation that should be cleaned up.

**[NIT]** Minor inconsistent alignment: `CommitID string` has extra whitespace padding (`string `) before the json tag compared to the other fields. This is a gofmt style deviation that should be cleaned up.
CommitID string `json:"commit_id,omitempty"`
Comments []ReviewComment `json:"comments,omitempty"`
Outdated
Review

[NIT] Removing the blank line between CommitID and Comments fields reduces readability in what is an exported, public-API struct. The blank line was providing visual grouping between the scalar fields (Body, Event, CommitID) and the slice field (Comments). This is purely cosmetic but the change is a minor readability regression with no functional benefit.

**[NIT]** Removing the blank line between CommitID and Comments fields reduces readability in what is an exported, public-API struct. The blank line was providing visual grouping between the scalar fields (Body, Event, CommitID) and the slice field (Comments). This is purely cosmetic but the change is a minor readability regression with no functional benefit.
}
1