[GitHub Actions] GitHub Actionsでブランチ名をチェックする方法

2024-09-09 hit count image

GitHub Actionsを使ってPRを作った時、ブランチ名をチェックする方法について説明します。

概要

Gitを使ってプロジェクトを開発する際、次のリンクのようにブランチ戦略を使うことがあります。

この時、ブランチ戦略に合わせてブランチを作っているか管理が必要な時があります。

今回のブログポストでは、GitHub Actionsを使ってPRを作った時、ブランチ名をチェックする方法について説明します。

GitHub Actions

ブランチ名をチェックするGitHub Actionsを作成するために、.github/workflows/check-branch-name.ymlファイルを作成し、次のように修正します。

name: Check Branch Name

on:
  pull_request:

jobs:
  check-branch-name:
    runs-on: ubuntu-latest
    timeout-minutes: 1
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
      - name: Extract branch and service name
        id: extract_branch_and_service_name
        run : |
          FULL_BRANCH_NAME=$

          BRANCH_NAME=""
          SERVICE_NAME=""

          if [[ $FULL_BRANCH_NAME == "main" || $FULL_BRANCH_NAME == "develop" ]]; then
            BRANCH_NAME="$FULL_BRANCH_NAME"
            SERVICE_NAME="$FULL_BRANCH_NAME"
          else
            # Split the branch name by "/"
            IFS='/' read -ra BRANCH_PARTS <<< "$FULL_BRANCH_NAME"

            # Check if the length of the array is greater than 1
            if [ "${#BRANCH_PARTS[@]}" -gt 1 ]; then
              # Assign the second part as the service name
              BRANCH_NAME=${BRANCH_PARTS[0]}
              SERVICE_NAME=${BRANCH_PARTS[1]}
            else
              # If the length is 1, raise an error
              echo "[Error] Branch name does not contain a valid service name."
              echo "Please check the branch name and try again."
              echo "You can change the branch name by running the following command:"
              echo "git branch -m <new-branch-name>"
              exit 1
            fi
          fi

          echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
          echo "SERVICE_NAME=$SERVICE_NAME" >> $GITHUB_ENV
          echo "FULL_BRANCH_NAME=$FULL_BRANCH_NAME" >> $GITHUB_ENV
      - name: Check Branch Name
        run: |
          BRANCH_NAMES=("dependabot" "hotfix" "release" "review" "feature" "fix" "sub-feature")
          SERVICE_NAMES=("npm_and_yarn" "github_actions" "SERVICE_1" "SERVICE_2" "template" "components" "config" "common")

          if [[ $BRANCH_NAME == "main" || $BRANCH_NAME == "develop" ]]; then
            echo "Branch name is valid."
          elif printf '%s\n' "${BRANCH_NAMES[@]}" | grep -qx "${BRANCH_NAME}" && printf '%s\n' "${SERVICE_NAMES[@]}" | grep -qx "${SERVICE_NAME}"; then
            echo "Branch name is valid."
          else
            echo "[Error] Branch name must contain valid branch names and service names."
            echo "- Current branch: $BRANCH_NAME"
            echo "- Branch names: main develop ${BRANCH_NAMES[@]}"
            echo "- Service names: ${SERVICE_NAMES[@]}"
            exit 1
          fi

このGitHub Actionsをもっと見てみましょう。

私はモノレポでプロジェクトを管理しています。

そのため、次のようなブランチ名を使っています。

feature/:SERVICE_NAME/:BRANCH_NAME
release/:SERVICE_NAME/:BRANCH_NAME
fix/:SERVICE_NAME/:BRANCH_NAME
...

この時、ブランチ名がdependabothotfixreleasereviewfeaturefixsub-featureなどで始まっているか確認し、SERVICE_NAMEを抽出して事前に定義した名前を使っているか確認しています。

なので、次のようにサービス名とブランチ名を事前に抽出して環境変数に保存しています。

...
      - name: Extract branch and service name
        id: extract_branch_and_service_name
        run : |
          FULL_BRANCH_NAME=$

          BRANCH_NAME=""
          SERVICE_NAME=""

          if [[ $FULL_BRANCH_NAME == "main" || $FULL_BRANCH_NAME == "develop" ]]; then
            BRANCH_NAME="$FULL_BRANCH_NAME"
            SERVICE_NAME="$FULL_BRANCH_NAME"
          else
            # Split the branch name by "/"
            IFS='/' read -ra BRANCH_PARTS <<< "$FULL_BRANCH_NAME"

            # Check if the length of the array is greater than 1
            if [ "${#BRANCH_PARTS[@]}" -gt 1 ]; then
              # Assign the second part as the service name
              BRANCH_NAME=${BRANCH_PARTS[0]}
              SERVICE_NAME=${BRANCH_PARTS[1]}
            else
              # If the length is 1, raise an error
              echo "[Error] Branch name does not contain a valid service name."
              echo "Please check the branch name and try again."
              echo "You can change the branch name by running the following command:"
              echo "git branch -m <new-branch-name>"
              exit 1
            fi
          fi

          echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
          echo "SERVICE_NAME=$SERVICE_NAME" >> $GITHUB_ENV
          echo "FULL_BRANCH_NAME=$FULL_BRANCH_NAME" >> $GITHUB_ENV
...

このように抽出したブランチ名とサービス名を使って、次のようにブランチ名とサービス名が有効か確認しています。

...
      - name: Check Branch Name
        run: |
          BRANCH_NAMES=("dependabot" "hotfix" "release" "review" "feature" "fix" "sub-feature")
          SERVICE_NAMES=("npm_and_yarn" "github_actions" "SERVICE_1" "SERVICE_2" "template" "components" "config" "common")

          if [[ $BRANCH_NAME == "main" || $BRANCH_NAME == "develop" ]]; then
            echo "Branch name is valid."
          elif printf '%s\n' "${BRANCH_NAMES[@]}" | grep -qx "${BRANCH_NAME}" && printf '%s\n' "${SERVICE_NAMES[@]}" | grep -qx "${SERVICE_NAME}"; then
            echo "Branch name is valid."
          else
            echo "[Error] Branch name must contain valid branch names and service names."
            echo "- Current branch: $BRANCH_NAME"
            echo "- Branch names: main develop ${BRANCH_NAMES[@]}"
            echo "- Service names: ${SERVICE_NAMES[@]}"
            exit 1
          fi
...

ブランチ名の変更

このGitHub Actionsを使って、事前に定義した規則に合わないブランチ名でPRを作成するとエラーが発生します。この時は次のようにブランチ名を変更します。

git checkout <current-branch-name>
git branch -m <new-branch-name>

また、次のように変更することができます。

git branch -m <current-branch-name> <new-branch-name>

このようにブランチ名を変更した場合、新しいPRを作成し、古いPRを閉じる必要があります。

Git hooks

間違ったブランチ名を使った場合、このGitHub Actionsで確認が可能ですが、PRを作成しないと確認ができません。また、ブランチ名が間違っている場合は、既存のPRを閉じて新しいPRを作成する必要があります。

このような場合、Git hooksを使うとPRを作成する前にブランチ名を確認することができて、不要な作業を減らすことができます。

ブランチ名の確認scriptの作成

ブランチ名を確認するscriptを作成するために、scripts/check-branch-name.shファイルを作成し、次のように修正します。

#!/usr/bin/env sh

pattern='^(dependabot|hotfix|release|review|feature|fix|sub-feature)/(npm_and_yarn|github_actions|SERVICE_1|SERVICE_2|template|components|config|common)/.*'
errorMessage='Invalid branch name. Please follow the correct naming convention.'

if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  echo "Error: Not inside Git working tree."
  exit 1
fi

branches=$(git branch | grep '^\*' | sed 's/^\* //')

if echo "$branches" | grep -Eq "$pattern"; then
  printf "\033[32mPassed\nBranch Name: %s\nPattern: %s\033[0m\n" "$branches" "$pattern"
else
  printf "\033[31mResult: failed\nError Msg: %s\nBranch Name: %s\nPattern: %s\033[0m\n" "$errorMessage" "$branches" "$pattern"
  echo "$errorMessage"
  exit 1
fi

Huskyの設定

Huskyを使ってGit hooksを設定する場合、次のように.husky/pre-commitファイルを修正します。

# Run validation branch name
. "$(dirname -- "$0")/scripts/validateBranchName.sh"

# Run lint-staged
yarn lint-staged

この時、先に作成したcheck-branch-name.shファイルは.husky/scripts/validateBranchName.shに移動させる必要があります。

Lefthookの設定

Lefthookを使ってGit hooksを設定する場合、次のように.lefthook.ymlファイルを修正します。

pre-push:
  scripts:
    "validateBranchName.sh":
      runner: bash

この時、先に作成したcheck-branch-name.shファイルは.lefthook/pre-commit/validateBranchName.shに移動させる必要があります。

完了

これでGitHub Actionsを使ってPRを作った時、ブランチ名をチェックする方法について説明しました。また、Git hooksを使ってPRを作成する前にブランチ名を確認する方法についても説明しました。

もし、私のようにプロジェクトでブランチ名が重要な役割を果たす場合は、このGitHub ActionsとGit hooksを使ってブランチ名を確認してみてください。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。

Posts