CircleCI のセットアップ・ワークフロープレビューに参加してみた

CircleCI に「セットアップ・ワークフロー」という新機能を触ってみたので、確認した内容をメモ。
因みに CircleCI2.1 の新機能です。

サンプルリポジトリ

サンプルとなるソースをリポジトリにまとめてみたのでこれを参考に紹介していきます。

セットアップ・ワークフロー

セットアップ・ワークフローに関しては以下のサイトを参照。

セットアップ・ワークフローとは、パイプラインを「セットアップ」するために実行されるワークフローです。CircleCI のジョブが、パイプラインのコンフィグやパラメータを生成、あるいは設定することで「セットアップ」を行います。
セットアップ・ワークフローが有効であることが期待される領域の一つに、モノリポ(モノレポ)を活用いただいているお客様のサポートが挙げられます。Bazel のようなビルドツールを利用して、git コマンドを実行して、変更のあったファイルを検出し、複雑な依存関係を分析した上で、複数あるコンフィグファイルを組み合わせて実行しているといった、さまざまなモノリポのユースケースにおいて、それぞれ異なるジョブを利用することが可能になります。

以上のようにモノリポ(モノレポ)のための機能のようです。

プロジェクトの設定

セットアップ・ワークフローを利用するために、
対象のプロジェクトの Project SettingsAdvanced の中にある Run Setup Workflows (PREVIEW) を有効にしときます。

workflowの有効化

サンプルのディレクトリ構成

src ディレクトリ配下にはモノリポ(モノレポ)っぽくクライアントとサーバーのソース分けてあります。

ディレクトリ構成
Copied!
$ tree
.
├── .circleci
│   ├── config.yml
│   └── sample.yml
├── README.md
└── src
    ├── client
    │   └── index.js
    └── server
        └── index.js

ファイルの中身

.circleci/config.yml
Copied!
version: 2.1

setup: true

orbs:
  path-filtering: circleci/path-filtering@0.0.2

executors:
  default:
    docker:
      - environment:
          TZ: Asia/Tokyo
        image: circleci/node:14.15.5

workflows:
  generate-config:
    jobs:
      - path-filtering/filter:
          base-revision: origin/main
          config-path: .circleci/sample.yml
          mapping: |
            src/server/.* build-server true
            src/client/.* build-client true
  • setup: true
    • セットアップ・ワークフローの有効化(必須です)
  • config-path
    • job や workflow などメインの処理が定義された config ファイルを指定します。
    • サンプルでは sample.yml というファイルですが、読み込むファイルのファイル名を continue_config.yml にすればこの設定は必要なく、自動読み込みされます。
  • mapping
    • 変更されたファイルのファイル名がここで定義された正規表現にマッチしている場合、定義してた「パイプライン パラメータ」を指定した値で明け渡すための定義です。今回のサンプルでは、src/server/配下のファイルが変更されていた場合はbuild-servertrue で明け渡すといった感じです。
.circleci/sample.yml
Copied!
version: 2.1

parameters:
  build-client:
    default: false
    type: boolean
  build-server:
    default: false
    type: boolean

executors:
  default:
    docker:
      - environment:
          TZ: Asia/Tokyo
        image: circleci/node:14.15.5
    working_directory: ~/repo

jobs:
  build-client:
    executor: default
    steps:
      - checkout
      - run:
          name: build-client
          command: |
            echo 'run build-client'

  build-server:
    executor: default
    steps:
      - checkout
      - run:
          name: build-server
          command: |
            echo 'run build-server'
  echo:
    executor: default
    steps:
      - run:
          name: Echo
          command: |
            echo '何もやることないとエラーになるよ'

workflows:
  version: 2
  build-client:
    jobs:
      - build-client
    when: << pipeline.parameters.build-client >>
  build-server:
    jobs:
      - build-server
    when: << pipeline.parameters.build-server >>
  echo:
    jobs:
      - echo
    when:
      and:
        - not: << pipeline.parameters.build-client >>
        - not: << pipeline.parameters.build-server >>
  • parameters
    • ここで、config.yml から渡されるパラメータを定義しておきます。デフォルト値も基本設定しておきましょう。
  • workflows
    • whenparameter 別で実行する workflow を切り替えています。例えば、src/server/ 配下のファイルのみが変更されていた場合は build-servertrue で渡ってくるので、build-server という workflow が実行され、build-client は実行されません。

サンプルまとめ

かなり簡素なサンプルですが、ここで CircleCI のパイプラインに付いて復習です。

パイプラインとは、CircleCI を使用するプロジェクトで作業をトリガーするときに実行される構成全体を指す言葉です。 .circleci/config.yml ファイルの全体が 1 つのパイプラインによって実行されます。

そして、セットアップワークフローの説明です。

セットアップ・ワークフローとは、パイプラインを「セットアップ」するために実行されるワークフローです。

セットアップワークフローを有効化した config.yml でパイプラインを生成または読み込んで実行するだけというイメージでいいと思います。
そのパイプライン呼び出し時に任意のパラメータを「どのファイルが変更されたのかに応じて変更したり」して渡したりすることで、パイプライン上でそのパラメータを利用することも可能です。

注意点

  • No Jobs have been run.All Workflows have been filtered from this Pipeline. - 最後に echo だけしていますが、これがなかった場合に今回のサンプルで例えばトップディレクトリにある README.md ファイルだけを変更した場合、mapping に引っかからないので、全てのパラメータは defaultfalse となってパイプラインは動きます。その結果、実行する workflow がない場合、エラーとなリます。そのため、sample.yml では最後に echo だけしてます。
    エラー画面

  • path-filtering/filter は何度も呼べない

    • 以下のように path-filtering/filter を複数回呼ぶのはできませんでした。
      • {"message":"Pipeline is not in setup state."} というエラーがでており、恐らく上述したパイプラインはプロジェクトで一つというのが関係あるのかなと思ってます。
.circleci/config.yml
Copied!
workflows:
  client:
    jobs:
      - path-filtering/filter:
          base-revision: origin/main
          config-path: .circleci/client.yml
          mapping: |
            src/client/.* build-client true
  server:
    jobs:
      - path-filtering/filter:
          base-revision: origin/main
          config-path: .circleci/server.yml
          mapping: |
            src/server/.* build-server true

動的なコンフィグの生成

サンプルでは、circleci/path-filtering で事前に用意しておいた config を呼び出していますが、
circleci/continuation を利用することで、動的に生成した config の呼び出しも可能です。

Copied!
version: 2.1

setup: true

orbs:
  continuation: circleci/continuation:0.1.2

jobs:
  setup:
    executor: continuation/default
    steps:
      - checkout
      - run:
          name: Generate config
          command: |
            ./generate-config.sh > generated_config.yml
      - continuation/continue:
          configuration_path: generated_config.yml

workflows:
  setup:
    jobs:
      - setup

ポイントは generate-config.sh で config を動的に生成するスクリプトなどを用意してそれを実行し、生成された config ファイルを continuation/continue で読み込み実行しています。