Sync your GitHub contribution graph to Google Calendar, day by day.
A lightweight FastAPI service that reads GitHub contributions and upserts all-day events into Google Calendar.
POST /syncto fetch and sync daily contributions in a date range.- GitHub GraphQL API integration via
contributionsCollection. - Google Calendar upsert using
extendedProperties.private.externalId. - Automatic color mapping by contribution count (
colorId). dry_runmode to preview create/update counts without writing.- Explicit upstream error handling (
502 Bad Gatewayfor GitHub/Google failures). - Unit tests included (settings, models, color mapping, sync logic, API clients).
Client
-> FastAPI (/sync)
-> SyncService
-> GitHubClient (fetch contribution days)
-> GoogleCalendarClient (upsert events)
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtexport GITHUB_TOKEN=ghp_xxx
export GOOGLE_ACCESS_TOKEN=ya29.xxxuvicorn app.main:app --reloadOpen: http://127.0.0.1:8000/docs
Health check endpoint.
Sync contribution days to Google Calendar.
{
"github_username": "octocat",
"calendar_id": "primary",
"start_date": "2026-01-01",
"end_date": "2026-01-31",
"show_zero_days": true,
"dry_run": false
}{
"synced_events": 31,
"skipped_days": 5,
"created_events": 20,
"updated_events": 11,
"dry_run": false
}400Validation error (e.g., invalid date range)500Missing required environment variables502Upstream API error (GitHub / Google)
pytest -qGitHubのコントリビューション(草)を、日単位でGoogleカレンダーへ同期するFastAPIサービスです。
POST /syncで指定期間の日別コントリビューションを取得・同期- GitHub GraphQL API(
contributionsCollection)連携 - Google Calendar API 連携(
extendedProperties.private.externalIdでupsert) - コントリビューション件数に応じた
colorIdを自動付与 dry_runによる書き込みなしの差分確認- 上流API障害時に
502 Bad Gatewayを返す明示的エラーハンドリング - ユニットテスト(設定検証・モデル検証・色マッピング・同期ロジック・APIクライアント)
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtexport GITHUB_TOKEN=ghp_xxx
export GOOGLE_ACCESS_TOKEN=ya29.xxxuvicorn app.main:app --reloadヘルスチェック。
コントリビューション情報をGoogleカレンダーに同期します。
{
"github_username": "octocat",
"calendar_id": "primary",
"start_date": "2026-01-01",
"end_date": "2026-01-31",
"show_zero_days": true,
"dry_run": false
}{
"synced_events": 31,
"skipped_days": 5,
"created_events": 20,
"updated_events": 11,
"dry_run": false
}400: バリデーションエラー(例: 日付範囲不正)500: 必須環境変数不足502: GitHub / Google の上流APIエラー
pytest -q