16 Commits
Author SHA1 Message Date
tiennm99 724990af1d feat: let commits-per-repo 0 mean every commit
The pagination guard broke on seen >= maxPerRepo, so a cap of 0 stopped
before the first page and rendered empty productive-time,
productive-weekday and most-commit-language cards. That inverted the
meaning 0 carries for top-repos, where it already means unlimited.

Treat a cap of 0 or less as no cap. Verified against a real repo: a cap
of 100 still stops at 100, while 500 and 0 both walk the full 382-commit
history.
2026-08-13 14:19:41 +07:00
tiennm99 d6ac8c36ff fix(github): split a saturated quarter by month to recover dropped repos
Quarterly windows were not enough for the busiest quarter: a live run
warned that 2026-04-01..2026-06-30 still came back at the 100-repo
ceiling, so its seed list was truncated and those repos never got
probed for commit history.

Re-ask a saturated quarter month by month and merge only the repo
lists. The quarter has already contributed its calendar days and commit
totals, so the month passes skip that fold; verified by forcing the
ceiling down to 20 and confirming all six calendar-derived cards stay
byte-identical. Warn only when a month itself saturates, since there is
no finer window left to ask for.
2026-08-13 13:34:08 +07:00
tiennm99 939fcdc33a feat: count org repos and fix contribution-window truncation
Split each contribution year into quarterly windows.
commitContributionsByRepository caps at 100 repos per query and drops
the remainder without signalling it, which a prolific year hits: 2026
returned exactly 100 where the quarterly union returns 108. Warn when a
window still comes back at the ceiling instead of reporting a complete
list.

Add -include-org-repos / include_org_repos so org-owned repos the user
administers count toward stars, repo count, repos-per-language and
top-starred. Off by default, since enabling it moves those totals for
every existing caller. Commit-driven cards already covered org repos
through the seed list. Org repos carrying only read or write access are
dropped via viewerPermission.

Rename Profile.PublicRepos to RepoCount and drop "public" from the card
label: the count tracks the fetch filters and includes private repos
whenever the token can see them.
2026-08-13 13:20:41 +07:00
tiennm99andGitHub 1763422570 feat(card): configurable start of week (#25)
* feat(card): configurable start of week for heatmap + weekday cards

New -start-of-week CLI flag (and start_of_week action input) rotates the
contribution-heatmap rows and the productive-weekday bars so users whose
calendars start on Monday (or any other day) get matching output. Default
stays Sunday to preserve existing renders.

* docs: note start-of-week in design-guidelines, codebase-summary, deployment-guide

- design-guidelines: heatmap row order + productive-weekday bar order now derive from Profile.WeekStart
- codebase-summary: list new weekday_start_test.go cases + TestParseWeekday
- deployment-guide: mention start_of_week as an optional action input in the workflow template
2026-04-21 20:57:21 +07:00
tiennm99andGitHub 872a5de358 feat(card): add S-tier cards — heatmap, streak, by-year, weekday, top-starred (#3)
Five new cards, all derived from data FetchProductive / FetchProfile already
pull, so zero additional API calls:

- contributions-heatmap: 7×53 calendar grid with a 5-bucket intensity ramp
  mixed from each theme's Background→Accent so palettes with no dedicated
  heat ramp still render sensibly.
- streak: current streak, longest streak with date ranges, active/total days.
- contributions-by-year: one bar per active year, peak year highlighted.
- productive-weekday + -all-time: 7-bar day-of-week mirror of the hour-of-day
  cards; FetchProductive now also fills Weekday / WeekdayAllTime histograms
  during the same commit-history pass.
- top-starred-repos: top 5 owned non-fork repos by stargazer count; threads
  Stars through RepoInfo.

Card count: 9 → 14. Registered in allCards grouped by recency (last-year
block, then all-time block). Render test extended to cover all new files
and realistic daily-series inputs.
2026-04-19 08:58:59 +07:00
tiennm99 cc7d0c6504 refactor(model): rename TotalContributions → TotalContributionsLastYear
N8 — the field is set from contributionsCollection.contributionCalendar,
a rolling last-year window, not a lifetime total. Rename + updated
comment makes the semantics explicit so future readers don't confuse
it with TotalCommitsAllTime.
2026-04-18 22:43:38 +07:00
tiennm99 76cf242ee9 fix: donut single-slice, partial-year warn, hoist per-repo total
- I1 — donut chart with a single slice (100%) now renders via two
  concentric <circle> elements instead of a degenerate SVG arc that
  drew nothing. Reproduced with a standalone probe; regression test
  added separately.
- I2 — FetchContributionsAllTime logs a warn to stderr when a year's
  query returns nil user data so callers notice partial results
  instead of rendering an empty all-time card silently.
- I6 — attributeCommit() receives the repo's byte total precomputed
  once per repo rather than re-summing language edges for every
  commit in the inner loop.
2026-04-18 22:43:24 +07:00
tiennm99 fcfec9a11b chore: small hygiene fixes from code review
- I3 — update FetchOptions doc to describe zero-value vs CLI-flag defaults.
- I5 — release workflow gates docker/binaries on a test job; tags no
  longer ship broken artifacts.
- N1 — replace handwritten joinErrs with strings.Join.
- N3 — truncate() now backs up to a UTF-8 rune boundary so error
  messages never end on a split codepoint.
- N4 — pin Docker base images (golang:1.26-alpine, alpine:3.21) to
  SHA256 digests.
- N5 — pin third-party GitHub Actions to commit SHAs with version
  comments for readability.
- N9 — drop the "(non-fork)" qualifier from the stats card label; the
  underlying GraphQL doesn't actually filter forks, so the phrasing
  was misleading.
2026-04-18 22:43:14 +07:00
tiennm99 90171c1080 feat: seed-based repo scanning + fork/private visibility flags
Replace the top-10-starred sampling with a seed list built from
contributionsCollection.commitContributionsByRepository, unioned across
every active contributionYear. Commit-history probes now land only on
repos where the user actually committed, covering all owned repos plus
forks and repos owned by others when allowed.

New visibility knobs (default off — public-facing READMEs stay
safe):
- -include-forks / include_forks    : include forked repos
- -include-private / include_private: include private repos (requires
                                      PAT with repo scope)

Compatibility:
- -top-repos default changed 10 → 0 (unlimited); still usable as a cap
  for fast local runs.
- commitHistoryQuery now takes $owner so probes can target forks or
  repos outside the user's ownership.
- FetchProfile now accepts FetchOptions; PublicRepos counts only repos
  that pass the visibility filter.

Seed-list approach mirrors github-profile-summary-cards' own repo
sourcing but keeps our byte-weighted commit attribution.
2026-04-18 22:01:26 +07:00
tiennm99 208629cf8f feat: add all-time variants of productive, language, contribution cards
Four time-bounded cards ("last year") now have all-time counterparts, and
the stats card gains a lifetime commits row.

New cards:
- 6-most-commit-language-all-time.svg (byte-weighted, all lifetime commits)
- 7-productive-time-all-time.svg       (hour histogram over all lifetime commits)
- 8-contributions-all-time.svg         (area chart spanning every active year)

Data pipeline:
- Drop the "since" filter from commitHistoryQuery; FetchProductive now
  paginates unbounded commits and splits each commit into last-year and
  all-time buckets in a single pass — no extra API calls.
- New contributionYearQuery iterates user.contributionYears to
  concatenate calendar data and accumulate TotalCommitsAllTime.
- -commits-per-repo default bumped 100 → 500 to give all-time depth.

Polish:
- Productive-time title embeds the configured tz as "UTC±N.NN" (e.g.
  UTC+7.00) on both last-year and all-time cards.
- Contribution x-axis flipped to mm/yy with an "mm/yy" footer caption
  paralleling productive-time's "hour of day".
- Contribution x-axis label stride now targets ~6 labels regardless of
  bucket count so the all-time chart (~100 months) stays readable while
  the underlying curve still samples every month.
2026-04-18 21:40:46 +07:00
tiennm99 d0d3862780 feat(card): add contributions area chart card
New 5-contributions.svg renders the last year's contribution calendar
as a monthly smooth-filled area chart. Pure Go SVG; no extra API calls
— one additional contributionCalendar.weeks block in the existing
profile GraphQL query carries the data.

- Y-axis mirrored on both sides with nice ticks.
- X-axis labels in YY/MM format, every other month to avoid overlap.
- Smooth curve via Catmull-Rom interpolation converted to cubic Bezier
  (d3.curveCatmullRom default tension 0.5).
- Missing months between first and last are inserted as zero-count so
  the chart stays time-continuous.
2026-04-18 21:20:52 +07:00
tiennm99 9ac029dfae refactor(github): attribute commits by repo language byte share
Each commit now contributes a full "vote" partitioned across the repo's
languages proportional to linguist byte counts, instead of crediting only
the primary language. A 60% Go / 40% Python repo adds 0.6 to Go and 0.4
to Python per commit.

- RepoInfo gains []LangEdge capturing the full byte breakdown already
  returned by profileQuery.
- FetchProductive distributes each commit via a fixed-point scaleFactor
  (int64 preserved, percentages unchanged in the card).
- Fallback to primary language only when linguist reports zero bytes
  (empty repo).

Caveat: linguist excludes prose languages (Markdown, AsciiDoc, reST) from
its byte output, so Markdown-heavy repos still skew toward the detected
code fraction. Fixing that case requires per-commit file classification
via REST /commits/{sha} + go-enry — tracked as future work.
2026-04-18 20:50:04 +07:00
tiennm99 cb502f2aa2 refactor: match github-profile-summary-cards chart styles
- Productive time is now a 24-hour bar chart with axes and nice tick labels
  instead of a 7x24 heatmap. Model Productive field reshaped from
  [7][24]int to [24]int.
- Language cards render as donut charts with a left-side legend instead of
  a stacked bar. Slices beyond top-6 collapse into an "Other" row.
- Add niceTicks helper (1/2/5 * 10^k ladder, d3-style) for axis ticks.
- Legacy language_bar.go removed.
2026-04-18 19:08:12 +07:00
tiennm99 40c311d304 refactor: split language card into repos-per-language and most-commit-language
Align card set with github-profile-summary-cards' 5-card layout:

  0-profile-details.svg       (unchanged)
  1-repos-per-language.svg    (new) owned repos grouped by primary language
  2-most-commit-language.svg  (new) last-year commits attributed to each repo's primary language
  3-stats.svg                 (renumbered)
  4-productive-time.svg       (renumbered)

- FetchProductive now fills p.CommitsByLanguage from the same commit history
  it uses for the heatmap, so no extra API calls are introduced.
- TopRepos carries primary language so productive-time can aggregate by lang.
- LangStat.Bytes renamed to Value (repo count or commit count, context-dependent).
- Shared bar+legend renderer extracted to language_bar.go.
- Ignore generated output/ directory.
2026-04-18 18:57:42 +07:00
tiennm99 643a15862b feat: implement profile summary cards with GraphQL fetch and Action wrapper
- Add GraphQL client fetching profile, stats, language aggregation, and
  per-repo commit histograms for the productive-time heatmap.
- Render real SVG cards (profile details, top languages, stats grid,
  weekday×hour heatmap) with XML escaping and thousands-formatted numbers.
- Expand theme palette to 30 built-ins ported from github-readme-stats;
  add -list-themes, multi-theme rendering, and 'all' shortcut.
- Package as Docker-based GitHub Action (action.yml, Dockerfile,
  entrypoint.sh) with optional auto-commit of generated cards.
- Release workflow publishes GHCR image and cross-platform binaries on
  v* tags.
- Unit tests cover rendering, XML escape, number formatting, language sort.
2026-04-18 18:39:51 +07:00
tiennm99 d92ef7e324 feat: scaffold ghstats — Go CLI for GitHub profile SVG cards 2026-04-18 18:22:20 +07:00