CircleCIでリポジトリ内でのフロントエンドとバックエンドを分けたCI/CD環境構築

本記事は [株式会社ACCESS Advent Calendar 2023](https://qiita.com/advent-calendar/2023/access) の23日目の記事です。

お久しぶりです。
一年に一回 Qiita へ寄稿する @Momijinn です。

あるプロジェクトで CircleCI を使った CI/CD を構築しました。
そのときにちょっとめんどくさい自体になったので解決方法を書いていこうと思います。　

## 問題になったこと

ひとつのリポジトリに バックエンド と フロントエンド が混在(フォルダでわけているような感じ)していました。

バックエンドのPRの場合はバックエンドの CI/CD を行い、 フロントエンドのPRの場合は フロントエンドの CI/CD を行いたいです。

単純に CI/CD を実装してしまうと、上記のことができない自体になりました。

## やりたいこと

* バックエンド側のコードが変更されたら **バックエンドのみ** の CI/CD を実行する。
* フロントエンド側のコードが変更されたら **フロントエンドのみ** の CI/CD を実行する。
* バックエンドとフロントエンドの両方が変更されたら **バックエンドとフロントエンド** の CI/CD を実行する。

## ざっくりした結論

`circleci/path-filtering@1.0.0` という orb をつかうといい感じにできました。
変更があったフォルダを探索してそれに応じた yml ファイル（CI）を実行するものになります。
しかし、ちょっと設定が面倒だったです。

c.f. https://circleci.com/developer/orbs/orb/circleci/path-filtering

## やり方

### 前提

以下のようなフォルダ構成とします。

```bash
- project
   |- .circleci
   |    |- config.yml # ci の setup みたいなやつ。はじめにこれが実行されてどこに変更があるか確認するCIが実行される。
   |    |- continue_config.yml # ダミー。名前の命名規則は決まっていたはず。backend と frontend の両方で変更がなかった場合に実行される。
   |    |- workflows
   |         |- backend.yml  # backendで実行したCI
   |         |- frontend.yml # frontendで実行したいCI
   |
   | - backend # backendのコードが入っているフォルダ
   | - frontend # frontendのコードが入っているフォルダ
```

### 準備

CircleCI の設定画面から `Enable dynamic config using setup workflows` を有効にする。

| Enable dynamic config using setup workflows |
| --- |
| ![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96450/58f0005b-2da2-b62b-cb60-5a1d800998ba.png) |

### 実装

#### config.yml

```yml
version: 2.1

setup: true

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

workflows:
  generate-config:
    jobs:
      - path-filtering/filter:
          base-revision: main
          mapping: |
            backend/.* run-backend-ci true .circleci/workflows/backend.yml # backend/ 以下に変更があったら .circleci/workflows/backend.yml を実行する
            frontend/.* run-frontend-ci true .circleci/workflows/frontend.yml # frontend/ 以下に変更があったら .circleci/workflows/frontend.yml を実行する
```

#### continue_config.yml

バックエンド側とフロントエンド側のコードで変更がない( `./backend` と `/frontend` のフォルダ以外のファイル変更がないPR )　ときに動く CI/CD ファイル。

これがないとエラーが起こる。

```yml
version: 2.1

parameters: # フラグ。おまじないとおもってよい。
  run-backend-ci:
    type: boolean
    default: false
  run-frontend-ci:
    type: boolean
    default: false

jobs:
  dummy-job:
    resource_class: small
    docker:
      - image: cimg/base:2023.07
    steps:
      - run: exit 0

workflows:
  dummy-workflow:
    jobs:
      - dummy-job
```

#### backend.yml

バックエンド用の CI/CD 実行ファイル。

`Hello, backend!` と出力するだけのやつ。

```yml
version: 2.1

parameters: # おまじない
  run-backend-ci:
    type: boolean
    default: false

jobs:
  backend-job:
    resource_class: small
    docker:
      - image: cimg/base:2023.07
    steps:
      - checkout
      - run:
          working_directory: backend
          command: |
            echo "Hello, backend!"
            ls -la
workflows:
  backend-workflow:
    jobs:
      - backend-job
```

#### frontend.yml

フロントエンド用の CI/CD 実行ファイル。

`Hello, frontend!` と出力するだけのやつ。

```yml
version: 2.1

parameters: # おまじない
  run-frontend-ci:
    type: boolean
    default: false

jobs:
  frontend-job:
    resource_class: small
    docker:
      - image: cimg/base:2023.07
    steps:
      - checkout
      - run:
          working_directory: frontend
          command: |
            echo "Hello, frontend!"
            ls -la
workflows:
  frontend-workflow:
    jobs:
      - frontend-job
```

#### 注意

おそらく実態は、複数の yml を合体させてCIを実行している。
そのため、 `backend.yml` と `frontend.yml` で同じ workflow の名前を使うとエラーになる。
そのため workflow を定義する時は prefix をつけた方がよい。

## まとめ

とあるプロジェクトで CircleCI を使った CI/CD を構築したときに問題になったことの解決方法をかきました。

ひとつのリポジトリにバックエンドとフロントエンドの両方があるというものは珍しいと思いますが、もしおなじような問題に直面し CI/CD を構築することになった人がいたら参考にしていただけると嬉しいです。

とりあえず、今年もアドベントカレンダーに参加できてよかったです。
また来年。お楽しみに。