Skip to content

fix: source PR commit author identity and timestamps from the git author across providers (server#5479)#958

Merged
AlexKantor87 merged 7 commits into
5479-pr-attestation-authorfrom
5479-author-todos
Jun 12, 2026
Merged

fix: source PR commit author identity and timestamps from the git author across providers (server#5479)#958
AlexKantor87 merged 7 commits into
5479-pr-attestation-authorfrom
5479-author-todos

Conversation

@AlexKantor87

Copy link
Copy Markdown
Contributor

What and why

Completes the author/committer fix for kosli-dev/server#5479, clearing the three TODO(server#5479) markers left by #957. PR-attestation commits now record the git author's identity and authored timestamp across all providers, not the committer's.

Stacked on #957 (base branch 5479-pr-attestation-author); GitHub will retarget this to main when #957 merges. Plan: https://github.com/kosli-dev/server/issues/5479#issuecomment-4690357750

Per-provider before → after

Provider author author_username timestamp
GitLab committer → author (AuthorName/AuthorEmail) — (none; unchanged) created_at → authored_date (fallback created_at)
Azure display-name only → Name <email> committer name → dropped committer date → author date
GitHub (author, from #957) (author login, from #957) committed → authored (fallback committed)
Bitbucket already author (author.raw) — unchanged — (none) single date field — unchanged

Azure commits expose only git name/email/date (no login), so author_username is dropped rather than populated from the wrong source; omitempty removes it from the wire. Its Author is aligned to the Name <email> format the other providers use.

How it's built

Each provider's commit mapping was extracted into a pure commitFrom<Provider>Commit function (GitHub already had buildPREvidence) so the logic is unit-testable without live API calls. Seven commits, refactor-then-fix per slice, each fix preceded by a failing test:

  • GitLab identity + timestamp
  • Azure identity + timestamp
  • GitHub timestamp (adds authoredDate to the shared GraphQL commit node)

Bitbucket was verified read-only: it already reads the API author field and exposes only a single commit date.

Compatibility note

Wire schema unchanged; values change. Policies (Rego or jq) reading commit author or timestamp may legitimately flip outcomes — never-alone checks comparing commit author to approvers, and any commit-time-window logic. Azure payloads lose author_username (it previously held the committer's display name, which was wrong, and Azure has no commit login to replace it). This needs a changelog + docs note before release, alongside #957's.

Verification

go build ./..., go vet, make lint (0 issues), and unit tests for all changed packages (github, gitlab, azure, bitbucket, types) pass locally. The full make test_integration was not run locally (no KOSLI_API_TOKEN_PROD in this environment); CI runs the authoritative full suite including the token-gated real-provider contract tests.

🤖 Generated with Claude Code

AlexKantor87 and others added 7 commits June 12, 2026 14:58
Pure extraction of the GitLab commit mapping so it can be unit-tested
directly. Behaviour unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…479)

GetMergeRequestCommits mapped CommitterName/CommitterEmail into the author
field. Map AuthorName/AuthorEmail instead. Red-first test with an
author != committer fixture.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pure extraction of the Azure commit mapping for direct unit testing.
Behaviour unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Azure recorded the author display name only and populated author_username
from the committer. Record the author as "Name <email>" (consistent with
the other providers) and drop author_username: Azure commits carry no
login, so the only honest options are the committer name (wrong) or
nothing. Red-first test asserts the format and the dropped field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fetch authoredDate in graphqlCommitNode and use it for the commit
timestamp, falling back to committedDate when absent. Matches the recorded
author identity; for rebased/applied-suggestion commits the two dates
differ. Red-first test plus a fallback test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Timestamp now sourced from commit.Author.Date rather than the committer
date, matching the recorded author identity. Red-first test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prefer AuthoredDate, falling back to CreatedAt when nil. Matches the
recorded author identity. Red-first test plus a fallback test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@claude

claude Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

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


PR Review: source PR commit author identity & timestamps from git author

  • Static analysis (go build, go vet, go mod tidy)
  • Review GitLab changes
  • Review Azure changes
  • Review GitHub changes
  • Review tests
  • Post review feedback

Verdict: LGTM. Clean, well-tested completion of the server#5479 author/timestamp fix. Refactor-then-fix slicing with pure commitFrom<Provider>Commit seams makes the mapping unit-testable without live APIs — exactly the testability pattern CLAUDE.md asks for. All three TODO(server#5479) markers are cleared.

Static analysis

Check Result
go build ./... ✅ passes
go vet (azure/gitlab/github) ✅ clean
go mod tidy + git diff go.mod go.sum ✅ no changes

(I couldn't run go test — the test runner needs an approval I don't have in this environment — but the new tests are small, deterministic, and I traced each by hand against the production code; they line up.)

Strengths

  • Consistent fallback handling where the API may omit the author date: GitHub (AuthoredDateCommittedDate) and GitLab (AuthoredDateCreatedAt) both guard and fall back, each with a dedicated regression test (FallsBackToCommittedDate / FallsBackToCreatedAt). Good edge-case coverage.
  • Right call dropping Azure author_username rather than back-filling it from the committer — Azure commits carry no login, and omitempty keeps it off the wire. The test asserts Empty(c.AuthorUsername), which locks that intent in.
  • Regression tests use realistic GitHub web-flow scenarios (committer = GitHub <noreply@github.com> distinct from author) — that's the exact case the bug manifests in, not a synthetic one.
  • The PR body's compatibility note (values change, wire schema unchanged; never-alone / commit-time-window policies may flip) is accurate and important — please do land the changelog + docs note before release as you flagged.

Observations (all non-blocking)

  1. Azure — two new pointer dereferences (internal/azure/azure.go:181-182): *commit.Author.Email and commit.Author.Date.Time are dereferenced where the old code only used Author.Name + Committer.Date. Consistent with the file's existing deref-freely style, so not a regression in kind — just a slightly larger nil blast radius. Inline comment with an optional guard. (Fix this →)

  2. GitLab CreatedAt fallback is unguarded (gitlab.go): when AuthoredDate == nil, the code calls commit.CreatedAt.Unix() with no nil check, so a commit with both dates nil would panic. This is pre-existing behaviour (the old code already did commit.CreatedAt.Unix() unconditionally), so it's not introduced here — but since you just added a nil guard for AuthoredDate, it's a natural moment to consider one for the CreatedAt fallback too. Optional.

  3. Minor cross-provider asymmetry: GitHub/GitLab express the timestamp choice as an explicit fallback chain; Azure just reads Author.Date directly (no fallback to committer date). Fine given Azure always populates author date — noting only for symmetry.

Nice, disciplined PR — small slices, tests-first, clear commit messages.

Comment thread internal/azure/azure.go
@AlexKantor87 AlexKantor87 merged commit d075b7e into 5479-pr-attestation-author Jun 12, 2026
20 checks passed
@AlexKantor87 AlexKantor87 deleted the 5479-author-todos branch June 12, 2026 14:46
@AlexKantor87

Copy link
Copy Markdown
Contributor Author

Folded into #957 via fast-forward (signed commits preserved) so the full server#5479 change is one reviewable unit for the merge-to-main approval. No code changed in the fold.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant