feat: capture commit signature and PR base_ref in pull_request attestations#959
Conversation
Adds the GitHub producer side for the V2 pull_request attestation fields added on the server (kosli-dev/server#5892): - types.Commit gains Verified (*bool) and SignatureState (*string), mapped from the GraphQL commit signature { isValid, state }. An unsigned commit (nil signature node) leaves both nil, keeping "unsigned" distinct from a present-but-invalid signature (verified=false). - types.PREvidence gains BaseRef, mapped from the PR baseRefName, in both GraphQL paths (PREvidenceByPRNumber and PREvidenceForCommitV2). All new fields are optional/omitempty, so other providers and existing consumers are unaffected. GitLab, Bitbucket and Azure are follow-up slices (Bitbucket and Azure cannot supply per-commit signatures). Requires the server schema change to deploy first, since base_ref lands on FoundPullRequestV2 (extra="forbid"). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
base_ref is mapped from the MR TargetBranch. Per-commit signatures are fetched via GetGPGSignature; GitLab returns 404 for unsigned commits, which is treated as unsigned (verified left nil) rather than failing the attestation, while other errors propagate. The pure gitlabCommitVerification mapper (verified only when status=="verified") is unit-tested. Part of kosli-dev/server#5892. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
base_ref is mapped from destination.branch.name. Bitbucket Cloud does not expose per-commit signature verification, so verified/signature_state are omitted. Part of kosli-dev/server#5892. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
base_ref is mapped from TargetRefName, kept raw (refs/heads/...) to match the existing head_ref. Azure DevOps does not expose per-commit signature verification, so verified/signature_state are omitted. Part of kosli-dev/server#5892. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract small pure seams from the provider PR-evidence builders so the new server#5892 mappings are unit-testable, and add the tests. No behaviour change. - GitLab: resolveGitlabSignature isolates the GetGPGSignature result handling — 404 -> unsigned (nil), other errors propagate, otherwise map verification_status. Covered for all four outcomes. gitlabMRRefs maps the head/base branch names. - Bitbucket: bitbucketBranchName extracts the source/destination branch name (used for both head_ref and base_ref); covered. - Azure: azurePRRefs maps the raw head/base ref names; covered. Part of kosli-dev/server#5892. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @AlexKantor87's task in 3m 24s —— View job Claude PR Review
Reviewed the producer-side changes that populate Static analysis ✅
(The full integration suite needs the local Kosli server + provider tokens, so it runs in CI — the new logic is exercised by pure-mapper unit tests, which is exactly the right testability split.) Strengths 👍
Notes (non-blocking)
Draft statusCorrectly marked draft: this sends Nice work — the design decisions are sound and the test coverage on the pure mappers is exactly where it should be. |
Producer side of kosli-dev/server#5892 — populates the new V2
pull_requestattestation fields across all four SCM providers. Server counterpart: kosli-dev/server#5898 (merged).What
Adds three optional fields to
pull_requestattestation evidence:verified(*bool) +signature_state(*string)base_refverifiedis tri-state:nil= unsigned/unknown,false= present-but-invalid,true= verified — so unsigned commits stay distinct from invalid signatures.Provider coverage
verified/signature_statebase_refrefs/heads/…)signature { isValid state }on the commit node +baseRefName, in both GraphQL paths.TargetBranch→base_ref; per-commitGetGPGSignature, where a 404 means unsigned (handled, not fatal); other errors propagate.destination.branch.name→base_ref; per-commit signatures not exposed by the API.TargetRefName→base_ref, kept raw (refs/heads/…) to matchhead_ref; per-commit signatures not exposed by the SDK.All new fields are optional/
omitempty, so other providers and existing consumers are unaffected.Tests
Pure mappers unit-tested: GitHub
buildPREvidence(signed / invalid / unsigned / base_ref), GitLabresolveGitlabSignature(404 / error / verified / unverified) +gitlabMRRefs, BitbucketbitbucketBranchName, AzureazurePRRefs.go build ./...,go vet, andgolangci-lintall clean. The full integration suite runs in CI.🤖 Generated with Claude Code