[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
...

이때 브랜치명이 dependabot, hotfixrelease, review, feature, fix, sub-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를 사용하여 브랜치명을 검사해 보시기 바랍니다.

제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!

앱 홍보

책 홍보

블로그를 운영하면서 좋은 기회가 생겨 책을 출판하게 되었습니다.

아래 링크를 통해 제가 쓴 책을 구매하실 수 있습니다.
많은 분들에게 도움이 되면 좋겠네요.

스무디 한 잔 마시며 끝내는 React Native, 비제이퍼블릭
스무디 한 잔 마시며 끝내는 리액트 + TDD, 비제이퍼블릭
[심통]현장에서 바로 써먹는 리액트 with 타입스크립트 : 리액트와 스토리북으로 배우는 컴포넌트 주도 개발, 심통
Posts