diff --git a/cmd/kosli/assertPRGithub_test.go b/cmd/kosli/assertPRGithub_test.go index 2bd2a412c..dd1b263bc 100644 --- a/cmd/kosli/assertPRGithub_test.go +++ b/cmd/kosli/assertPRGithub_test.go @@ -23,7 +23,22 @@ func (suite *AssertPRGithubCommandTestSuite) SetupTest() { ghUtils.NewGithubRetrieverFunc = func(token, baseURL, org, repository string, debug bool) types.PRRetriever { return &ghUtils.FakeGitHubClient{ PRsByCommit: map[string][]*types.PREvidence{ - suite.commitWithPR: {{URL: "https://github.com/kosli-dev/cli/pull/1", State: "MERGED"}}, + suite.commitWithPR: {{ + URL: "https://github.com/kosli-dev/cli/pull/1", + State: "MERGED", + Author: "test-user", + Title: "test PR", + CreatedAt: 1234567890, + HeadRef: "test-branch", + MergeCommit: suite.commitWithPR, + Commits: []types.Commit{{ + SHA: suite.commitWithPR, + Message: "test commit", + Author: "Test User ", + Timestamp: 1234567890, + Branch: "test-branch", + }}, + }}, }, } } diff --git a/cmd/kosli/attestPRGithub_test.go b/cmd/kosli/attestPRGithub_test.go index c888a35f1..b345ccd42 100644 --- a/cmd/kosli/attestPRGithub_test.go +++ b/cmd/kosli/attestPRGithub_test.go @@ -36,7 +36,22 @@ func (suite *AttestGithubPRCommandTestSuite) SetupTest() { ghUtils.NewGithubRetrieverFunc = func(token, baseURL, org, repository string, debug bool) types.PRRetriever { return &ghUtils.FakeGitHubClient{ PRsByCommit: map[string][]*types.PREvidence{ - suite.commitWithPR: {{URL: "https://github.com/kosli-dev/cli/pull/1", State: "MERGED"}}, + suite.commitWithPR: {{ + URL: "https://github.com/kosli-dev/cli/pull/1", + State: "MERGED", + Author: "test-user", + Title: "test PR", + CreatedAt: 1234567890, + HeadRef: "test-branch", + MergeCommit: suite.commitWithPR, + Commits: []types.Commit{{ + SHA: suite.commitWithPR, + Message: "test commit", + Author: "Test User ", + Timestamp: 1234567890, + Branch: "test-branch", + }}, + }}, }, } } diff --git a/internal/github/build_pr_evidence_test.go b/internal/github/build_pr_evidence_test.go index dcb295a69..c18935bae 100644 --- a/internal/github/build_pr_evidence_test.go +++ b/internal/github/build_pr_evidence_test.go @@ -1,6 +1,7 @@ package github import ( + "encoding/json" "testing" "time" @@ -152,6 +153,33 @@ func TestBuildPREvidence_RecordsCommitSignature(t *testing.T) { require.Equal(t, "VALID", *c.SignatureState) } +// TestBuildPREvidence_EmptyAuthorIsPreserved verifies that when the PR +// creator's GitHub account has been deleted (Author.Login = ""), the empty +// string is preserved and serialised as "" rather than omitted, allowing the +// server to accept it directly. +func TestBuildPREvidence_EmptyAuthorIsPreserved(t *testing.T) { + evidence, err := buildPREvidence( + "https://github.com/kosli-dev/cli/pull/671", + "0e723254516c841126e81f76100be57258ff1386", + "MERGED", + "", // empty author — PR creator account deleted + "2026-03-01T09:00:00Z", + "2026-03-01T12:00:00Z", + "Fix something", + "fix-branch", + "main", + nil, nil, + ) + require.NoError(t, err) + require.Equal(t, "", evidence.Author, + "empty PR author login must be preserved so it is serialised as an empty string, not omitted") + + b, err := json.Marshal(evidence) + require.NoError(t, err) + require.Contains(t, string(b), `"author":""`, + "empty author must be serialised, not omitted") +} + // TestBuildPREvidence_UnsignedCommitHasNoSignatureFields verifies an unsigned // commit (no signature node) leaves verified/signature_state nil, so "unsigned" // stays distinct from "present-but-invalid" (verified=false). diff --git a/internal/types/types.go b/internal/types/types.go index 8e427a3ea..05a6b82ea 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -5,7 +5,7 @@ type PREvidence struct { URL string `json:"url"` State string `json:"state"` Approvers []any `json:"approvers"` - Author string `json:"author,omitempty"` + Author string `json:"author"` CreatedAt int64 `json:"created_at,omitempty"` MergedAt int64 `json:"merged_at,omitempty"` Title string `json:"title,omitempty"`