mikefarah/yqを使って複数のYAMLを統合する

開発環境

> yq --version
yq (https://github.com/mikefarah/yq/) version 4.25.2

モチベーション

CircleCIで複数YAMLを扱う場合はDynamic Configurationを利用し、その際に複数YAMLを1つのYAMLに統合する必要がある。今回はyqを使って2つのYAMLを統合してみる。

使用するYAML

android.yml

version: 2.1

jobs:
  android-job:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run: "echo Android!"

workflows:
  android-workflow:
    jobs:
      - android-job

ios.yml

version: 2.1

parameters:
  ios-manual:
    type: boolean
    default: false

jobs:
  ios-job:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run: "echo iOS!"

workflows:
  ios-workflow:
    when: << pipeline.parameters.ios-manual >>
    jobs:
      - ios-job

ゴール

  • version の記載を1行のみ追加する
  • ios.yml の parameter をコピーする
  • jobs 配下に両ファイルの jobs をコピーする
  • workflows 配下に両ファイルの workflows をコピーする

単純な統合

> yq android.yml ios.yml > merged.yml
version: 2.1
jobs:
  android-job:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run: "echo Android!"
workflows:
  android-workflow:
    jobs:
      - android-job
---
version: 2.1
parameters:
  ios-manual:
    type: boolean
    default: false
jobs:
  ios-job:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run: "echo iOS!"
workflows:
  ios-workflow:
    when: << pipeline.parameters.ios-manual >>
    jobs:
      - ios-job

yq を使った最もシンプルなYAML結合。versionjobs などが重複していたり、仕切り線(---) があって消したい。

eval-all と reduce を組み合わせる

直前の問題は表題を使えば解決できた。

> yq eval-all '. as $item ireduce ({}; . * $item)' android.yml ios.yml > merged.yml
version: 2.1
jobs:
  android-job:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run: "echo Android!"
  ios-job:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run: "echo iOS!"
workflows:
  android-workflow:
    jobs:
      - android-job
  ios-workflow:
    when: << pipeline.parameters.ios-manual >>
    jobs:
      - ios-job
parameters:
  ios-manual:
    type: boolean
    default: false

ゴールが満たせていい感じに結合ができた。
一点だけ、同じkeyでもvalueが異なる場合(versionが2.1だったり2.2だったりする場合)は後続の評価が優先されるところは注意する必要がありそう。

参考