コードベース移行ガイド
フレームワークのアップグレード、APIリネーム、設定ファイルの書き換え、構造的なリファクタリングを、数百ファイルにわたって調整します。ローカルの編集はエージェントが実行し、Composio CLI が周辺処理(課題管理、バッチごとのPR、CI検証)を担当します。
いつ使うか
- フレームワークアップグレード(React 17 → 19、Node 18 → 22、Django 4 → 5)。
- モノレポ内のAPIリネーム(例:
getUserById→users.byId)。 - 設定/フォーマットの移行(webpack → vite、eslint → biome、jest → vitest)。
- 「200ファイルを同じ方法で変更する」タスクで、レビュー可能なスライスに分割して出荷したい場合。
前提条件
curl -fsSL https://composio.dev/install | bash
composio login
composio link github # PR + CIステータス用
composio link linear # または jira — 移行管理用
エージェントが直接使用するローカルツール: git, rg, jscodeshift/ts-morph/comby/ast-grep(言語に応じて)、およびテストランナー。
計画フェーズ
- 変換内容を正確に定義する。 悪い例: 「vitestに移行」。良い例: 「
jest.mockをvi.mockに置き換え、jest.fn()をvi.fn()に置き換え、jest.config.jsをテンプレートXを使ってvitest.config.tsにリネーム」。 - 影響範囲を評価する:
rg -l 'jest\.(mock|fn|spyOn)' | wc -l rg -l 'from "jest"' | sort - 追跡用の課題を作成する:
composio execute LINEAR_CREATE_ISSUE -d '{ "teamId":"TEAM_ID", "title":"テストランナー移行: jest → vitest", "description":"各バッチ約25ファイル。各PRがグリーンになったらチェックポイント。" }'
レビュー可能なバッチで実行する
ループ: Nファイル選択 → 変換 → テスト → PR → グリーンを待つ → マージ → 次のバッチ。
# バッチヘルパー: パターンに一致する最初の25ファイル(未処理のものから)
BATCH=$(rg -l 'jest\.mock' | grep -v done.list | head -25)
echo "$BATCH" > batch.list
エージェントが batch.list に対してcodemodを実行し、その後:
git checkout -b migrate/vitest-batch-03
xargs < batch.list codemod-runner # 例: jscodeshift / ts-morph / comby
npm test -- --changed
git add -A && git commit -m "migrate(test): jest → vitest (batch 3)"
git push -u origin migrate/vitest-batch-03
composio execute GITHUB_CREATE_A_PULL_REQUEST -d '{
"owner":"acme","repo":"app",
"head":"migrate/vitest-batch-03","base":"main",
"title":"migrate(test): jest → vitest (batch 3)",
"body":"LIN-482 の一部。25ファイル。Codemod: `transforms/jest-to-vitest.ts`。"
}'
次にCIをポーリングし、グリーンになったらマージ:
composio execute GITHUB_LIST_WORKFLOW_RUNS_FOR_A_REPOSITORY \
-d '{"owner":"acme","repo":"app","branch":"migrate/vitest-batch-03"}'
ワークフロースクリプト
scripts/migrate-batch.ts、バッチごとに composio run --file scripts/migrate-batch.ts -- --batch 3 で実行:
const batch = process.argv[process.argv.indexOf("--batch") + 1];
const pr = await execute("GITHUB_CREATE_A_PULL_REQUEST", {
owner: "acme", repo: "app",
head: `migrate/vitest-batch-${batch}`, base: "main",
title: `migrate(test): jest → vitest (batch ${batch})`,
body: `LIN-482 の一部。transforms/jest-to-vitest.ts を参照。`
});
await execute("LINEAR_CREATE_COMMENT", {
issueId: "LIN-482",
body: `PR #${pr.number} をオープン: ${pr.html_url}`
});
安全策
- 1 PRにつき1つの変換のみ。 リネームとフォーマット変更を混在させない。
done.listを維持する 移行済みファイルを記録し、次のバッチでスキップする。- 最終バッチではテストスイート全体を実行する、たとえバッチごとのPRが
--changedで実行されても。 - Codemodを優先、手動編集は後。 codemodで3ファイル見逃したら手動で修正し、PR本文に記録する。
- バッチごとにロールバックする、全体ではなく。各PRはクリーンにリバートできること。
検証ループ
各マージ後:
rg 'jest\.(mock|fn|spyOn)' | wc -l # 0に近づくはず
npm test # 全テストスイート
composio execute GITHUB_LIST_WORKFLOW_RUNS_FOR_A_REPOSITORY \
-d '{"owner":"acme","repo":"app","branch":"main","event":"push"}' \
| jq '.workflow_runs[0].conclusion'
トラブルシューティング
- codemodの正規表現が拾いすぎる → ASTベースのツール(
ast-grep、ts-morph)に切り替えて構造マッチングを行う。 - ローカルでテストが通るがCIで失敗する → Node/Pythonのバージョンを同じに固定する;
.nvmrc/pyproject.tomlを確認。 - PRが大きすぎてレビューできない → バッチサイズを半分にする; メンテナーは800行の差分をレビューしない。
- バッチ間でコンフリクトが発生する → 現在のバッチをマージする前にオープンバッチをリベースする; マージ済みバッチにはforce pushしない。
CLI完全リファレンス: docs.composio.dev/docs/cli