LoginSignup
1
0

【CircleCI / Monorepo】変更されたファイルに応じてworkflowを実行する

Last updated at Posted at 2023-09-04

環境

やりたいことの前提

  • Monorepo
    • 具体的には、以下のようなディレクトリがレポジトリ配下に存在し、ファイルの変更されたPATHに応じて、必要なworkflowのみを実行する。
      • frontend
      • backend
  • 管理のため、それぞれのcircle configも分ける。

CircleCI の設定の前提

ここにある通り、Enable dynamic config using setup workflowson になっていること。

上記の設定をしても、今まで通り単一の config.yml で書くことは可能。
config.yml のトップレベルで setup: true と定義することにより、上記で有効にした dynamic config using setup workflows が有効になる。

CircleCI Config ファイル構成

※分かりやすいように、前述の backend, frontend というディレクトリも記載している。

├── .circleci
│   ├── config.yml
│   ├── _base.yml # ファイル名は任意
│   ├── packages # PATH、及びその配下のファイル名は任意
│       ├── backend_config.yml
│       ├── frontend_config.yml
│
├── backend
├── frontend

各 yml ファイル

.circleci/_base.yml(ファイル名は任意)

.circleci/_base.yml
version: 2.1

orbs:

parameters:

executors:

commands:

jobs:

workflows:

.circleci/config.yml

setup: true の定義により、dynamic configuration が有効になる。

.circleci/config.yml
version: 2.1

# this allows you to use CircleCI's dynamic configuration feature
setup: true
orbs:
  path-filtering: circleci/path-filtering@1.0.0

jobs:
  merge-config:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      - run:
          name: "Generate yaml"
          # https://mikefarah.gitbook.io/yq/operators/reduce#merge-all-yaml-files-together
          command: |
            mkdir -p /tmp/workspace
            yq eval-all '. as $item ireduce ({}; . * $item )' .circleci/_base.yml .circleci/packages/*.yml > /tmp/workspace/merged.yml
            cat /tmp/workspace/merged.yml
      - persist_to_workspace:
          root:  /tmp/workspace
          paths:
            - merged.yml

workflows:
  generate-config:
    jobs:
      - merge-config
      - path-filtering/filter:
          requires:
            - merge-config
          pre-steps:
            - attach_workspace:
                at: /tmp/workspace
          base-revision: develop
          config-path: /tmp/workspace/merged.yml
          mapping: |
            backend/.* run_backend_jobs true
            frontend/.* run_frontend_jobs true

.circleci/packages/backend_config.yml

.circleci/packages/backend_config.yml
version: 2.1

parameters:
  run_backend_jobs:
    type: boolean
    default: false

executors:
  backend_default:
    working_directory: ~/repo # default: ~/project
    docker:
      - image: cimg/ruby:3.2.2
        environment:
          BUNDLER_VERSION: 2.4.15
          BUNDLE_APP_CONFIG: ~/repo/backend/.bundle
          RAILS_ENV: test

commands:
  restore_bundle_dependencies:
    steps:
      - restore_cache:
          name: Restore bundle dependencies cache
          keys:
            - v1-bundle-dependencies-{{ checksum "backend/Gemfile.lock" }}
            - v1-bundle-dependencies-
  install_bundler:
    steps:
      - run:
          name: Install bundler
          working_directory: backend
          command: gem install bundler -v $BUNDLER_VERSION
  set_bundle_config:
    steps:
      - run:
          name: Set bundle config
          working_directory: backend
          command: bundle config --local path 'vendor/bundle'
  install_bundle_dependencies:
    steps:
      - run:
          name: Install bundle dependencies
          working_directory: backend
          command: |
            bundle install --jobs=4 --retry=3
  save_bundle_dependencies:
    steps:
      - save_cache:
          key: v1-bundle-dependencies-{{ checksum "backend/Gemfile.lock" }}
          paths:
            - backend/vendor/bundle
  run_rubocop:
    steps:
      - run:
          name: Run rubocop
          working_directory: backend
          command: bundle exec rubocop

jobs:
  backend_setup:
    executor: backend_default
    steps:
      - checkout
      - restore_bundle_dependencies
      - install_bundler
      - set_bundle_config
      - install_bundle_dependencies
      - save_bundle_dependencies
      - persist_to_workspace:
          root: ~/repo
          paths:
            - backend
  backend_lint_rubocop:
    executor: backend_default
    steps:
      - attach_workspace:
          at: ~/repo
      - restore_bundle_dependencies
      - install_bundler
      - run_rubocop

workflows:
  backend:
    when: << pipeline.parameters.run_backend_jobs >>
    jobs:
      - backend_setup
      - backend_lint_rubocop:
          requires:
            - backend_setup

.circleci/packages/frontend_config.yml

.circleci/packages/frontend_config
version: 2.1

parameters:
  run_frontend_jobs:
    type: boolean
    default: false

executors:
  frontend_default:
    working_directory: ~/repo # default: ~/project
    docker:
      - image: cypress/base:18.16.1
        environment:
          YARN_CACHE_FOLDER: ~/repo/frontend/yarn_packages
          TZ: Asia/Tokyo

jobs:
  frontend_setup:
    executor: frontend_default
    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-yarn-packages-{{ checksum "frontend/yarn.lock" }}
            - v1-yarn-packages
      - restore_cache:
          keys:
            - v1-node-modules-{{ checksum "frontend/package.json" }}
            - v1-node-modules
      - run:
          name: Install yarn packages
          working_directory: frontend
          command: yarn install
      - save_cache:
          key: v1-yarn-packages-{{ checksum "frontend/yarn.lock" }}
          paths:
            - frontend/yarn_packages
            - .cache
      - save_cache:
          key: v1-node-modules-{{ checksum "frontend/package.json" }}
          paths:
            - frontend/node_modules
            - .cache
      - persist_to_workspace:
          root: ~/repo
          paths:
            - frontend
            - .cache
  frontend_lint_eslint:
    executor: frontend_default
    steps:
      - attach_workspace:
          at: ~/repo
      - run:
          name: Run eslint
          working_directory: frontend
          command: yarn run lint

workflows:
  frontend:
    when: << pipeline.parameters.run_frontend_jobs >>
    jobs:
      - frontend_setup
      - frontend_lint_eslint:
          requires:
            - frontend_setup

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0