Skip to content

🧹 [Code Health] Refactor fetchContributions to reduce complexity#454

Open
is0692vs wants to merge 1 commit into
mainfrom
fix/github-contributions-refactor-7121083320895186331
Open

🧹 [Code Health] Refactor fetchContributions to reduce complexity#454
is0692vs wants to merge 1 commit into
mainfrom
fix/github-contributions-refactor-7121083320895186331

Conversation

@is0692vs

@is0692vs is0692vs commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

🎯 What: Extracted CONTRIBUTIONS_QUERY, processContributionsCalendar, and calculateRecentContributions out of fetchContributions.
💡 Why: Improves maintainability and readability by reducing the length and complexity of fetchContributions.
✅ Verification: Ran test suite and manually verified logic.
✨ Result: fetchContributions is now shorter and more focused.


PR created automatically by Jules for task 7121083320895186331 started by @is0692vs

Greptile Summary

このPRは fetchContributions 関数のリファクタリングで、GraphQLクエリ文字列・カレンダー変換ロジック・直近コントリビューション集計をそれぞれモジュールレベルの定数・関数として切り出しています。ロジック自体に変更はなく、既存の動作は維持されています。

  • CONTRIBUTIONS_QUERY をモジュール定数として分離し、再利用しやすくした
  • processContributionsCalendarcalculateRecentContributions を独立した関数として抽出し、fetchContributions の見通しを改善
  • 抽出時に定義された ContributionWeek 型が実際には参照されておらず、不要なデッドコードが残っている

Confidence Score: 4/5

純粋なリファクタリングでロジック変更はなく、マージは安全。

抽出された3つの関数はオリジナルのロジックを忠実に再現しており、動作への影響はない。未使用の ContributionWeek 型と残存する空行という軽微な整理残しがあるものの、機能的な問題はない。

src/lib/github.ts の ContributionWeek 型(508行目)は定義後に参照されておらず、削除または活用が必要。

Important Files Changed

Filename Overview
src/lib/github.ts fetchContributions からGraphQLクエリ・カレンダー処理・直近集計の3つを抽出してモジュールレベルに移動。ロジックの変更はなく既存の挙動を保持しているが、未使用の ContributionWeek 型と余分な空行が残存している。

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant fetchContributions
    participant graphql
    participant processContributionsCalendar
    participant calculateRecentContributions
    participant calculateStreaks
    participant calculateMostActiveDay

    Caller->>fetchContributions: username, token
    fetchContributions->>graphql: CONTRIBUTIONS_QUERY, token, variables
    graphql-->>fetchContributions: ContributionsResponse
    fetchContributions->>processContributionsCalendar: cc.contributionCalendar.weeks
    processContributionsCalendar-->>fetchContributions: calendar (sorted)
    fetchContributions->>calculateRecentContributions: calendar, sevenDaysAgoStr, thirtyDaysAgoStr
    calculateRecentContributions-->>fetchContributions: weeklyContributions, monthlyContributions
    fetchContributions->>calculateStreaks: calendar
    calculateStreaks-->>fetchContributions: longestStreak, currentStreak
    fetchContributions->>calculateMostActiveDay: calendar
    calculateMostActiveDay-->>fetchContributions: mostActiveDay
    fetchContributions-->>Caller: ContributionData
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant fetchContributions
    participant graphql
    participant processContributionsCalendar
    participant calculateRecentContributions
    participant calculateStreaks
    participant calculateMostActiveDay

    Caller->>fetchContributions: username, token
    fetchContributions->>graphql: CONTRIBUTIONS_QUERY, token, variables
    graphql-->>fetchContributions: ContributionsResponse
    fetchContributions->>processContributionsCalendar: cc.contributionCalendar.weeks
    processContributionsCalendar-->>fetchContributions: calendar (sorted)
    fetchContributions->>calculateRecentContributions: calendar, sevenDaysAgoStr, thirtyDaysAgoStr
    calculateRecentContributions-->>fetchContributions: weeklyContributions, monthlyContributions
    fetchContributions->>calculateStreaks: calendar
    calculateStreaks-->>fetchContributions: longestStreak, currentStreak
    fetchContributions->>calculateMostActiveDay: calendar
    calculateMostActiveDay-->>fetchContributions: mostActiveDay
    fetchContributions-->>Caller: ContributionData
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
src/lib/github.ts:508
**未使用の型定義**

`ContributionWeek` 型が定義されていますが、コード内のどこからも参照されていません。`processContributionsCalendar` の引数型は同じ型を直接 `NonNullable<ContributionsResponse["user"]>["contributionsCollection"]["contributionCalendar"]["weeks"]` として展開しているため、この型エイリアスは現状デッドコードになっています。削除するか、関数の引数型を `ContributionWeek[]` に置き換えて活用してください。

### Issue 2 of 2
src/lib/github.ts:560-565
**余分な空行**

インラインクエリを削除した後、`fetchContributions` 内に連続する空行が2行残っています。1行にまとめてください。

```suggestion
  const sevenDaysAgoStr = new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
  const thirtyDaysAgoStr = new Date(now.getTime() - 29 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];

  const data = await graphql<ContributionsResponse>(CONTRIBUTIONS_QUERY, token, {
```

Reviews (1): Last reviewed commit: "refactor: extract helper functions in fe..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Context used:

  • Context used - 日本語で!!! (source)

Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
github-user-summary Ignored Ignored Jul 10, 2026 6:58am

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@is0692vs, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 41 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d27c76f4-cb8b-4d93-ad4b-483766357688

📥 Commits

Reviewing files that changed from the base of the PR and between 05bc250 and af5ec0e.

📒 Files selected for processing (1)
  • src/lib/github.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/github-contributions-refactor-7121083320895186331

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment thread src/lib/github.ts
}
}`;

type ContributionWeek = NonNullable<ContributionsResponse["user"]>["contributionsCollection"]["contributionCalendar"]["weeks"][number];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 未使用の型定義

ContributionWeek 型が定義されていますが、コード内のどこからも参照されていません。processContributionsCalendar の引数型は同じ型を直接 NonNullable<ContributionsResponse["user"]>["contributionsCollection"]["contributionCalendar"]["weeks"] として展開しているため、この型エイリアスは現状デッドコードになっています。削除するか、関数の引数型を ContributionWeek[] に置き換えて活用してください。

Context Used: 日本語で!!! (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/github.ts
Line: 508

Comment:
**未使用の型定義**

`ContributionWeek` 型が定義されていますが、コード内のどこからも参照されていません。`processContributionsCalendar` の引数型は同じ型を直接 `NonNullable<ContributionsResponse["user"]>["contributionsCollection"]["contributionCalendar"]["weeks"]` として展開しているため、この型エイリアスは現状デッドコードになっています。削除するか、関数の引数型を `ContributionWeek[]` に置き換えて活用してください。

**Context Used:** 日本語で!!! ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment thread src/lib/github.ts
Comment on lines 560 to +565
const sevenDaysAgoStr = new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
const thirtyDaysAgoStr = new Date(now.getTime() - 29 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];

const query = `query($login: String!, $from: DateTime!, $to: DateTime!) {
user(login: $login) {
contributionsCollection(from: $from, to: $to) {
totalCommitContributions
totalPullRequestContributions
totalIssueContributions
totalPullRequestReviewContributions
contributionCalendar {
totalContributions
weeks {
contributionDays {
date
contributionCount
}
}
}
}
}
}`;

const data = await graphql<ContributionsResponse>(query, token, {

const data = await graphql<ContributionsResponse>(CONTRIBUTIONS_QUERY, token, {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 余分な空行

インラインクエリを削除した後、fetchContributions 内に連続する空行が2行残っています。1行にまとめてください。

Suggested change
const sevenDaysAgoStr = new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
const thirtyDaysAgoStr = new Date(now.getTime() - 29 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
const query = `query($login: String!, $from: DateTime!, $to: DateTime!) {
user(login: $login) {
contributionsCollection(from: $from, to: $to) {
totalCommitContributions
totalPullRequestContributions
totalIssueContributions
totalPullRequestReviewContributions
contributionCalendar {
totalContributions
weeks {
contributionDays {
date
contributionCount
}
}
}
}
}
}`;
const data = await graphql<ContributionsResponse>(query, token, {
const data = await graphql<ContributionsResponse>(CONTRIBUTIONS_QUERY, token, {
const sevenDaysAgoStr = new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
const thirtyDaysAgoStr = new Date(now.getTime() - 29 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
const data = await graphql<ContributionsResponse>(CONTRIBUTIONS_QUERY, token, {
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/github.ts
Line: 560-565

Comment:
**余分な空行**

インラインクエリを削除した後、`fetchContributions` 内に連続する空行が2行残っています。1行にまとめてください。

```suggestion
  const sevenDaysAgoStr = new Date(now.getTime() - 6 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
  const thirtyDaysAgoStr = new Date(now.getTime() - 29 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];

  const data = await graphql<ContributionsResponse>(CONTRIBUTIONS_QUERY, token, {
```

How can I resolve this? If you propose a fix, please make it concise.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors src/lib/github.ts by extracting the GraphQL query into a constant and modularizing the contribution processing logic into helper functions. The reviewer suggests improving type safety and readability by defining a ContributionDay type and ensuring explicit return types for the new helper functions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/lib/github.ts

type ContributionWeek = NonNullable<ContributionsResponse["user"]>["contributionsCollection"]["contributionCalendar"]["weeks"][number];

function processContributionsCalendar(weeks: NonNullable<ContributionsResponse["user"]>["contributionsCollection"]["contributionCalendar"]["weeks"]) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve readability and type safety, you can introduce a ContributionDay type and use the existing ContributionWeek type. This makes the function signature cleaner and more self-documenting.

First, define ContributionDay before this function:

type ContributionDay = { date: string; count: number };

Then, you can update this function's signature. You should also update calculateRecentContributions to use ContributionDay[] for its calendar parameter. Ensure that explicit return types are maintained for type safety.

Suggested change
function processContributionsCalendar(weeks: NonNullable<ContributionsResponse["user"]>["contributionsCollection"]["contributionCalendar"]["weeks"]) {
function processContributionsCalendar(weeks: ContributionWeek[]): ContributionDay[] {
References
  1. Maintain explicit return types for functions in TypeScript to ensure type safety and API clarity.

Comment thread src/lib/github.ts
return calendar;
}

function calculateRecentContributions(calendar: { date: string; count: number }[], sevenDaysAgoStr: string, thirtyDaysAgoStr: string) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To align with the suggested change in processContributionsCalendar, you should update this function to use the new ContributionDay type for the calendar parameter. Additionally, ensure the function has an explicit return type to maintain type safety and API clarity.

Suggested change
function calculateRecentContributions(calendar: { date: string; count: number }[], sevenDaysAgoStr: string, thirtyDaysAgoStr: string) {
function calculateRecentContributions(calendar: ContributionDay[], sevenDaysAgoStr: string, thirtyDaysAgoStr: string): number {
References
  1. Maintain explicit return types for functions in TypeScript to ensure type safety and API clarity.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant