Vercelでsimple-gitが動かない!GitHub APIへの移行記録

Vercelでsimple-gitが動かない!GitHub APIへの移行記録 Next.js
スポンサーリンク

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 found

gitコマンドが見つからない..?

なぜ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は現在も開発を続けています。興味のある方はぜひ使ってみてください。

👉 Team Insights

このブログでは、【ConoHa WING】を使っています

このブログでは、【ConoHa WING】を使っています
ブログ村を利用しています
素人エンジニアの苦悩 - にほんブログ村
PVアクセスランキング にほんブログ村
Next.js
スポンサーリンク
スポンサーリンク
シェアする
amateur_engineerをフォローする
素人エンジニアの苦悩

コメント

タイトルとURLをコピーしました