📚

[GitHubActions]CDKTFの実行結果に応じてLablesを付与する

2025/02/09に公開

はじめに

最近転職したのでPublication経由の投稿ではなくなりました。
自身での投稿第一弾です。
今後は今の会社でも技術ブログの文化を作っていきたいと考えています。

概要

CDKTFの実行をGitHubActionsで行っています。
CDK For Terraformの実行するためのActionsは公式にあります。

  • 参考

plan結果をPullRequestにコメントしてくれたり、
設定内容に応じて作業用ディレクトリを指定できたり、
mode の指定に応じて処理内容変更してくれたりします。

これだけでも便利ではあるのですが、
plan結果に応じてLabelsを付与することで
整理しやすくなると考え、スクリプト自作しました。

ちなみにTerraformで運用している場合は
suzuki-shunsukeさんが作成されているtfcmtが便利なので
こちらがいいかと思います。

  • 参考

実装

  • add_labels.sh

処理概要: applyが0以外であればapplyラベルを付与し、
0であれば削除する。changeやdestroyも同様です。

#!/bin/bash
# PR番号とplan出力を引数として受け取る
PR_NUMBER="$1"
PLAN_OUTPUT="$2"

if echo "$PLAN_OUTPUT" | grep -q "No changes."; then
  gh pr edit "$PR_NUMBER" --add-label "nochange"
  # 変更がなければ、apply, change, destroyラベルがあれば削除する
  gh pr edit "$PR_NUMBER" --remove-label "apply"
  gh pr edit "$PR_NUMBER" --remove-label "change"
  gh pr edit "$PR_NUMBER" --remove-label "destroy"
else
  # 変更があった場合はnochangeラベルを削除する 
  gh pr edit $PR_NUMBER --remove-label "nochange"

  
  # add,change,destroyカウントの抽出
  if [[ $PLAN_OUTPUT =~ ([0-9]+)[[:space:]]+to[[:space:]]+add ]]; then
    ADD_COUNT=${BASH_REMATCH[1]}
  else
    ADD_COUNT=0
  fi
  if [[ $PLAN_OUTPUT =~ ([0-9]+)[[:space:]]+to[[:space:]]+change ]]; then
    CHANGE_COUNT=${BASH_REMATCH[1]}
  else
    CHANGE_COUNT=0
  fi
  if [[ $PLAN_OUTPUT =~ ([0-9]+)[[:space:]]+to[[:space:]]+destroy ]]; then
    DESTROY_COUNT=${BASH_REMATCH[1]}
  else
    DESTROY_COUNT=0
  fi

  # applyラベル(add)
  if [ "$ADD_COUNT" -gt 0 ]; then
    gh pr edit "$PR_NUMBER" --add-label "apply"
  else
    gh pr edit "$PR_NUMBER" --remove-label "apply"
  fi

  # changeラベル
  if [ "$CHANGE_COUNT" -gt 0 ]; then
    gh pr edit "$PR_NUMBER" --add-label "change"
  else
    gh pr edit "$PR_NUMBER" --remove-label "change"
  fi

  # destroyラベル
  if [ "$DESTROY_COUNT" -gt 0 ]; then
    gh pr edit "$PR_NUMBER" --add-label "destroy"
  else
    gh pr edit "$PR_NUMBER" --remove-label "destroy"
  fi
fi
  • GitHubActions(サンプル)

Cacheなどの設定をカスタマイズしてありますが、Stack名やワーキングディレクトリを
変更することで、他のリポジトリでも流用できると思います。

name: "Sample CDK for Terraform"
on:
   pull_request:
    branches:
     - main

    types: [opened, synchronize, reopened, closed]
    paths:
   workflow_dispatch:
#-------------------------#
# 環境変数
#-------------------------#
env:
    CDKTF_VERSION: 0.20.10
    TERRAFORM_VERSION: 1.10.5
    WORK_DIRECTORY: cdk_for_terraform
    STACK_NAME: sample



permissions:
    id-token: write
    contents: read
    pull-requests: write
    repository-projects: write
    issues: read
  

jobs:
  cdktf:
    name: "CDK For Terraform "
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Configure AWS credentials from account
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: ap-northeast-1

      - name: Cache Node.js modules
        id: cache-node-modules
        uses: actions/cache@v4
        with:
          path: ${{ env.WORK_DIRECTORY }}/node_modules
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-


      - name: Cache .gen directory
        id: cache-gen
        uses: actions/cache@v4
        with:
          path: cdk_for_terraform/.gen
          key: ${{ runner.os }}-gen-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-gen-

      - uses: actions/setup-node@v4
        with:
          node-version: "22"

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ env.TERRAFORM_VERSION }}

      - name: Install dependencies
        run: |
          cd ${{ env.WORK_DIRECTORY }} 
          make install
        if: steps.cache-node-modules.outputs.cache-hit != 'true'  

      - name: Generate module and provider bindings
        run: | 
         cd ${{ env.WORK_DIRECTORY }}
         npx cdktf-cli@${{ env.CDKTF_VERSION }} get
        if: steps.cache-gen.outputs.cache-hit != 'true'
 
      - name: Run Terraform CDK DryRun
        id: plan
        if: github.event.pull_request.merged != true
        uses: hashicorp/terraform-cdk-action@v7
        with:
          terraformVersion: ${{ env.TERRAFORM_VERSION }}
          cdktfVersion: ${{ env.CDKTF_VERSION }}
          stackName: ${{ env.STACK_NAME }}
          mode: plan-only
          githubToken: ${{ secrets.GITHUB_TOKEN }}
          workingDirectory: ${{ env.WORK_DIRECTORY }}
          suppressOutput: false # プランの出力を抑制フラグ

      # ラベル付与
      - name: Add labels based on plan
        if: github.event.pull_request.merged != true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # PR番号とplan出力を引数として渡す
          PR_NUMBER=${{ github.event.pull_request.number }}
          LABEL_OUTPUT="${{ steps.plan.outputs.stdout }}"
          ./.github/scripts/add_labels.sh "$PR_NUMBER" "$LABEL_OUTPUT"

処理イメージ

alt text

このような感じでGitHubActionsによってLabelsが付与されます。

まとめ

plan結果を人間の目で確認することも重要ではありますが、
視覚的に識別できるというのも重要と考えています。

本運用を導入することで今までplanが実行されたら必ず注意深くみていたものが
nochange lablesが付与されているものは注意深くみなくてもよくなりました。

今後の構想として特定のファイルの変更のみでトリガーされるようにすることを前提とし、
nochacngeのラベルが付与されたものを自動でマージもしくは
承認なしてもマージしてもいいような運用にしていきたいと考えています。

Discussion