ビルド成果物をGit管理から除外し、ビルドステップを各フローに組み込む

basecamp/lexxy

JavaScriptのビルド成果物(lexxy.js等)をGit管理から除外し、CI・gem build・bin/setupそれぞれのフローにyarn buildを自動的に組み込むことで、PRごとのマージコンフリクトを解消しつつ、各利用シーンで必要なアセットが確実に生成される仕組みを整備しました。

背景

app/assets/javascript/以下のビルド成果物が、ソースコード変更を含むすべてのPRでマージコンフリクトを引き起こしていました。lexxy.js(14,087行)・.min.js.br.gzはいずれもyarn buildが生成するアーティファクトであり、ソースコードとしての意味を持ちません。バンドル結果のような大容量生成ファイルをバージョン管理に含めると、差分ノイズの増加・コンフリクトの頻発・レビューコストの増大といった問題が生じます。

これらのファイルは.gitignore/app/assets/javascript/*.js.mapのみが除外されており、成果物本体は追跡対象のままでした。本PRはこの設計上の不整合を解消するものです。

技術的な変更

ビルド成果物の除外と、それを補うビルドステップの追加が3箇所に施されました。

.gitignoreの変更では、ファイル単位の除外パターンからディレクトリ単位の除外パターンへ変更されています。

変更前:

-/app/assets/javascript/*.js.map

変更後:

+/app/assets/javascript/

これにより、現在存在するlexxy.jslexxy.min.js.br.gzだけでなく、将来生成されるいかなる成果物も追跡対象に入らなくなります。CSSのソースファイルはapp/assets/stylesheets/に、JSのソースファイルはsrc/にあるため、javascript/ディレクトリを丸ごと除外しても追跡すべきファイルは失われません。

Rakefileの変更では、yarn_buildタスクを定義し、Rake::Task["build"].enhanceを使って既存のbuildタスクの前処理として差し込んでいます。

task :yarn_build do
  sh "yarn build"
end

Rake::Task["build"].enhance([ :yarn_build ])

enhanceメソッドは既存タスクの定義を書き換えずに依存タスクを追加できるため、bundler/gem_tasksが定義したbuildタスクを侵襲することなく前処理を注入できます。これによりgem build(Rakeのbuildタスク)を実行すると自動的にyarn buildが先行し、gemファイルに最新のビルド成果物が同梱されます。

CIとセットアップスクリプトの変更では、rails-system-testsジョブのyarn installステップの直後にyarn buildステップが追加され、bin/setupでもyarn installの直後にyarn buildが実行されるようになりました。PRの説明によれば、ビルド済みアセットを必要とするのはRailsシステムテストのジョブのみであり、PlaywrightやVitestのジョブには変更はありません。

設計判断

「ビルド成果物はディスクに生成するが、Gitには含めない」 という原則を、gem配布・CI・開発環境セットアップの3つの経路すべてで一貫させた設計です。

各経路でyarn buildを呼び出すタイミングを明示的に管理することで、「Gitから取得するだけでは動かない」という状態を許容しつつ、「各フローの正しいステップで必ずビルドが実行される」ことを保証しています。lexxy.gemspecのglobはビルド時にディスク上のファイルを拾うため、gemspec自体の変更は不要です。

また、Rake::Task["build"].enhanceによる注入は、bundler/gem_tasksが提供するタスクを直接上書きしない低侵襲なアプローチです。Rakeの依存関係解決に委ねることで、将来的なbundler側の変更にも追従しやすくなっています。

まとめ

ビルド成果物の除外とビルドステップの各フローへの組み込みを同時に行うことで、マージコンフリクトの根本原因を取り除きながら、gemの配布・CI・ローカル開発のいずれの経路でも成果物が欠けない状態を維持しています。変更の規模は小さいものの、「何をGitで管理し、何をビルドプロセスに委ねるか」という境界を明確に引き直した設計上の整理といえます。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
46adaaf6

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

「総論→各論→結論」の構成が明確です。リード文で要旨を述べ、背景、技術詳細、設計判断、まとめが適切に配置されています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```diff:.gitignore, ```ruby:Rakefile)やGitHubへのリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

ビルドプロセスやCI/CD、Rakeタスクに関する内容で、専門知識を持つエンジニアという対象読者に適切です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論の構成になっており、各段落はトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が遵守されています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内のコード引用(.gitignore, Rakefile)は、提供されたDiff情報と完全に一致しています。CIやsetupスクリプトの変更に関する説明も正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「Rake::Task#enhance」や「アーティファクト」、「低侵襲」など、技術用語の選択と使用法が正確かつ適切です。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

各変更点(.gitignore, Rakefile, CI)に関する技術的な説明は、Diffの内容と整合しており、論理的かつ正確です。「enhance」メソッドの役割についても的確に解説されています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(マージコンフリクトの問題、gemspecの変更が不要な理由など)は、PRのDescriptionやDiffによって裏付けられています。ハルシネーションは見られません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#861)や削除されたファイルの行数(14,087行)など、数値や固有名詞はすべて正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトルは、PRのタイトル「Remove built JavaScript assets from git」とPR全体の変更内容を的確に要約しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PR情報に記載のない外部知識(LTS情報、リリース日程など)の追記はなく、事実に基づいた記述になっています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現に関する歪曲や不正確な記述は見られませんでした。