코드베이스 마이그레이션
수백 개의 파일에 걸친 프레임워크 업그레이드, 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에 대해 코드 모드를 실행한 후:
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개 파일. 코드 모드: `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}`
});
안전 장치
- PR당 하나의 변환만. 이름 변경과 포맷 변경을 절대 섞지 마세요.
done.list를 유지하여 이미 마이그레이션된 파일을 추적하고 다음 배치가 건너뛰도록 합니다.- 마지막 배치에서는 전체 테스트 스위트를 실행하세요. 배치별 PR이
--changed옵션으로 실행되었더라도 마찬가지입니다. - 코드 모드 먼저, 수동 편집은 나중에. 코드 모드가 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'
문제 해결
- 코드 모드 정규식이 너무 많이 잡힘 → 구조적 일치를 위해 AST 기반 도구(
ast-grep,ts-morph)로 전환하세요. - 로컬에서는 테스트가 통과하지만 CI에서 실패 → Node/Python 버전 일치 확인;
.nvmrc/pyproject.toml을 확인하세요. - PR이 리뷰하기 너무 큼 → 배치 크기를 절반으로 줄이세요; 메인테이너는 800줄 짜리 diff를 리뷰하지 않습니다.
- 배치 간 충돌 → 현재 배치를 병합하기 전에 열린 배치를 리베이스하세요; 병합된 배치에 강제 푸시하지 마세요.
전체 CLI 참조: docs.composio.dev/docs/cli