上長からconfig.yml分割できないか調査してくれない?ということで調査。
まず、CircleCI公式ドキュメント https://circleci.com/docs/faq/#split-config-into-different-files で
「.circleci/config.yml の複数ファイルへの分割はサポートされていない」
と明言されている。残念・・・
が、同時に
「本件についてもっと情報がほしいなら、このサポート記事 を見たらいい」
とも記述されていた。
対象の記事には
「Dynamic Configuration の セットアップワークフロー を使用すると、.circleci/フォルダに存在しない別のconfig.yml をトリガーにできる」
と記述されている。で、Dynamic Configuaration のドキュメントを参照すると、Dynamic Configuataionを利用するには
- CircleCIのProjectSettingから、Enable dynamic config using setup workflows を ONにする
- config.yml に setup: true を追加する
- ワークフローの最後に continuation orb からジョブを呼び出す
が必要とわかった。
「Dynamic Configurationのセットアップワークフローを利用することで、.circleci/config.ymlとは別のymlでCircleCIを実行できる」ということで、
あとはその別のymlを生成する処理、今回の要件でいうと「分割したymlから continuation orb に実行させるymlを生成する」ステップを、
セットワップワークフロー内で「continuation orb からジョブを呼び出す」のStepの前に実行すればいい。
・・・これらをすごくうまいことやっているのが
で、「分割したymlから continuation orb に実行させるymlを生成する」を yq (jqコマンドのyaml版)を利用して実現している。
実際に記事の通りやってみたらできた!感謝感謝。
2023/10/19追記
この手法、自身の環境だとあまり使い勝手がよくないかも・・・
というのも、やっていることは「分割したconfig.ymlファイルをCI実行時にマージし、それを使ってもっかいCI走らせる」という感じで、
- 毎回マージ処理が走るの無駄。
- 生成はyqにまかせているため、本当に期待通りのマージ後ファイルが生成されて、本当に実行したいCIが走るかまでは担保できてない。
という、デメリットがあることに気づいた。
特に、yqでのマージについては、分割前のconfig.yml内でアンカー(&)とエイリアス(*)を利用している場合、
yq eval-all '. as $item ireduce ({}; . * $item )' file1.yml file2.yml > merged.yml
記事の通りに実行すると「参照できないが?」的なエラーが発生してしまう。
これを防ぐために、一旦「同一ファイルだけど内部的には分割されている扱いのファイル(エイリアスがアンカーを参照できる状態にする)」を作ってからyqにかけるみたいな工夫が必要だった。
TARGET_YML_FILES=$("file1.yml" "file2.yml")
for TARGET_YML_FILE in ${TARGET_YML_FILES[@]}; do
cat "${TARGET_YML_FILE}" >> tmp.yml
echo "---" >> tmp.yml # "---"でYAMLを区切ると1ファイル内で分割されている扱いになる
done
sed -i '$d' tmp.yml # 末尾の"---"を削除
で、がんばったもののyqもバージョン違いで挙動が異なり、古いバージョンだと↑の末尾の"---"を削除しないとエラーになるのに、新しいバージョンだと削除しなくてもエラーにならない・・・というのもあり。その辺の不安定さも、今後これで本運用していくにあたっての懸念になる。
・・・分割したconfig.ymlからマージしてできる 「CI実行のための本質的なconfig.yml」はgit上で差分管理したい し、yqコマンドをローカルで実行して単純に.circleci/config.ymlを作成する運用にした方がよさそう。結構がんばったけど残念。
Dynamic Configurationは、単純にdevelop用、staging用、production用の.circleci/config.ymlを作っておき、workflowで対象ブランチごとに読み込ませたいconfig.ymlを設定するようにする、くらいにとどめておくのがいいのかもしれない。