2025年8月16日から9月15日まで、株式会社プレイドのDeveloper Experience & Performanceチームで、1か月のサマーインターンに参加しました。特定の画面や機能ではなく、複数のプロダクトチームが使うテスト、Lint、依存管理、CI、静的検査を横断して改善しました。
参加した背景
参加前から、GitHub Actions、Vitest、Storybook、Playwright、Turborepoを使った開発フローに関心がありました。一方、個人開発の規模では、変更範囲の特定、複数チームへの展開、CIコストと安全性の両立を十分に経験できません。
インターン先のkarte-io-systemsは、複数のpnpm workspaceと36のsystemを含む巨大なモノレポでした。本人執筆の公開記事では、当時29万6千件を超えるコミットがあり、Issue・Pull Request番号が13万3千台に達していたと記録しています。
Developer Experience & Performanceチームは特定製品に閉じず、ライブラリ、標準的な開発経路、CI/CDなどを通してプロダクトチームの開発体験を改善します。私は既存の運用を観察し、小さな修正から複数workspaceにまたがる移行までをPull Request単位で進めました。
公開記事に記録された担当
公開記事には、次の成果が記録されています。
- Vitest Test Projectsと変更関連テストだけを実行するCIの導入
- Express、Hono、tRPC向けの社内ESLintプラグイン開発
- pnpm catalogへの依存バージョン集約
pncatへのOSSコントリビュート- GitHub ActionsからNamespace runnerへの移行検証
- 既存フロントエンドのESLint v9移行とルール有効化
- role、キーボード操作、
fieldsetとlegendなどのアクセシビリティ修正 - Terraform向けTrivy静的検査の試験導入
- Tailwind CSS v4対応、CIのLint・型チェック修正など、複数リポジトリの改善
以下では、その中でも判断過程を公開できる5つの取り組みを整理します。
1. 変更に関係するテストだけを実行する
KARTE AIのworkspaceには12個のVitest設定があり、内部packageをまたぐ依存関係の追跡が必要でした。まずVitest Test Projectsを使って設定をルートへ集約し、内部packageのソースを追跡できるようにしました。
当初はvitest run --changed=<ref>を使うため、shallow fetchとsparse checkoutでmerge baseに必要な履歴だけを取得しようとしました。しかし、巨大な履歴ではcheckoutに50秒以上かかり、差分テストのための準備として実用的ではありませんでした。
そこでPull RequestではGitHub REST APIを使って変更ファイル一覧を取得し、対象workspaceからの相対パスへ変換してvitest relatedへ渡しました。公開記事では、変更ファイル取得を2秒まで短縮したと報告しています。一方、developへのpushでは全テストを実行し、Pull Requestの速さと統合後の安全確認を分けました。
2. 安全なデータ取得をLintルールにする
Express、Hono、tRPCで、request bodyから渡されたproject ID、user ID、API keyをそのまま信頼する実装を禁止する社内ESLintプラグインを開発しました。認証済みsessionやサーバー管理の値を使う設計を、レビュー時の注意事項だけでなく静的検査として共有するためです。
プラグイン群は、今後ルールを追加しやすいTurborepo構成にし、GitHub Actions、Changesets、pnpmでreleaseとpublishを管理しました。正例・負例はVitestとeslint-vitest-rule-testerで記述し、検出位置とmessageもsnapshotで確認しました。公開記事では、publish後に一部workspaceへ導入したことを記録しています。
3. 依存バージョンをpnpm catalogへ集約する
各package.jsonが個別に依存バージョンを持つと、同じpackageの異なるバージョンが混在し、更新箇所とインストールされる依存が増えます。2つのpnpm workspace、合計47ファイルをpncat CLIでpnpm catalogへ移行しました。
名前付きcatalogは複数のmajor versionを意図的に併存させる場合に使い、通常の依存は名前なしのcatalog:へまとめる方針にしました。catalogMode: strictでcatalog利用を必須にし、cleanupUnusedCatalogs: trueで未使用項目を整理します。結果として、2つのsystemでそれぞれ127packageと90packageをcatalog管理へ統一しました。
移行中に、default catalogが冗長なcatalog:defaultとして書き出される問題を見つけ、pncat本体へ修正を送りました。公開されているPull Request #3と#4で、生成だけでなくdetectとmigrateの経路もcatalog:へそろえています。
4. runnerを変えてキャッシュの前提を見直す
既存のGitHub Actionsでは、container初期化とpnpm installがボトルネックでした。依存が変わるとcacheのdownload・uploadにも時間がかかるため、ローカルNVMeへcacheを保持できるNamespace runnerへ移行して検証しました。
公開記事では、対象test jobを1分14秒から32秒へ短縮したと報告しています。ただし、Namespaceのcheckout actionはsparse checkoutに対応せず約15秒かかった一方、従来のactions/checkoutとsparse checkoutは約2秒でした。そのため、runnerを全面的に置き換えるのではなく、test実行環境とcacheはNamespace、checkoutは既存actionという組み合わせを残しました。
5. Terraformの静的検査を開発環境とCIに置く
評価環境向けTerraformの静的検査では、TrivyとCheckovを比較しました。コマンドだけでなく、開発者が修正中に使うVS Code拡張の利用条件も選定対象にしました。
当時確認したCheckov側の拡張はAPI keyや有料serviceとの関係があり、community forkも期待した動作をしなかったため、公式のOSS拡張を利用できるTrivyを選びました。trivy.yaml、VS Code拡張、GitHub Actionsをそろえ、手元とCIで別の規則にならない形で試験導入しました。
得た設計基準と今後
1か月で、CI、test、Lint、dependency、accessibility、security scanを横断するPull Requestを作成しました。個々の変更は異なりますが、共通していたのは、既存の遅さや危険を計測・再現し、導入後も各product teamが維持できる形へ落とすことです。
差分testではPull Requestとdevelopで安全性の境界を分け、runner移行では速い部分だけを採用し、ESLint pluginでは文章による注意を自動検査へ変換しました。新しいtoolを入れること自体ではなく、巨大な既存環境の制約下でどこに境界を置くかがDeveloper Experienceの設計対象でした。
今後も同種の改善では、導入したtoolの数ではなく、変更前後の時間、影響するworkspace、失敗時の戻し方、保守するチームが使い続けられるかを確認します。Pull Requestでは関連testを高速に実行し、統合後には全testを残したように、速度と安全性を一つの指標へ単純化しないことが今回の公開事例から得た基準です。
