【GitHub Actions】編集されたディレクトリに応じてラベルを付与する
はじめに
最近になってTerraformを触る機会が少し増えてきました。そのリポジトリはdevelopment, staging, productionのそれぞれのディレクトリがありました。
.
└── environments
├── development
│ ├── main.tf
│ └── xxx.tf
├── staging
│ ├── main.tf
│ └── xxx.tf
└── production
├── main.tf
└── xxx.tf
この構成では環境ごとに別々のPRが立てられます。その中で自分がレビューしている、または出しているPRがいったいどの環境のものなのかわからなくなることがよくありました。そのためGitHub Actionsを活用して自動で環境ラベルを貼るようにしました。
実装方法
特定のディレクトリに変更があった際にActionを実行したいときは、多くの場合GitHub Actionのpathフィルターを活用することで実現ができると思います。
今回の目的は「PRで編集されたディレクトリに応じてラベルが付与された状態にする」です。これには2つの要件があります。
- 特定のディレクトリ配下のファイルが編集されていた場合、ラベルを付与する
- 特定のディレクトリ配下のファイルが編集されなくなった場合、ラベルを削除する
pathフィルターでは、2つ目の要件を達成できないとは言いませんが煩雑になってしまいます。そのため今回は別の方法を考えます。
Labelerを使う
一番お手軽に実現ができるのは、Labeler Actionを使う方法です。
Readmeや、記事が多くあるのでこちらを使う場合は別の記事を参照してください。
今回はもう少し細かいstepのカスタマイズなどをしたいため、こちらのActionは使いませんでした。
もうちょっと自分でカスタムできるようにする
まずはファイルの変更検知が必要です。paths-filter Actionを利用しました。
変更を検知して、ラベルを付与したいディレクトリをmatrixとして以下のように利用できます。
name: Detect Changes
on:
pull_request:
types:
- opened
- synchronize
workflow_dispatch:
jobs:
detect:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
env: [development, staging, production]
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
env:
- 'environments/${{ matrix.env }}/**'
- name:
if: steps.changes.outputs.env == 'true'
# environments/${{ matrix.env }} 配下のファイルが変更されたときの処理
development, staging, productionの3つの環境において、並列にjobを実行します。path-filter Actionを使うと、ステップ単位でファイルの変更の有無を参照できます。
次に必要なのはラベルの付与、削除です。今回はghコマンドを使用しました。
# 省略
env:
GITHUB_REPO: ${{ github.repository }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.number }}
# 中略
- name: add label
if: steps.changes.outputs.env == 'true'
run: |
gh pr edit "$PR_NUMBER" --add-label ${{ matrix.env }}
- name: remove label
if: steps.changes.outputs.env == 'false'
run: |
gh pr edit "$PR_NUMBER" --remove-label ${{ matrix.env }}
このコマンドでは、ラベルが事前に存在していない場合はfailします。development, staging, productionというラベルを作成しておきました。
ghコマンドを利用することで簡単にラベルが付与できます。環境変数を適切に渡してあげてください。複数のstepで利用するため、jobに対して環境変数を定義しておきました。
最終的にできたもの
こちらになります
name: Environment Label
on:
pull_request:
types:
- opened
- synchronize
workflow_dispatch:
jobs:
label:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
env: [development, staging, production]
env:
GITHUB_REPO: ${{ github.repository }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.number }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
env:
- 'environments/${{ matrix.env }}/**'
- name: add label
if: steps.changes.outputs.env == 'true'
run: |
gh pr edit "$PR_NUMBER" --add-label ${{ matrix.env }}
- name: remove label
if: steps.changes.outputs.env == 'false'
run: |
gh pr edit "$PR_NUMBER" --remove-label ${{ matrix.env }}
個人的には結構簡潔に書けて満足です。
応用してみる
ラベルが付与されたらSlack通知する
こんな感じで拡張できます。
# 省略
- name: add label
if: steps.changes.outputs.env == 'true'
run: |
gh pr edit "$PR_NUMBER" --add-label ${{ matrix.env }}
- name: Post to a Slack channel
if: steps.changes.outputs.env == 'true'
uses: slackapi/slack-github-action@v2.0.0
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: "howdy <@channel>!"
- name: remove label
if: steps.changes.outputs.env == 'false'
run: |
gh pr edit "$PR_NUMBER" --remove-label ${{ matrix.env }}
Discussion