Carina の開発はこれまでコード自体をほとんど見ずにやらせていたので、コード全体の品質や一貫性がどうなっているかは把握していなかった。
そこで、Claude Codeに問題点をGitHubイシューとして登録させ、そのイシューをひとつずつ潰させる、というサイクルを回してみた。イシューの対応はすべて自分でPRをレビューしてからマージしていて、これは自分自身のコードや設計の理解を深める意味もある。10日間回した結果、90個のイシューが登録され、67個がクローズされた。
具体的な作業フローはこんな感じ。
/pick-issue
スキルを呼ぶと、一番新しいオープンイシューをpickしてくる
/self-review
スキルで5回セルフレビューさせる
イシューの優先順位付けは特にやっていない。
/pick-issue
が一番新しいイシューを拾ってくるので、基本的にはFILO(後入れ先出し)で回している。気になるイシューがあれば
/pick-issue 123
のように番号指定することもあるが、大半はそのまま最新のものを拾わせている。修正の過程で見つかった新しいイシューが次にpickされやすいので、関連する問題が芋づる式に片付いていく、という副次的な効果もある。
イシューの登録元はセルフレビューだけではなく、コードベース全体のレビューや、acceptance testの実行結果から問題を拾ってイシューに登録させる、ということもやっている。
このフローだと、完全にボトルネックは人間によるレビュー。レビュー対象はPRのコードだけでなく、Claude Codeが立てたplanも含まれる。plan段階でプロジェクトの方針とまったく逆方向の提案をしてくることもあるので、方針がおかしければそこで差し戻す。
まずClaude Codeにコードベース全体のレビューとacceptance testの実行をさせたところ、1日で23個のイシューが登録された。バグ、設計上の問題、不足している機能など、色々なカテゴリのイシューが一気に出てきた。たとえば:
Effect::Delete
にリソース識別子が含まれていない(
#135
)
create_plan()
が削除すべきリソースを検出しない(
#137
)
name
属性をリソース識別子として使うのをやめるべき(
#148
)
初日のイシューを潰し始めると、修正の過程で新たな問題が次々と見つかった。
特に大きかったのが、
--detailed-exitcode
(
#130
)の実装と、acceptance testへのapply後plan verify追加(
#129
)。apply後にもう一度planを実行して差分がないことを確認する仕組みを入れたところ、べき等性の問題が大量に見つかった。
List<Struct>
の比較が順序依存で、false diffが出る(
#171
)
acceptance testを実際に10アカウント並列で回すと、テストランナー自体のバグも出てきた。ワーカーサブシェルがエラーで黙って停止する問題( #170 )や、apply失敗時のリソースクリーンアップ( #180 )など。こういった問題もすべてイシューとして登録させて、同じフローで潰していった。
べき等性の問題を追いかけていくと、根本原因がenum処理の一貫性のなさに行き着いた。
enumの正規化・バリデーション・変換まわりはアドホックなコードが多く、
normalize_instance_tenancy
、
normalize_region
のような個別のハードコードされた関数が各crateに散らばっていて、それぞれ微妙に違う挙動をしていた。
ここからenumの大掃除が始まった。
normalize_*
関数を
carina-core::utils
に集約(
#201
、
#204
)
get_enum_valid_values()
をスキーマ定義から自動生成(
#186
)
extract_enum_value
パターンの重複排除(
#203
、
#209
、
#219
)
ひとつ直すと「この関数と同じパターンがあっちにもある」「この関数、もう使われてないのでは」と芋づる式にイシューが出てくる。Claude Codeに「さっき直した関数と同じパターンが他にもないか探して」と指示すると、重複を見つけてイシューを登録し、修正してくれる。
enumの大掃除が一段落したところで、今度はAPIの公開範囲の見直しに入った。
validate_iam_policy_document
をprivateに(
#231
)
validate_namespaced_enum
を
pub(crate)
に(
#233
)
pub(crate)
に(
#236
)
validate_*
関数のエラーメッセージ形式を統一(
#228
)
この日は13個のイシューが登録され、13個すべてクローズ。登録してすぐ直す、のリズムが回っていた。
同じ日に、コード生成まわりのバグもいくつか見つかった。VPC Endpoint IDの演算子優先順位問題( #244 )は、初日に登録されていた #132 の派生バグで、5日かけて全箇所を潰した形になる。
初日のレビューで「carina-coreやCLIにプロバイダ固有のロジックが入り込んでいる」( #155 )というイシューが登録されていた。ここに本格的に着手。
ProviderFactory
トレイトを導入して、設定バリデーション、リージョン抽出、プロバイダインスタンス化、スキーマ読み込みを抽象化した(
#259
)。CLI側にあった
"aws"
や
"awscc"
のmatchブロックがなくなり、新しいプロバイダを追加してもCLIのコードを変更する必要がなくなった。
enum処理のうちプロバイダ固有のものも、CLI側からProvider trait側に移動させた( #185 、 #190 )。
10日間のサイクルで実装された主な機能・改善をまとめておく。
新機能:
carina plan --out=plan.json
/
carina apply plan.json
)
--detailed-exitcode
フラグ
lifecycle { force_delete }
メタ引数
<attr>_prefix
サポート(ランダムサフィックス付きリソース名生成)
IpProtocol
の
all
→
-1
など)
リファクタリング:
name
属性からの分離)
ProviderFactory
traitによるCLI/プロバイダの分離
テスト: