三話目の今日は、パスフィルタリングと組み合わせてみるぞー!
第一話:設定ファイル分割の紹介
第二話:モノレポ用の実験
前回の最後に
こんなことを言ったので、今日ぼけーっと考えてた
ブランチごとに合成方法を変えたりできるかなぁ?か、変更があったサービスのジョブだけ実行したりできないかなぁ?のどっちかを考えてみたいな。できるかどうか分かんないけど!
ブランチは別にいっか
でも、ブランチは別に考えなくていいなと思った。main だったらこの設定ファイルだけを合成に使う、feature ブランチだったらこの設定ファイル、みたいにブランチごとに合成する設定ファイルを変えるのは、あんまりユースケースが思いつかない
あるかもって思ったのは「ブランチごとの設定を別ファイルに分けてわかりやすく管理したい」かな。でも、それは特に難しいことを考えずに今の機能で足りそう。 main.yml
とか feature.yml
とかにそれぞれのブランチ用のワークフローを書いて、それをマージしてしまえば良さそうなので
変更があったサービスのジョブだけ実行
ということで、今日はこちらを実験してみようと思う
どういうものかというと、昨日試してみたモノレポ的なリポジトリで「変更が入ったサービスのビルドだけを実行したい!」っての
実は、これ自体は既に公式の Orb がある。path-filtering という Orb
この Orb もダイナミックコンフィグを使ってるから、組み合わせて動くかなぁ?ってのを試してみるだけになるかな
path-filtering Orb
まずは path-filtering Orb のことを簡単に紹介
僕が読んだ記事たち↓。どれも分かりやすいー!
- CircleCI Cloudのpath-filteringを試してみる
- [CircleCI][Orbs][path-filtering]特定ディレクトリに差分が出たらterraform applyを適用するように実装してみた – ADACHIN SERVER LABO
- CircleCIのDynamic Configで差分ビルド - Carpe Diem
- ブログズミ: CircleCI でモノレポ上の指定パスに変更があったらテストを走らせる
仕組み
セットアップ用のジョブに、こんな風に書くと
version: 2.1 setup: true orbs: path-filtering: circleci/path-filtering@0.1.3 workflows: setup-workflow: jobs: - path-filtering/filter: config-path: .circleci/continue-config.yml mapping: | src/.* build-code true doc/.* build-docs true
mapping
の定義に従って、正規表現に一致したファイルに変更が入った場合に、指定してあるパラメータに指定した値が設定される(正規表現 パラメータ名 パラメータ値 になってる)config-path
に指定したファイルを設定ファイルとして、ダイナミックコンフィグの機能を使ってパイプラインが実行される。このときに(1)のパラメータが渡される
なので、上の例だと .circleci/continue-config.yml
の中で build-code
や build-docs
というパラメータが true
かどうかをジョブの実行条件に加えることで「変更が入ったサービスのビルドだけを実行したい!」が実現できる
どこからの差分?
ところで「変更が入った」ってどこからの差分だろう?と思って Orb のコードを見てみたらデフォルトでは main
からの差分だった。なるほど。・・・ん?
「え、じゃあ main 自体のビルドの場合はどうなるの?」って思うよね。で、見てみたら main
の場合は一個前のコミットとの差分を見てた。へー
だから、気をつけておきたいのは、main
でビルドに失敗して、もういっかい何か変更を加えてコミットしてプッシュしたときとかに、一個前のコミットとの差分を元に起動されて大丈夫かどうかってところかなぁ
そういうときのために、手動でトリガーできるパイプラインパラメーターを用意しておくか、まぁ、ジョブを走らせたいディレクトリのファイルをわざと触るかしたら良さそうかな
組み合わせる
で、本題の、設定ファイル分割と、この path-filtering を同時に動かせるかどうか、ってやつ
ここまでの情報をふまえると頭の中では、大丈夫そう。先に設定ファイル合成のジョブを走らせておいてから、そこで合成したファイル名を path-filtering/filter
ジョブの config-path
に指定してあげれば動くはず
ということで、本当に動くかどうかやってみよー!
実験
今日のコード:
こんな構成にしてみた
path-filtering は mapping にマッチしなかったケースを書いておいてあげないといけないので Tsuji さんの記事を参考に noop.yml
を書いたのと
version: 2.1 jobs: noop: docker: - image: cimg/base:stable steps: - run: name: "No operation" command: echo "No operation" workflows: noop: when: and: - not: << pipeline.parameters.build-service1 >> - not: << pipeline.parameters.build-service2 >> jobs: - noop
パラメータの定義が必要なのでそれを parameters.yml
に書いておいた
version: 2.1 parameters: build-service1: type: boolean default: false build-service2: type: boolean default: false
別ファイルで既に書いてあるから、version: 2.1
はつけなくてもいいんだけど、なんとなく
それに合わせて、config.yml
以外の YAML ファイルも読み込めるように find の正規表現を昨日のやつから少し変えておいた
command: | find . -type f -regex '.*/\.circleci/.*\.yml' -not -regex '\./\.circleci/config\.yml' \ | tee .circleci/config-list.txt
今日のは余裕やろー!
と思って
generate-config
->path-filtering/filter
なセットアップワークフローをこんな風に書いたら
workflows: setup-workflow: jobs: - generate-config - path-filtering/filter: config-path: .circleci/generated_config.yml mapping: | service1/.* build-service1 true service2/.* build-service2 true requires: - generate-config
怒られた!
jq: error: Could not open file .circleci/generated_config.yml: No such file or directory
・・・はっ!そうか。ジョブ間でファイルを渡してあげなきゃか
ワークスペースを使う
ジョブ間のファイルのやりとりにはワークスペースを使えばいいので
generate-config
ジョブの最後にこうやって
- persist_to_workspace: root: . paths: - .circleci/generated_config.yml
で、どうやって、このワークスペースを path-filtering/filter
にアタッチしようかなぁって思って見てみたら
path-filtering/filter
に workspace_path
ってパラメータがあった。Orb のソースを見た感じ、これを使えばちょうどいい場所でアタッチしてくれそう
なので、こういう感じになった(workspace_path: .
が足した部分)
workflows: setup-workflow: jobs: - generate-config - path-filtering/filter: workspace_path: . config-path: .circleci/generated_config.yml mapping: | service1/.* build-service1 true service2/.* build-service2 true requires: - generate-config
動作確認
じゃ、動作確認していこー!
service1
にも service2
にも変更が入らなかった場合 -> noop
ワークフローが実行された
service1
にだけ変更が入った場合 -> service1
用のワークフローだけが実行された
service2
にだけ変更が入った場合 -> service2
用のワークフローだけが実行された
service1
にも service2
にも変更が入った場合 -> 両方のワークフローが実行された
やったー!
次は
アンカーの動作確認をしておきたい。これまで特に YAML の要素の順番を気にしてこなかったけど、YAML のアンカーって先に定義がでてきてないと怒られるんじゃないかなぁ?って思うのでその確認をしておきたい
で、それが終わったら、このファイル分割の機能を Orb 化しようかな
楽しい3連休だったー!
間引いたバジルで娘1がカプレーゼ作ってくれた! pic.twitter.com/1hFMrma311
— Mitsuyuki Shiiba (@bufferings) July 18, 2022
今日も今日とて宣伝
梅田まで来れる方はぜひお申し込みくださいませー!