個人開発で複数のプロダクトを同時に運用していると、開発日記(devlog)の管理が課題になります。各リポジトリで日記を書きたいけど、全体を俯瞰したいときは1箇所で見たい。この記事では、GitHub Actionsを使って複数リポジトリの開発日記を自動集約する仕組みを解説します。
背景:なぜ自動集約が必要か
私は現在、6つのプロダクトを並行して開発しています。
- CancelNavi(サブスク解約ナビ)
- Wakulier(フリーランス向け依頼管理)
- IdeaSpool(アイデア管理ツール)
- BandBridge(ミュージシャンマッチング)
- 自治会DX(自治会業務デジタル化)
- ZERONOVA LAB(このサイト)
各プロダクトには独自のリポジトリがあり、そこで開発日記を書いています。しかし、ポートフォリオサイト(ZERONOVA LAB)では全プロダクトの開発状況を一覧したい。
手動コピーの問題点:
- 毎日複数リポジトリを巡回してコピーするのは面倒
- コピー忘れが発生する
- 形式の統一が難しい
そこで、Claude Code を活用して GitHub Actionsで毎日自動同期する仕組みを構築しました。
設計方針
全件同期 vs 差分同期
最初に悩んだのは同期方式です。開発日記にはこう書きました:
開発日記の同期方式: 差分同期 vs 全件同期で迷った。結論: 全件同期(毎回全ファイルをコピー)で十分。日記ファイルは軽量で、Git Actions の実行時間も1-2分程度
| 方式 | メリット | デメリット |
|---|---|---|
| 差分同期 | 処理が速い | 削除検知が複雑、状態管理が必要 |
| 全件同期 | シンプル、確実 | 処理時間がやや長い |
結論として全件同期を選択しました。理由は:
- 開発日記ファイルは軽量(1ファイル数KB)
- GitHub Actionsの実行時間は1-2分程度
- 月2000分の無料枠に対して余裕あり(30-60分/月)
リポジトリ名とディレクトリ名のマッピング
リポジトリ名とプロダクト名が一致しないケースがあります。
product-a-repo → product-a(プロダクト名)
product-b-repo → product-b(わかりやすい名前)
これを環境変数で定義することで柔軟に対応します。
実装
ワークフロー全体像
name: Sync Devlogs & Features
on:
schedule:
# 毎日 9:00 JST (0:00 UTC) に実行
- cron: '0 0 * * *'
workflow_dispatch:
inputs:
repositories:
description: '同期するリポジトリ(カンマ区切り、空欄で全て)'
required: false
default: ''
env:
REPOSITORIES: |
your-username/product-a-repo:product-a
your-username/product-b
your-username/product-c-repo:product-c
REPOSITORIES 環境変数で同期対象を定義。リポジトリ名:ディレクトリ名 の形式で、ディレクトリ名を省略するとリポジトリ名がそのまま使われます。
PAT(Personal Access Token)の設定
プライベートリポジトリにアクセスするには、Fine-grained PAT が必要です。
設定手順:
- GitHub Settings > Developer settings > Personal access tokens > Fine-grained tokens
- Repository access で対象リポジトリを選択
- Permissions で
Contents: Read-onlyを設定 - 生成したトークンをリポジトリの Secrets に
REPO_ACCESS_TOKENとして登録
sparse-checkout で必要なディレクトリだけ取得
大きなリポジトリでも sparse-checkout を使えば特定ディレクトリだけを取得できます。
git clone --depth 1 --sparse "https://x-access-token:${GH_TOKEN}@github.com/${repo}.git" "temp/${repo_name}"
cd "temp/${repo_name}"
git sparse-checkout set docs/devlog
--depth 1: 最新のコミットのみ取得--sparse: sparse-checkout モードで clonegit sparse-checkout set docs/devlog: devlog ディレクトリのみ展開
これにより、clone の所要時間を大幅に短縮できます。
GITHUB_TOKEN vs カスタム PAT の使い分け
ここで重要なのが、2種類のトークンの使い分けです。
| トークン | 用途 | 権限 |
|---|---|---|
GITHUB_TOKEN | ワークフローが実行されるリポジトリへのアクセス | 自動付与、write 権限あり |
| カスタム PAT | 他リポジトリへのアクセス | 手動設定、必要最小限の権限 |
実装のポイント:
- name: Checkout zeronova-lab
uses: actions/checkout@v4
# GITHUB_TOKEN を使用(デフォルト)
- name: Sync devlogs from repositories
env:
GH_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
run: |
# カスタム PAT で他リポジトリを clone
git clone "https://x-access-token:${GH_TOKEN}@github.com/${repo}.git"
checkout ステップではデフォルトの GITHUB_TOKEN を使用し、他リポジトリの clone にはカスタム PAT を使用します。
初回実装時のトラブルと解決
実は最初、checkout ステップでもカスタム PAT を使ってしまい、エラーが発生しました。
Error: exit code 128: git clone failed
原因: カスタム PAT は他リポジトリへの Read-only 権限のみで、zeronova-lab への write 権限がなかった
解決: checkout ステップから token パラメータを削除し、デフォルトの GITHUB_TOKEN を使用
最小権限の原則を守りつつ、適切にトークンを使い分けることが重要です。
インデックス自動生成
同期後、統合インデックスを自動生成するスクリプトも Claude Code で用意しました。
#!/bin/bash
# generate-devlog-index.sh
DEVLOG_DIR="docs/devlog"
OUTPUT_FILE="$DEVLOG_DIR/README.md"
cat > "$OUTPUT_FILE" << 'EOF'
# 開発日記(Devlog)統合インデックス
全プロダクトの開発日記を一覧できます。
このファイルは GitHub Actions により自動生成されています。
EOF
for product_dir in "$DEVLOG_DIR"/*/; do
product=$(basename "$product_dir")
echo "## $product" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# 日付降順でファイルを列挙
for file in $(ls -r "$product_dir"*.md 2>/dev/null); do
filename=$(basename "$file" .md)
echo "- [$filename](./$product/$filename.md)" >> "$OUTPUT_FILE"
done
echo "" >> "$OUTPUT_FILE"
done
運用してみた結果
実行時間
ワークフローの実行時間は約13秒でした。
Run sync devlogs from repositories
処理中: your-username/product-a-repo -> product-a
✓ product-a の devlog を同期しました
処理中: your-username/product-b -> product-b
✓ product-b の devlog を同期しました
...
5リポジトリを同期しても余裕です。
GitHub Actions の無料枠
- 無料枠: 2,000分/月(プライベートリポジトリ)
- 使用量: 約1分/日 × 30日 = 30分/月
- 余裕度: 98.5%
全く問題ありません。
応用:機能リストの同期
同じ仕組みで、機能リスト(feature-content-map)も同期しています。
FEATURE_REPOS: |
your-username/product-a:source-file-name:output-file-name
your-username/product-b:feature-map-b:features-b
ただし、機能リストは「機能追加(プロダクト側)」と「記事公開状況(zeronova側)」で更新元が異なるため、2ファイル構成にしています。
docs/synced/features-*.md: 同期ファイル(読み取り専用)docs/content-status-*.md: ステータスファイル(zeronova-lab で編集可能)
まとめ
GitHub Actions を使った複数リポジトリの開発日記自動集約のポイント:
- 全件同期でシンプルに: 差分同期より実装が簡単で、無料枠も余裕
- sparse-checkout で高速化: 必要なディレクトリだけ取得
- トークンの使い分け: GITHUB_TOKEN と カスタム PAT を適切に使い分け
- 環境変数でマッピング: リポジトリ名とディレクトリ名の変換を柔軟に
個人開発でも、このような自動化を導入することで、ドキュメントの一元管理が楽になります。
参考リンク:
Zeronova(ゼロノバ)
Product Manager / AI-Native Builder
Web/IT業界19年以上・20以上のWebサービスを担当したPdM。東証プライム上場企業の子会社代表として事業経営を経験。現在はAIを駆使して企画から実装まで完結させる個人開発を実践中。