Next.jsで開発したGitHub分析アプリ「Team Insights」をVercelにデプロイしたところ、ローカルでは完璧に動いていたsimple-gitが全く動かない問題に遭遇しました。この記事では、なぜVercelでgitコマンドが使えないのか、そしてGitHub APIへ移行して解決した方法を紹介します。
何が起きたか
Team Insightsは、GitHubリポジトリの開発活動を分析・可視化するWebアプリです。当初の設計では、simple-gitライブラリを使ってリポジトリをcloneし、コミット履歴やPR情報を分析していました。
ローカル開発環境では問題なく動作。意気揚々とVercelにデプロイしたところ、こんなエラーが発生しました。正確に覚えてないけど..
Error: fatal: unable to access '/tmp/repo/': git not foundgitコマンドが見つからない..?
なぜVercelでsimple-gitが動かないのか
原因を調べてみると、Vercelのサーバーレス環境の特性にありました。
1. gitバイナリがインストールされていない
Vercelのサーバーレス関数は、AWS Lambdaに近い環境で動作します。最小限のランタイムのみが用意されており、gitコマンドはデフォルトでインストールされていません。
2. ファイルシステムの制限
サーバーレス環境では、書き込み可能なディレクトリは/tmpのみ。しかもこちらのDiscussionによると容量は512MBに制限されているらしいです。
→ https://github.com/vercel/vercel/discussions/5320
大きなリポジトリをcloneしようとすると、容量オーバーになる可能性もあります。
3. 実行時間の制限
Vercelのサーバーレス関数には実行時間の上限があります。
→ https://vercel.com/docs/functions/limitations#max-duration
大規模なリポジトリのcloneには数分かかることもあり、タイムアウトのリスクがありました。
解決策の選択肢
いくつかの選択肢を検討しました。
案1: Vercel以外のgitが使える環境にデプロイする
AWS EC2やRenderなど、gitが使える環境にデプロイする方法です。
案2: Docker対応のプラットフォームにデプロイする
Dockerコンテナをサポートするプラットフォームを使えば、gitをインストールした環境を構築できます。
案3: GitHub APIに移行する
リポジトリをcloneする代わりに、GitHub REST APIから必要なデータを取得する方法です。
最終的に案3のGitHub APIへの移行を選びました。理由は以下の通りです。
- clone不要でシンプル
- サーバーレス環境との相性がいい
- Vercelの利便性をそのまま維持できる
- 大規模リポジトリでも高速に動作
GitHub APIへの移行実装
実際の移行手順を紹介します。
Octokitの導入
GitHubの公式JavaScriptクライアント「Octokit」を使います。
npm install @octokit/rest認証の設定
Team InsightsではNextAuth.js v5でGitHub OAuthを実装しているため、ユーザーのアクセストークンをそのまま使えます。
import { Octokit } from '@octokit/rest';
const octokit = new Octokit({
auth: accessToken, // GitHub OAuthで取得したトークン
});Before: simple-gitでの実装
移行前のコードはこのような形でした。
import simpleGit from 'simple-git';
async function analyzeRepository(repoUrl: string) {
const repoPath = '/tmp/repo';
// リポジトリをclone
await simpleGit().clone(repoUrl, repoPath);
// コミット履歴を取得
const git = simpleGit(repoPath);
const log = await git.log();
return log.all;
}After: GitHub APIでの実装
移行後はこのようになりました。
import { Octokit } from '@octokit/rest';
async function analyzeRepository(
owner: string,
repo: string,
accessToken: string
) {
const octokit = new Octokit({ auth: accessToken });
// コミット履歴を取得
const { data: commits } = await octokit.rest.repos.listCommits({
owner,
repo,
per_page: 100,
});
return commits;
}cloneの処理が完全に不要になり、コードもシンプルになりました。
よく使うAPIエンドポイント
Team Insightsで使用している主なエンドポイントを紹介します。
// コミット一覧を取得
const { data: commits } = await octokit.rest.repos.listCommits({
owner,
repo,
per_page: 100,
});
// PR一覧を取得
const { data: pulls } = await octokit.rest.pulls.list({
owner,
repo,
state: 'all',
per_page: 100,
});
// リポジトリ情報を取得
const { data: repository } = await octokit.rest.repos.get({
owner,
repo,
});移行で得られたメリット
GitHub APIへの移行により、いくつかの嬉しい副産物がありました。
1. cloneが不要に
clone不要になったことで、大規模リポジトリでも短時間で分析が完了するようになりました。以前は数分かかることもあったので、UXが大幅に改善しました。
2. サーバーレス環境との相性○
ファイルシステムを使わないため、Vercelの制約を全く気にする必要がなくなりました。
3. コードのシンプル化
一時ディレクトリの管理やcleanup処理が不要になり、コードの見通しが良くなりました。
注意点・ハマりポイント
移行にあたっていくつか注意すべき点があります。
1. Rate Limit
GitHub APIにはRate Limitがあります。認証済みリクエストで5,000回/時間です。
// Rate Limit情報を確認
const { data: rateLimit } = await octokit.rest.rateLimit.get();
console.log(rateLimit.rate.remaining); // 残りリクエスト数大量のデータを取得する場合は、Rate Limitを意識した設計が必要です。
2. ページネーション
GitHub APIは1回のリクエストで最大100件までしか取得できません。それ以上のデータが必要な場合は、ページネーションを実装する必要があります。
async function getAllCommits(owner: string, repo: string) {
const allCommits = [];
let page = 1;
while (true) {
const { data: commits } = await octokit.rest.repos.listCommits({
owner,
repo,
per_page: 100,
page,
});
if (commits.length === 0) break;
allCommits.push(...commits);
page++;
}
return allCommits;
}3. GitHub APIで取得できない情報
GitHub APIは多くの情報を提供していますが、すべてのgit操作をカバーしているわけではありません。必要な情報がAPIで取得可能か、事前にドキュメントを確認しておきましょう。
まとめ
Vercelでsimple-gitが動かない問題は、GitHub APIへの移行で解決できました。
振り返ると、最初からGitHub APIで設計していれば良かったという反省があります。Vercelのようなサーバーレス環境でGitHub連携アプリを作る場合は、最初からGitHub API一択で考えるのが正解です。
同じ問題に遭遇した方の参考になれば幸いです。
Team Insightsは現在も開発を続けています。興味のある方はぜひ使ってみてください。

コメント