Skip to content

fix: guard against commit author with no login - #21

Merged
blimmer merged 1 commit into
mainfrom
fix/commit-author-missing-login
May 27, 2026
Merged

fix: guard against commit author with no login#21
blimmer merged 1 commit into
mainfrom
fix/commit-author-missing-login

Conversation

@blimmer

@blimmer blimmer commented May 27, 2026

Copy link
Copy Markdown
Contributor

Summary

A production scan crashed with an uncaught TypeError: undefined is not an object (evaluating 'author.login.endsWith') (Sentry PATCHWAVE-ANALYSIS-CLI-1). The GitHub REST "List commits" endpoint can return a non-null author object that has no login — the empty-object arm of GitHub's documented simple-user | {} | null union, which surfaces for e.g. deleted/anonymized accounts. Our hand-rolled ListCommitsItem type claimed login: string, so the truthy-author guard passed and author.login.endsWith('[bot]') threw, killing the whole scan. This makes the type honest (login?: string) and skips authors without a login.

Closes PATCHWAVE-ANALYSIS-CLI-1.

Review focus

This is the minimal hot-fix. The deeper issue is that our GithubClient seam takes the response type as a blind caller-supplied generic (paginate<T>(route: string, ...)), fully disconnected from octokit's published endpoint types — so hand-rolled REST response interfaces can silently drift from reality. Other REST collectors (repos.ts, request<T> callers) carry the same latent risk. Tracking that as a separate follow-up rather than expanding scope here.

Commits

  • 1141f86 — guard against a commit author with no login and make the ListCommitsItem type honest

The GitHub REST "List commits" endpoint can return a non-null author
object that has no login (an empty-object arm of the documented union,
e.g. a deleted/anonymized account). Our hand-rolled ListCommitsItem type
claimed login: string, so the truthy-author guard passed and
author.login.endsWith('[bot]') threw an uncaught TypeError that crashed
the scan.

Make the type honest (login?: string) and skip authors without a login.

Fixes PATCHWAVE-ANALYSIS-CLI-1
@blimmer
blimmer requested a review from jcarver989 as a code owner May 27, 2026 19:00
@blimmer
blimmer merged commit 75097bf into main May 27, 2026
7 checks passed
@blimmer
blimmer deleted the fix/commit-author-missing-login branch May 27, 2026 19:01
blimmer pushed a commit that referenced this pull request May 27, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.2.2](v0.2.1...v0.2.2)
(2026-05-27)


### Bug Fixes

* guard against commit author with no login
([#21](#21))
([75097bf](75097bf))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: contextbridge-pr-automation[bot] <259134118+contextbridge-pr-automation[bot]@users.noreply.github.com>
blimmer added a commit that referenced this pull request May 27, 2026
## Summary

Follow-up to the `PATCHWAVE-ANALYSIS-CLI-1` hot-fix (#21). The root
cause was that `GithubClient` took the response type as a blind
caller-supplied generic (`paginate<T>(route: string, …)`), so every
collector hand-rolled a response interface that could drift from
GitHub's real API. This binds our types to the **published schemas** and
adds a runtime safety net for the cases types can't catch:

- **REST** — `paginate`/`request` are now generic over the route
literal, deriving params + response types from octokit's `Endpoints` /
`PaginatingEndpoints`. Field typos and genuinely-absent/nullable fields
now fail at compile time.
- **GraphQL** — `graphql()` takes a `TypedDocumentNode`; the
Dependabot-PR query moved to a `.graphql` file with types generated by
graphql-codegen against `@octokit/graphql-schema` (no more hand-rolled
`RawPullRequest`/`RawActor`).
- **Runtime validation** — `paginate()` accepts a Zod schema reflecting
reality; invalid items are dropped with a warning instead of crashing
the scan. Collectors keep ownership of normalization (schema +
raw→domain map), so everything downstream still sees only clean domain
types.

Build wiring is consolidated behind one `bun run build:assets` step
(graphql codegen + report-web) referenced by package scripts, the
justfile, and goreleaser. The generated module is committed and excluded
from lint/format.
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