Skip to content

feat: record every pull request review, not only approvals - #1270

Merged
AlexKantor87 merged 2 commits into
mainfrom
claude/7422-pr-reviews
Oct 16, 2026
Merged

AlexKantor87 merged 2 commits into
mainfrom
claude/7422-pr-reviews

Conversation

@AlexKantor87

@AlexKantor87 AlexKantor87 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

kosli attest pullrequest now sends a reviews list holding every review, not only approvals. A policy can then see a change request given after an approval.

Merge only after kosli-dev/server#7448 is in prod. Until then the server drops the field.

What each provider sends

Provider Raw value → sent as
GitHub every submitted review, with time and commit. APPROVED, CHANGES_REQUESTED, COMMENTED, DISMISSED as is. PENDING not sent
GitLab approvals from approved_by. requested_changes → CHANGES_REQUESTED, reviewed → COMMENTED. unreviewed, review_started, unapproved not sent
Bitbucket approved, changes_requested. No state but has commented → COMMENTED
Azure vote 10, 5 → APPROVED. -5, -10 → CHANGES_REQUESTED. 0 and groups not sent

Sources: GitHub's GraphQL schema, GitLab's MergeRequestReviewerState, Bitbucket's swagger participant, Azure's IdentityRefWithVote.Vote.

Not a clean fit: GitHub DISMISSED is a fourth state, because GitHub overwrites what the dismissed review decided. GitLab unapproved is dropped. Azure folds 5 into 10 and -5 into -10.

For policy authors

  • GitHub logs every inline reply as a COMMENTED review. Take each reviewer's latest APPROVED, CHANGES_REQUESTED or DISMISSED one.
  • reviews: [] means reviews were read and there were none. A missing reviews means they weren't read (old CLI, or a GitLab without the reviewers endpoint).
  • Bitbucket times a change request by the reviewer's last comment, not by the request itself. Don't use it to order a change request against an approval. Approval times are exact.
  • Azure approvers is unchanged (vote 10 only, groups in), so it can disagree with reviews.

GitHub approvers now come from the reviews, one per reviewer per commit, so a repeat approval of the same commit is listed once.

Tested

  • Each test proven red first; every mapping guard mutated.
  • Full suite against a local server built from server#7448: 3,625 green.
  • Real GitHub, server PR 7200: approve, changes requested, approve, stored and read back.
  • GitLab, Bitbucket and Azure against fixtures only. Bitbucket and Azure wiring isn't under test.

Part of kosli-dev/server#7422

🤖 Generated with Claude Code

Policies could not see a change request given after an approval, because
the CLI only sent approvals. Pull request attestations now carry a
reviews list for every provider, with states mapped to APPROVED,
CHANGES_REQUESTED, COMMENTED and, on GitHub, DISMISSED.

- GitHub: every submitted review, with time and reviewed commit.
- GitLab: approvals from approved_by, plus each reviewer's state.
- Bitbucket: each participant's state and participated_on.
- Azure: each reviewer's vote, leaving out groups.

GitHub approvers now come from the same reviews, one per reviewer per
commit, so approving the same commit twice no longer lists the reviewer
twice. Approvals of different commits are both kept.

Needs kosli-dev/server#7448 deployed first; the server drops unknown
fields. Part of kosli-dev/server#7422.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added go Pull requests that update go code feat labels Oct 15, 2026
@claude

claude Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @AlexKantor87's task in 1m 43s —— View job


PR review

  • Static checks: go build ./... ✅, go vet ./internal/... ✅, go mod tidy leaves no diff ✅
  • Review diff
  • Post findings

I found no blocking issues. Both fixes from the earlier review are in 3d94964 and look right:

  • MarshalJSON now leaves out a nil reviews and sends an empty one as [].
  • GitLab now matches approvers to reviewers on Username.

Findings (all minor)

  1. Bitbucket timestamps (inline comment): participated_on is the time of the participant's last activity, not of their decision. Policies shouldn't use it to order reviews.
  2. ApprovalsFrom "latest kept" (internal/types/types.go): this keeps whichever review comes last in the input, not the newest by Timestamp. That is correct for GitHub, because GraphQL returns reviews oldest first and pages are drained in order. The comment could say it expects the input oldest first, or the function could compare Timestamp, so a future caller doesn't get this wrong.
  3. Azure nil pointers (azureReviewerName): it reads *DisplayName and *UniqueName without a nil check. Before, that only ran for vote 10; it now runs for every reviewer with a non-zero vote. azureReviews checks Vote for nil, but azureApprovers still doesn't. This risk was already there; a small guard would make the two functions match.
  4. GitHub approvers changes: a repeat approval of the same commit is now listed once. The PR body says so. It's worth a line in the release notes for anyone counting approvers entries.

What's good

  • Each provider's mapping is a pure function (gitlabReviews, azureReviews, bitbucketReviews, ApprovalsFrom) tested with fixtures. That's easy to review and to check by mutation.
  • Keeping "not collected" (nil, GitLab 404) apart from "none" ([]) is a careful choice, and the tests cover it.
  • Keeping a Bitbucket change request that has no username, rather than dropping it, avoids reporting it as missing.
  • The PR body's notes on each provider's mapping and for policy authors are clear and useful.

Comment thread internal/types/types.go
Comment thread internal/gitlab/gitlab.go Outdated
Comment thread internal/github/pagination.go
omitempty dropped an empty reviews list as well as a nil one, so a PR
with no reviews looked the same as one whose reviews were never read.
An empty list is now sent as [], and only a nil one is left out.

GitLab now matches approvers to reviewers on username rather than on
the display name, which the two endpoints could format differently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AlexKantor87
AlexKantor87 marked this pull request as draft October 15, 2026 14:42
@AlexKantor87
AlexKantor87 marked this pull request as ready for review October 16, 2026 06:47
Comment thread internal/bitbucket/bitbucket.go
@AlexKantor87
AlexKantor87 enabled auto-merge (squash) October 16, 2026 07:05
@jbpros
jbpros disabled auto-merge October 16, 2026 07:21
@AlexKantor87
AlexKantor87 merged commit c35be88 into main Oct 16, 2026
27 checks passed
@AlexKantor87
AlexKantor87 deleted the claude/7422-pr-reviews branch October 16, 2026 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants