CircleCI の Config ファイルと一緒にダイエット（最適化）

こんにちは。CircleCI カスタマーサクセスチームの Chisato です。

年末年始は美味しいものを躊躇なく頬張りたくなるものですが、先日、アドベントカレンダーの投稿日と同じ週に健康診断を控えていることを思い出しました。
ちなみにこの時右手に持っていたのは、ダークモカチップフラペチーノ（ホイップ多め）です。
そこで今回、重いConfigファイルをすっきり軽量化するかのごとく、私もプチダイエットしてみることにしました（おまけ参照）。

今回は CircleCI の Config.yml ファイル（設定ファイル）のサイズを重くする設定例と、すっきりさせる方法をご紹介します。

2023年11月に、Config ファイル の サイズの最大値が 4MB から 8MBに変更になりました。
制限は緩くなったものの、それでも制限に引っかかるというケースがあります。
普段あまり Configファイル のリファクタリングをしていないという方は、年末年始のこの機会に設定を見直してみてはいかがでしょうか？

<br>

# 重い Config ファイルの作り方
ここではまず、どういった設定が Config ファイルのサイズを重くしやすいのかをご紹介します。
今回このブログの執筆のためにアドバイスをくださったのは、 カスタマーエンジニアリング マネージャーの Makoto さんです。
Makoto さんお手製の 8MBもある Config ファイルは10万行以上あり、操作時にラップトップからのファンの音を楽しめます。

### 複雑な処理や手順が多い処理等の大きなスクリプトを、 Configファイルに直接ベタ書きする
ファイルサイズの大きな重い Configファイルを作る要因のひとつとして、複雑な処理を Configファイルにベタ書きする、というのがあります。
非常に読みづらく、管理しづらいファイルに仕上がります。

### パラメータを具体的に細かく設定する
複数のパターンがある時、各パターンごとにパラメータを設定すると、あっという間に Config ファイルの行数を稼ぐことができます。

ちなみに、パラメーターの定義は下記のとおりです。
パイプラインパラメーター: 型指定されたパイプライン変数。 設定ファイルの一番上にある parameters キーで宣言します。 parameters は、API からパイプラインの新規実行をトリガーする際にパイプラインに渡すことができます。
（詳細はこちら：[パイプラインの値とパラメーター](https://circleci.com/docs/ja/pipeline-variables/#pipeline-parameters-in-configuration)）

<br>

# Config ファイルのサイズの確認方法
Source → compiled の処理の段階で、必ずファイルサイズは大きくなります。
このため、Source の段階では 8MB を下回っていても、compiledで展開した際にサイズが8MBを超えると、ワークフローは実行できません。
今回 8MB のファイルでビルドを試みましたが、下記のエラーメッセージが出ました。
”Your compiled config is too large to be processed. Please contact support.”
他には次のようなエラーメッセージが出るようです。
"Unexpected exception processing config"
"A compiled config YAML must be at most 8MB"

そもそも、ワークフローを実行せずに Config ファイルのサイズを確認する方法はないのでしょうか？

あります！CircleCI CLIを使って確認できます。

次のコマンドを実行すると、設定ファイルがバリデーションされると共に、展開されたソース設定ファイルが元の設定ファイルと一緒に表示されます (Orb を使用している場合に便利です)。

```
circleci config process
```

CircleCI CLI について、詳しくはこちら
[CircleCI ローカル CLI の使用方法](https://circleci.com/docs/ja/how-to-use-the-circleci-local-cli/#processing-a-config)

# Config ファイルの設定・管理において重要な考え方
Makotoさんが 感じている世の中の傾向として、「config ファイルをリファクタする重要性が理解されていない」というものがあります。
CI/CD の利用目的は、ソフトウェアのライフサイクルを速くまわすというものです。これを達成しつづけようとすると、普通は状況の変化に応じてワークフロー、パイプラインも変化するはずです。
ただ、「一度設定したまま Configファイルの設定を見直していない」という声を聞くことも少なくありません。
放置しておくと、最初はわずかだったズレがどんどんと大きくなっていき、直すのも大変になります。そして、使う方もどんどん使いづらくなります。使いづらく直しづらくなった状態のファイルを、重い腰を上げて直そうとするには、かなりの労力がかかるのではないでしょうか。

このため、「Config ファイルは定期的に設定を見直し、その時のチームやプロジェクトの状況にあった設定に育てていく」というのがベストプラクティスです。

<br>

# Config ファイルの軽量化
ここでは、Config ファイルの軽量化・最適化のための方法を7つご紹介します。

### 大きなスクリプトを config.yml に直接書き込んでいる場合は、そのスクリプトを外部化する
これにより、`run` ステップが「スクリプトを実行する」という一行のシンプルなものになります。
下記のような config ファイルになります。
```
    - checkout # まずスクリプトをダウンロードしてくるべく checkout
    - run: run_my_own_script.sh # run_my_own_script.sh に config.yml に直書きされていたスクリプトをあらかじめ書き出しておいて、最終的に run_my_own_script.sh を実行
```

### 類似したステップやジョブの定義が何度も出てこないよう command/job を抽象化

「パラメータを正しく設計することが重要! 」というのは、説明の際にMakotoさんが何度も強調していました。
１つの定義で全体のパターンをカバーできるように心がけましょう。
E2EテストはOSごとに作法がちがう場合があるので、全体に対しての定義をつくりつつ、変更が必要なところだけ別途定義するようにしましょう。


### 環境変数の設定のような処理は BASH_ENV を活用して繰り返さない

CircleCI は、`BASH_ENV` の環境変数を各ビルドの最初に定義します。

環境変数の動的設定のような、各ステップ実行時に毎回実行したい処理は、 config.yml に書き込まず BASH_ENV に書き出すことをおすすめします。
詳細はこちらのサポート アーティクルを参照：[Source a bash file before every command](https://support.circleci.com/hc/en-us/articles/360011501714-Source-a-bash-file-before-every-command-)

<br>

上記以外にも、下記サポートアーティクルで紹介されている Tips をご紹介します。
[Receiving "Your compiled config is too large to be processed." How Can I Reduce my Config File Size?](https://support.circleci.com/hc/en-us/articles/8258725964699-How-can-I-reduce-my-config-file-size-)
詳しい手順は記事を参照ください。

### カスタムの Docker イメージに、依存関係をプリインストールしておく
Docker エグゼキュターを用いたジョブに対して有効です。
これにより、ビルドの一部として依存関係をインストールする必要がなくなります。

### Orb の中の不要なジョブやコマンドを取り除く
Orb の中のジョブやコマンドは、すべての実行環境（例：Linux, MacOS, Windows）を網羅していることが多いため、そのままインストールするのではなく、不要なものを取り除いたほうがコンパクトに利用できます。

### ダイナミックコンフィグを用いて、 Config ファイルを分割する
ダイナミックコンフィグを用いると、複数の Config ファイルを設定でき、条件に基づいて動的にワークフローを実行することも可能になります。

### プロジェクトを複数のプロジェクトに分割する
モノレポや、各コンポーネントを独立したプロジェクトにできそうな場合など、限定的なケースで有用な手段です。

<br>


# おまけ
私のプチダイエットと、来年の抱負について紹介します。
今回は、健康診断までに1kg体重を落とすことにしました。
誤差の範囲のような数字ですが、実施期間が短かったのと、外食の予定が結構入っていたので、無理は禁物です。

実践したのは以下の3つです。
- 会社でランチを食べるとき、配膳してくれる方に「少なめでお願いします」と伝える。
- 数日に1回はジムのサウナに行く。（大好きなお風呂に行くと考えると、行くハードルが下がる。現地についてしまえば、「しょうがない、プールでちょっとだけ歩くか」とついでに運動する気持ちが湧いたり湧かなかったりする。）
- 理想的な体型の友人と時間を多く過ごす。（友人の食事・行動習慣からいろいろ勉強させてもらう）

上記の実践の結果、無事に1kg減量を達成しました。

<br>

来年の抱負
先日聞いた、野原しんのすけ氏の「あー、いいもん見た。長生きしててよかった」というセリフがとても気に入りました。来年は、このセリフを5回以上言えるような素敵な年にしたいと思います。

いつも CircleCI をご利用いただきありがとうございます。
良いお年をお迎えください。


<br>


技術的なご質問はこちら：[サポートセンター](https://support.circleci.com/hc/ja)
上記のページをスクロールダウンすると、サポート アーティクルをご覧いただけます。
サポート アーティクルでは、たくさんの有益な情報を発信しています。