TerraformのCI/CDパイプラインを構築しよう
このハンズオンでは、Terraformのインフラコードに対してCI/CDパイプラインを構築し、コードレビューとデプロイの自動化を実際にハンズオン形式で手を動かしながら体験します。
- Terraformコードを管理するGitHubリポジトリを準備する
- Pull Request時に
terraform fmtとterraform planを自動実行するワークフローを構築する - Plan結果をPull Requestのコメントに自動投稿するようにする
- マージ時に
terraform applyを自動実行するワークフローを構築する - OIDCを使ってGitHub ActionsからAWSに安全に接続する
1. 事前準備
このハンズオンでは、Infra as a Code章の内容を前提としています。まだ修了していない場合は、先に修了してください。
関連講座: Infra as a Code:この章で学べること
Gitの基礎知識を習得していることを前提とします。自信のない方は先に以下の講座を実施してください。
また、以下のツールやアカウントが必要です。まだ準備できていない場合は、リンク先の手順に沿って準備をお願いします。
2. ハンズオンの概要
コンテナのビルドとデプロイを自動化しようでは、アプリケーションコードに対するCI/CDパイプラインを構築しました。このハンズオンでは、インフラコード(Terraform)に対するCI/CDパイプラインを構築します。
インフラコードもアプリケーションコードと同様に、変更のたびにレビューと検証を行い、安全にデプロイすることが重要です。
ローカル環境から手動でterraform applyを行おうとすると、以下のような問題が発生するリスクがあります。
- 実行する人のTerraformのバージョンや環境設定によって、適用結果が変わってしまう
- コマンド等の操作ミスで誤ったリソースが作成される
- 誰がどのように更新したかが把握できない
Terraformの実行にもCI/CDパイプラインを導入することで、こうしたリスクを抑えられます。
2.1 構築するパイプライン
今回は2つのワークフローを作成します。
ワークフロー1: Pull Request時(チェック)
Pull Requestが作成・更新されたタイミングで、以下の処理を自動実行します。
terraform fmt -check— コードのフォーマットが統一されているかをチェックするterraform init— プロバイダやモジュールを初期化するterraform validate— 構文を検証するterraform plan— 変更内容をプレビューする- Plan結果をPull Requestにコメントとして投稿する
レビュアーは、Pull Requestの画面上でPlan結果を確認し、意図した変更かどうかを判断できます。
ワークフロー2: マージ時(適用)
Pull Requestがマージされた(mainブランチにPushされた)タイミングで、以下の処理を自動実行します。
terraform init— プロバイダやモジュールを初期化するterraform apply -auto-approve— 変更を自動適用する
2.2 対象のTerraform構成
今回は、TerraformでシンプルなAWS構成を作ろうと同等のシンプルなAWS構成をCI/CDパイプラインの対象とします。Terraformコードの詳細な説明は省略しますので、内容を確認したい場合は該当の講座に記載があります。
3. リポジトリの準備
3.1 リポジトリの作成
まず、Terraformコードを管理するGitHubリポジトリを作成します。
GitHubにログインし、画面右上の「+」ボタンから「New repository」を選択します。表示されたフォームで、以下の内容を設定してください。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| Repository name | terraform-cicd-handson | 本ハンズオン用のリポジトリ名として使用する |
| Choose visibility | Public | 誰でも閲覧できる公開リポジトリにする |
| Start with a template | No template | テンプレートは利用しない |
| Add README | On(トグルを有効化) | mainブランチをREADME.mdと初期コミットで初期化し、以降の作業はすべてPR経由で行えるようにする |
| Add .gitignore | No .gitignore | 追加しない |
| Add license | No license | 追加しない |

設定を確認したら「Create repository」をクリックしてリポジトリを作成します。作成が完了すると、README.mdだけを含む初期コミットが入った状態のリポジトリが表示されます。

続いて、作成したリポジトリをローカル環境にクローンします。任意のフォルダに移動して、以下のコマンドを実行してください。
git clone https://github.com/<your-github-account-name>/terraform-cicd-handson.git
<your-github-account-name>はご自身のGitHubアカウント名に置き換えてください。
クローンしたら、Visual Studio Codeでterraform-cicd-handsonフォルダを開きます。「ファイル」→「フォルダーを開く」から、クローンしたフォルダを選択してください。
エクスプローラーにterraform-cicd-handsonフォルダが表示されていれば、リポジトリの準備は完了です。
3.2 Terraformコードの配置
CI/CDパイプラインの対象となるTerraformコードを配置します。今回はTerraformでシンプルなAWS構成を作ろうと同等の内容を使うため、zipファイルで配布します。
以下からzipをダウンロードし、展開して出てくる3つのファイルを、先ほどクローンしたterraform-cicd-handsonフォルダ直下(README.mdと同じ階層)に配置してください。
配置すると、以下のようなファイル構成になります。
terraform-cicd-handson/
├── README.md
├── main.tf ← ダウンロードしたファイル
├── variables.tf ← ダウンロードしたファイル
└── terraform.tfvars ← ダウンロードしたファイル
Terraformのコードに関する解説は省略しますが、今回作成するAWSリソースは以下のとおりです。
| リソース | 内容 |
|---|---|
| VPC | 10.0.0.0/16のネットワーク空間を作成する |
| パブリックサブネット | ap-northeast-1aに10.0.1.0/24のサブネットを配置する |
| インターネットゲートウェイ | VPCをインターネットに接続する |
| ルートテーブル | パブリックサブネットからインターネットへの経路を設定する |
| セキュリティグループ | EC2に対してSSH(22)とHTTP(80)を許可する |
| EC2インスタンス | Amazon Linux 2023をt2.microで起動する |
コードの詳しい内容はTerraformでシンプルなAWS構成を作ろうに記載があります。
エクスプローラーに3つのファイルが表示されていれば、Terraformコードの配置は完了です。
3.3 CI/CD用AWSリソースの準備
CI/CDパイプラインを動かすために、以下のAWSリソースを事前に用意します。
| リソース | 内容 |
|---|---|
| S3バケット | Terraformのtfstateファイルを保存する。バージョニング・サーバサイド暗号化・パブリックアクセスブロックを有効にする |
| OIDCプロバイダ | GitHub Actionsが発行するIDトークンをAWS側で検証・信頼するために設定する |
| IAMロール | GitHub Actionsから引き受けて、Terraformが必要とするAWS操作を委譲する |
| 💡 ポイント |
|---|
| これらのリソースはTerraformでも作成できますが、他の講座に合わせてCloudFormationで作成します。tfstateバケットやIAMロールはCI/CDが動く前提となる土台のリソースなので、CI/CDパイプラインの外側で用意しておく構成にしています。 |
以下からCloudFormationテンプレートをダウンロードします。
CloudFormationのダッシュボードでスタックの作成 > 新しいリソースを使用(標準)をクリックし、スタック作成ウィザードを開きます。
ステップ1: スタックの作成
「テンプレートの準備」で既存のテンプレートを選択を、「テンプレートソース」でテンプレートファイルのアップロードを選択します。ファイルの選択からダウンロードしたtf-cicd-oidc.ymlをアップロードし、次へをクリックします。

ステップ2: スタックの詳細を指定
「スタック名」と「パラメータ」を、以下の値で入力します。
| 設定項目 | 値 | 設定の基準 |
|---|---|---|
| スタック名 | tf-cicd-oidc | ハンズオン用に分かりやすい名前をつける |
| GitHubOrg | ご自身のGitHubユーザ名(すべて小文字) | S3バケット名の一意性の確保と、どのGitHubリポジトリに信頼を委譲するかの指定に利用する |
| 💡 ポイント |
|---|
S3バケット名はグローバルで一意である必要があるため、末尾にGitHubユーザ名を付けてterraform-cicd-handson-tfstate-<GitHubユーザ名>という命名にしています。GitHubユーザ名は基本的に他の受講生とは重複しないため、これで衝突を回避できます。S3バケット名は小文字のみ利用可能なため、GitHubユーザ名に大文字を含む場合はすべて小文字に変換して入力してください。 |
入力できたら次へをクリックします。

ステップ3: スタックオプションの設定
そのまま画面を下にスクロールし、「機能」セクションのAWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。にチェックを入れて次へをクリックします。
| 💡 ポイント |
|---|
今回はハンズオンの簡略化のためIAMロールにAdministratorAccessを付与していますが、本番環境では必要最小限の権限に絞ることが推奨されます。 |

ステップ4: 確認して作成
内容を確認して、最下部の送信をクリックしてスタックを作成します。

スタックの作成完了確認
スタックのステータスがCREATE_COMPLETEになったら、出力タブにGitHubActionsRoleArn・AWSAccountId・TfStateBucketNameの3つが表示されていることを確認します。

main.tfのbucket名の置き換え
続いて、CloudFormationで作成したtfstateバケットの名前をmain.tfにも反映します。VS Codeでmain.tfを開き、backend "s3"ブロックのbucketの<your-github-username>を、GitHubユーザ名(すべて小文字)に置き換えて保存してください。
以下は、GitHubユーザ名がyamadaの場合の書き換え例です。
backend "s3" {
bucket = "terraform-cicd-handson-tfstate-yamada"
key = "terraform.tfstate"
region = "ap-northeast-1"
use_lockfile = true
}
main.tfのbucketがCloudFormationで作成したバケット名と一致していれば、CI/CD用AWSリソースの準備は完了です。次のステップでAWSAccountIdの値を利用します。
3.4 シークレットの登録
GitHub ActionsからAWSに接続する際は、引き受けるIAMロールのARNをワークフロー内で組み立てる必要があります。ARNの構成要素であるAWSアカウントIDをリポジトリのシークレットに登録しておきます。
GitHubリポジトリのSettings > Secrets and variables > Actionsを開き、New repository secretをクリックして以下のシークレットを登録します。
| シークレット名 | 値 | 設定の基準 |
|---|---|---|
| AWS_ACCOUNT_ID | CloudFormation出力のAWSAccountId |
GitHub Actionsから引き受けるIAMロールのARNを組み立てるために利用する |
Repository secretsの一覧にAWS_ACCOUNT_IDが表示されていれば、登録は完了です。

配置したTerraformコードはmainブランチには直接Pushせず、次のセクションで作成するチェック用ワークフローと同じPull Requestで一緒にmainブランチへ投入します。PRのterraform plan結果に、TerraformコードそのものとCI/CDワークフローが新規追加として表示され、何がAWSに反映されるかを一目で確認できるようにするためです。
4. チェック用ワークフローの作成(PR時)
Pull Request時にterraform fmt・validate・planを実行し、結果をPRのコメントに投稿するワークフローを作成します。
4.1 ワークフローファイルの作成
Visual Studio Codeのエクスプローラーでterraform-cicd-handsonフォルダを右クリックし、「新しいフォルダー」から.github/workflowsを作成し、その中にterraform-plan.ymlを作成します。
terraform-cicd-handson/
├── README.md
├── main.tf
├── variables.tf
├── terraform.tfvars
└── .github/
└── workflows/
└── terraform-plan.yml ← このファイルを作成
作成したファイルに以下の内容を記述して保存します。
name: Terraform Plan
on:
pull_request:
branches:
- main
permissions:
id-token: write
contents: read
pull-requests: write
env:
AWS_REGION: ap-northeast-1
TF_VERSION: "1.12"
jobs:
terraform-plan:
name: Terraform Plan
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v5
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/tf-cicd-handson-github-actions-role
aws-region: ${{ env.AWS_REGION }}
- name: Terraform Format Check
id: fmt
run: terraform fmt -check -recursive
continue-on-error: true
- name: Terraform Init
run: terraform init
- name: Terraform Validate
id: validate
run: terraform validate
- name: Terraform Plan
id: plan
run: terraform plan -no-color -input=false
continue-on-error: true
- name: Post Plan to PR
uses: actions/github-script@v7
with:
script: |
const fmtOutcome = '${{ steps.fmt.outcome }}';
const validateOutcome = '${{ steps.validate.outcome }}';
const planOutcome = '${{ steps.plan.outcome }}';
const planOutput = `${{ steps.plan.outputs.stdout }}`.slice(0, 60000);
const body = `### Terraform Plan 結果
| チェック | 結果 |
|---------|------|
| 📝 Format | \`${fmtOutcome}\` |
| ✅ Validate | \`${validateOutcome}\` |
| 📋 Plan | \`${planOutcome}\` |
<details>
<summary>Plan 詳細(クリックで展開)</summary>
\`\`\`
${planOutput}
\`\`\`
</details>`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
- name: Check Results
if: steps.fmt.outcome == 'failure' || steps.plan.outcome == 'failure'
run: exit 1
コードを解説します。
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
hashicorp/setup-terraformアクションで、指定したバージョンのTerraformをランナー環境にインストールしています。
- name: Terraform Format Check
id: fmt
run: terraform fmt -check -recursive
continue-on-error: true
terraform fmt -checkはコードのフォーマットが統一されているかをチェックします。-recursiveでサブディレクトリも対象にします。continue-on-error: trueを指定しているため、フォーマットが崩れていてもワークフローは続行し、最後のステップで結果をまとめて判定します。
- name: Terraform Plan
id: plan
run: terraform plan -no-color -input=false
continue-on-error: true
terraform planで変更内容をプレビューします。-no-colorはANSIカラーコードを除去してコメントに投稿しやすくするオプションです。-input=falseは対話入力を無効にします。
- name: Post Plan to PR
uses: actions/github-script@v7
actions/github-scriptを使って、Plan結果をPull Requestのコメントとして投稿しています。レビュアーはGitHubの画面上でPlan結果を確認でき、どのリソースが追加・変更・削除されるかを把握したうえでレビューできます。
- name: Check Results
if: steps.fmt.outcome == 'failure' || steps.plan.outcome == 'failure'
run: exit 1
最後に、fmtまたはplanが失敗していた場合はワークフロー全体を失敗させます。保護ブランチのステータスチェックと組み合わせることで、問題のあるコードのマージを防止できます。
4.2 動作確認
作成したチェック用ワークフローが正しく動作するかを、実際にPull Requestを作成して確認します。今回のPull Requestで、配置したTerraformコード(main.tf・variables.tf・terraform.tfvars)とチェック用ワークフロー(terraform-plan.yml)をまとめてmainブランチに投入します。
作業用のブランチを作成します。
git switch -c feature/add-cicd-pipeline
追加したファイルをまとめてステージングします。
git add .
コミットします。
git commit -m "add terraform code and plan workflow"
Pushします。
git push origin feature/add-cicd-pipeline
GitHubのリポジトリ画面を開き、Compare & pull request(表示されない場合はPull requestsタブからNew pull request)をクリックします。baseにmain、compareにfeature/add-cicd-pipelineを選択し、Create pull requestをクリックしてPull Requestを作成します。
Pull Requestが作成されると、下部のChecksセクションにTerraform Plan / Terraform Plan (pull_request)のチェックが表示され、ワークフローが自動的に実行されはじめます。

しばらく待つと、github-actionsボットからPlan結果のコメントがPull Requestに投稿されます。コメントの上部の表には、以下の3項目の結果が表示されます。
- 📝 Format: フォーマットチェックの結果を表示する(success / failure)
- ✅ Validate: 構文検証の結果を表示する(success / failure)
- 📋 Plan:
terraform planの実行結果を表示する(success / failure)

表の下の**Plan 詳細(クリックで展開)**を開くと、terraform planの出力全文を確認できます。今回のPull Requestで新規に追加されるTerraformコードが対象となり、VPC・サブネット・インターネットゲートウェイ・ルートテーブル・セキュリティグループ・EC2のリソースがto addとして表示されます。
Plan結果のコメントがPull Requestに投稿されており、Format・Validate・Planがすべてsuccessになっていれば、チェック用ワークフローの動作確認は完了です。次の適用ワークフローの動作確認でも同じPull Requestを利用するため、マージはまだ行わずに開いたままにしておきます。
5. 適用ワークフローの作成(マージ時)
mainブランチにマージされたタイミングでterraform applyを自動実行するワークフローを作成します。
5.1 ワークフローファイルの作成
Visual Studio Codeのエクスプローラーで.github/workflowsフォルダを右クリックし、「新しいファイル」からterraform-apply.ymlを作成します。
terraform-cicd-handson/
├── README.md
├── main.tf
├── variables.tf
├── terraform.tfvars
└── .github/
└── workflows/
├── terraform-plan.yml
└── terraform-apply.yml ← このファイルを作成
作成したファイルに以下の内容を記述して保存します。
name: Terraform Apply
on:
push:
branches:
- main
permissions:
id-token: write
contents: read
env:
AWS_REGION: ap-northeast-1
TF_VERSION: "1.12"
jobs:
terraform-apply:
name: Terraform Apply
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v5
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/tf-cicd-handson-github-actions-role
aws-region: ${{ env.AWS_REGION }}
- name: Terraform Init
run: terraform init
- name: Terraform Apply
run: terraform apply -auto-approve -input=false
コードを解説します。
- name: Terraform Apply
run: terraform apply -auto-approve -input=false
terraform apply -auto-approveは確認プロンプトなしで変更を適用します。CI/CDパイプラインでは対話操作ができないため、-auto-approveを指定して自動で適用を実行します。Pull Requestのレビューで変更内容を確認済みであるため、マージされた時点で安全に適用できるという考え方です。
5.2 動作確認
作成した適用ワークフローが正しく動作するかを、チェック用ワークフローの動作確認で作成したPull Requestに追加コミットし、マージして確認します。
同じfeature/add-cicd-pipelineブランチ上で作業していることを確認し、作成したterraform-apply.ymlをステージングします。
git add .github/workflows/terraform-apply.yml
コミットします。
git commit -m "add terraform apply workflow"
Pushします。
git push origin feature/add-cicd-pipeline
Pull Requestの画面をリロードすると、追加コミットが取り込まれてTerraform Planワークフローが再度実行されます。Plan結果のコメントが新しく投稿されることを確認したら、下部のチェック欄がAll checks have passedになっていることを確認し、Merge pull request > Confirm mergeをクリックしてマージします。

マージするとmainブランチが更新され、Terraform Applyワークフローが自動実行されます。GitHubのActionsタブを開き、Terraform Applyのワークフロー実行を選択すると、Terraform Applyジョブが実行中(Status: In progress)で表示されます。

しばらく待ち、StatusがSuccessになれば、terraform applyがCI/CD経由で実行されています。

続いて、AWSマネジメントコンソールでリソースが作成されていることを確認します。EC2のダッシュボードを開き、tf-cicd-ec2という名前のEC2インスタンスを選択します。詳細ペインでインスタンスの状態が「実行中」になっていれば、terraform applyによってTerraformコードで定義したリソースが作成されています。

ローカル環境もmainブランチに戻して最新化しておきます。
git switch main
git pull origin main
EC2インスタンスが作成されており、ローカルのmainブランチも最新になっていれば、適用ワークフローの動作確認は完了です。
6. 変更のテスト
CI/CDパイプラインが正しく動作することを、Terraformコードに小さな変更を加えて最後まで通しで確認します。ここでは、EC2インスタンスにEnvironmentタグを追加してみましょう。
main.tfのEC2インスタンス(aws_instance.web)のtagsブロックに、Environment = "test"の1行を追加します。
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.ec2.id]
tags = {
Name = "${var.prefix}-ec2"
Environment = "test"
}
}
変更用のブランチを作成します。
git switch -c feature/add-environment-tag
変更をステージングします。
git add main.tf
コミットします。
git commit -m "add Environment tag to EC2"
Pushします。
git push origin feature/add-environment-tag
GitHubでPull Requestを作成すると、Plan結果のコメントにPlan: 0 to add, 1 to change, 0 to destroy.が表示されます。**Plan 詳細(クリックで展開)**を開くと、EC2インスタンス(aws_instance.web)のtagsにEnvironment = "test"が追加される差分が表示されます。

Plan結果を確認したら、Merge pull request > Confirm mergeをクリックしてマージします。Actionsタブを開き、Terraform ApplyワークフローのStatusがSuccessになっていれば、変更がAWSに反映されています。

AWSマネジメントコンソールでEC2のダッシュボードを開き、tf-cicd-ec2インスタンスを選択します。画面下部の詳細ペインでタグタブを開き、Environmentにtestが追加されていれば、CI/CDパイプラインが最後まで通しで動作していることが確認できます。

7. リソースの削除
最後に、本ハンズオンで作成したリソースをすべて削除します。CI/CDパイプラインを構築したので、Terraformで作成したリソースの削除もPull Requestのマージで実行します。
7.1 Terraformリソースの削除
先にローカル環境をmainブランチに戻し、最新の状態にしておきます。
git switch main
git pull origin main
次に、main.tfからリソース定義(resourceブロックとdataブロック)をすべて削除します。terraformブロック・providerブロックはバックエンド設定として次回のapply時にも必要なため、そのまま残してください。variables.tfとterraform.tfvarsは触りません。
削除後のmain.tfは以下のようになります(GitHubユーザ名がyamadaの場合の例)。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "terraform-cicd-handson-tfstate-yamada"
key = "terraform.tfstate"
region = "ap-northeast-1"
use_lockfile = true
}
}
provider "aws" {
region = var.aws_region
}
削除用のブランチを作成します。
git switch -c feature/destroy-resources
変更をステージングします。
git add main.tf
コミットします。
git commit -m "remove all resources for cleanup"
Pushします。
git push origin feature/destroy-resources
GitHubでPull Requestを作成すると、Plan結果のコメントにPlan: 0 to add, 0 to change, 7 to destroy.が表示され、これまでに作成したAWSリソース(VPC・サブネット・IGW・ルートテーブル・ルートテーブル関連付け・セキュリティグループ・EC2の7つ)がすべて削除対象になっていることが確認できます。
Plan結果を確認したら、Merge pull request > Confirm mergeをクリックしてマージします。適用ワークフローが実行され、terraform applyによってAWSリソースがすべて削除されます。
ActionsタブでTerraform ApplyワークフローがSuccessになり、EC2ダッシュボードでtf-cicd-ec2が、VPCダッシュボードでtf-cicd-vpcが表示されなくなっていれば、Terraformリソースの削除は完了です。
7.2 tfstateバケットの中身の削除
S3のダッシュボードを開き、terraform-cicd-handson-tfstate-<GitHubユーザ名>バケットを選択します。CloudFormationスタックを削除する前に、バケット内のオブジェクト(tfstateファイル)を空にしておく必要があります。空にするをクリックし、指示に従ってバケットの中身をすべて削除してください。
7.3 CloudFormationスタックの削除
CloudFormationのダッシュボードを開き、tf-cicd-oidcスタックを選択して削除をクリックします。ステータスがDELETE_COMPLETEになれば、tfstateバケット・OIDCプロバイダ・IAMロールがまとめて削除されます。
すべてのステータスが完了になっていれば、リソースの削除は完了です。
8. まとめ
このハンズオンでは、TerraformのインフラコードをCI/CDパイプラインで管理する仕組みを構築しました。
- Pull Request時に
terraform fmt・validate・planを自動実行し、コードの品質と変更内容を事前に確認できるようにした - Plan結果をPull Requestのコメントに自動投稿することで、レビュアーがGitHub上で変更内容を確認できるようにした
- マージ時に
terraform applyを自動実行し、レビュー済みの変更を安全にAWSへ適用できるようにした - OIDCを使ってGitHub ActionsからAWSに接続することで、アクセスキーの管理を不要にした
- インフラの変更もアプリケーションコードと同様に、コードレビュー→自動検証→自動デプロイのフローで運用できるようにした