Skip to content

feat(domain): add UserStats type (GIT-33 — PR 1/8)#39

Open
hurtki wants to merge 1 commit into
hurtki/git-33-more-statistics-on-bannerfrom
hurtki/git-33-pr1-userstats-domain
Open

feat(domain): add UserStats type (GIT-33 — PR 1/8)#39
hurtki wants to merge 1 commit into
hurtki/git-33-more-statistics-on-bannerfrom
hurtki/git-33-pr1-userstats-domain

Conversation

@hurtki
Copy link
Copy Markdown
Owner

@hurtki hurtki commented May 9, 2026

First PR in the GIT-33 series (Linear). All PRs target the long-lived base branch hurtki/git-33-more-statistics-on-banner; that branch merges to master at the end.

Summary

  • Adds api/internal/domain.UserStats + ContributionCalendar / ContributionWeek / ContributionDay
  • Mirrors GraphQL response shape: PR/Issue counts by state, totalCommits / totalPRReviews / totalPRsCreated / totalIssuesCreated from contributionsCollection, top-100 repo aggregates (TotalRepos / TotalStars / Languages), and the contribution calendar
  • Adds ContributionCalendar.CurrentStreak() — counts consecutive trailing days with >0 contributions; today=0 is treated as in-progress and does not break the streak

Out of scope

  • Legacy GithubUserStats / GithubUserData / GithubRepository deliberately untouched. Removed in PR 7 once the new banner template fully consumes UserStats.
  • No fetcher / DB / Kafka / renderer changes — those land in PR 2..6.

Test plan

  • go build ./... clean for the api service
  • go test ./internal/domain/ — 8 unit tests for CurrentStreak: empty, all-zero, all-active, mid-streak break, today=0 ignored, today+yesterday=0 → 0, multi-week streak, single active day
  • Reviewer: confirm field naming and that OpenPRs/ClosedPRs/MergedPRs (lifetime, by state) coexisting with TotalPRsCreated (last-year contributions) is the right model

Introduces api/internal/domain.UserStats — the target structure for the
GraphQL stats refactor. Mirrors the GraphQL response: PR/issue counts
by state, totalCommits/totalPRReviews from contributionsCollection,
top-100 repos aggregates (TotalRepos/TotalStars/Languages), and a
ContributionCalendar with a CurrentStreak helper.

Legacy GithubUserStats/GithubUserData/GithubRepository remain in place
and continue to drive the existing flow; they will be removed in PR 7
once the new banner template fully consumes UserStats.
@hurtki
Copy link
Copy Markdown
Owner Author

hurtki commented May 9, 2026

Roadmap for the GIT-33 refactor — context for review

Posting this so you have the full map of what's coming. This PR is just step 1 of 8.

Goal

Replace the current REST-based GitHub fetcher (2+ requests, then we calculate stats locally from raw repos/user data) with a single GraphQL request that returns all stats directly. Also adds a new banner design that uses the richer stats.

Locked decisions (already discussed with the team)

  • DB: drop github_data.users and github_data.repositories, replace with one new user_stats table (jsonb for languages and contribution calendar).
  • Renderer API: new HTTP route /v2/preview. Kafka stays on the same topic — the event_version field already exists in GithubBannerInfoEvent, so we just bump it to 2 and the consumer branches on it.
  • Old banner template: adapted to read from the new UserStats (TotalRepos/TotalStars/Languages are still available there). Kept as a banner type, not removed.
  • GraphQL repos: single query, top 100 by stars, no pagination. Languages aggregate is a sample, not exhaustive — reasonable since it's already weighted toward the user's most prominent work.

Branch flow

All 8 PRs target the long-lived base branch hurtki/git-33-more-statistics-on-banner. That branch will be merged to master only at the end, when everything compiles together. Each PR is small enough to review in isolation.

PR breakdown

  1. (this PR) Domain: new UserStats model — types only, no wiring.
  2. GraphQL fetcher — replace api/internal/infrastructure/github/fetcher.go. Token rotation preserved. One POST to /graphql. Decide on shurcooL/githubv4 vs raw HTTP.
  3. DB migration — drop legacy tables (006), create user_stats (007). New api/internal/repo/user_stats/ package. Cache adapted to new struct (same TTLs).
  4. Stats service + API handlers — rewrite the cache→fetcher→repo flow in domain/user_stats/service.go. Delete calculator.go (no client-side aggregation needed anymore). External REST contract unchanged at this point.
  5. Kafka v2 event — extend the Stats payload, producer writes event_version: 2, consumer branches: v1 → skip+warn, v2 → handle.
  6. Renderer /v2/preview HTTP route — new route + DTO carrying full UserStats. API switches its renderer client to /v2/preview. Old /preview removed. Renderer mirrors the UserStats type.
  7. Adapt old banner + add new banner template — rewrite banner.svg to read from new UserStats. Add new banner_stats.svg (the GitHub Stats design from the issue). Extend BannerType enum, layout builder routes by type. Delete legacy domain types here.
  8. Cleanup — remove the v1 Kafka consumer branch once the production backlog has drained.

What to focus on for this PR specifically

  • Field naming on UserStats. In particular: I kept both OpenPRs/ClosedPRs/MergedPRs (lifetime PRs by state, from the pullRequests queries) and TotalPRsCreated (last-year contributions, from contributionsCollection.totalPullRequestContributions). Same split for issues. Different semantics, both are in the GraphQL query — but if you'd rather collapse one, now's the time.
  • CurrentStreak semantics: today=0 is treated as in-progress and doesn't break the streak; any earlier zero does. Matches GitHub's own UI behavior.
  • Anything in OriginalRepos / ForkedRepos / TotalForks that's missing — those aren't in the GraphQL query in the issue, and the new banner mockup doesn't show them either. The old banner will lose its fork breakdown when adapted in PR 7. Speak up here if that's a problem.

@hurtki
Copy link
Copy Markdown
Owner Author

hurtki commented May 9, 2026

Will continue working on this plan in future

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