커밋 메시지 자동 검사

Git Hooks와 commitlint를 이용해 작성한 커밋 메시지가 유효한지 검사할 수 있습니다.

다음 글들을 참고하시면 더 많은 정보를 얻으실 수 있습니다.

 

 

Conventional Commits | 쿡앱스 기술 블로그

Conventional Commits 본 포스팅의 완성 된 예제 소스 는 GitHub에 올려져 있습니다. 개요 Conventional Commits 이란 git 으로 commit 시에 일괄된 양식을 유지하고 그 양식을 바탕으로 버전 관리나 Change Log 를 만

blog.cookapps.io

 

 

conventional-changelog/commitlint

📓 Lint commit messages. Contribute to conventional-changelog/commitlint development by creating an account on GitHub.

github.com

Git Hooks

 

 

Git - Git Hooks

It’s important to note that client-side hooks are not copied when you clone a repository. If your intent with these scripts is to enforce a policy, you’ll probably want to do that on the server side; see the example in An Example Git-Enforced Policy.

git-scm.com

프로젝트의 .git 폴더 내부는 다음과 같이 구성되어 있습니다.

├── COMMIT_EDITMSG
├── HEAD
├── ORIG_HEAD
├── config
├── description
├── hooks
├── index
├── info
├── logs
├── objects
└── refs

이 중 hooks 폴더에 들어가면 다음과 같은 sample 파일들을 만나게 됩니다.

├── applypatch-msg.sample
├── commit-msg.sample
├── fsmonitor-watchman.sample
├── post-update.sample
├── pre-applypatch.sample
├── pre-commit.sample
├── pre-merge-commit.sample
├── pre-push.sample
├── pre-rebase.sample
├── pre-receive.sample
├── prepare-commit-msg.sample
└── update.sample

각각의 파일들은 쉘 스크립트 파일들이며, .sample을 지울 경우 git의 각 과정에서 작동합니다.

이 중에서 commit-msg 파일을 작성해 commit message 작성 후 convention 검사를 진행할 수 있습니다.

정규표현식을 사용해서 commit 메시지 체크하기

# exit with an error
exit 1

각 과정에서 위와 같은 방식으로 종료할 경우, 그 commit (이 외에 다른 동작들도) 은 자동적으로 취소됩니다.

따라서 다음과 같은 sh 파일을 만들 수 있습니다.

config=commit-msg.config.json

# set variables
enabled=$(jq -r .enabled $config)
revert=$(jq -r .revert $config)
types=($(jq -r '.types[]' $config))
min_length=$(jq -r .length.min $config)
max_length=$(jq -r .length.max $config)

if [[ ! -f $config || ! $enabled ]]; then
    exit 0
fi

regexp="^("

if $revert; then
    regexp="${regexp}revert: )?(\w+)("
fi

for type in "${types[@]}"
do
    regexp="${regexp}$type|"
done

regexp="${regexp})(\(.+\))?: "

regexp="${regexp}.{$min_length,$max_length}$"

msg=$(head -1 $1)

if [[ ! $msg =~ $regexp ]]; then
  echo -e "\n\e[1m\e[31m[INVALID COMMIT MESSAGE]"
  echo -e "------------------------\033[0m\e[0m"
  echo -e "\e[1mValid types:\e[0m \e[34m${types[@]}\033[0m"
  echo -e "\e[1mMax length (first line):\e[0m \e[34m$max_length\033[0m"
  echo -e "\e[1mMin length (first line):\e[0m \e[34m$min_length\033[0m\n"

  # exit with an error
  exit 1
fi
// commit-msg.config.json

{
    "enabled": true,
    "revert": true,
    "length": {
        "min": 1,
        "max": 52
    },
    "types": [
        "build",
        "ci",
        "docs",
        "feat",
        "fix",
        "perf",
        "refactor",
        "style",
        "test",
        "chore"
    ]
}

위 스크립트는 json 파일로 설정을 읽어들여오고 정규표현식을 이용해 검사하는 코드입니다.

huscky & commitlint를 이용한 검사

git hook 을 트리거 하는 용도로 npm 모듈인 huscky를 사용할 수 있습니다.

commitlint의 경우 commit 에 대한 lint를 확인하여 성공/실패를 리턴합니다.

다음 명령을 .git 폴더가 있는 프로젝트의 root에서 실행해주세요

yarn add husky @commitlint/cli @commitlint/config-conventional -D

husky가 githook 을 덮어쓰기 때문에 husky 설정 이전에 repo를 먼저 초기화 해야 합니다.

그리고 package.json에 다음과 같은 내용을 추가합니다.

  "husky": {
    "hooks": {
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  }

위 명령은 husky에서 hooks가 일어났을 때, commit-message에서 commitlint를 검사한다는 내용입니다.

commitlint에서 extends로 node_modules 내부의 @commitlint/config-conventional 에 존재하는 index.js 파일에서 설정을 읽어 오는데요,

설정 파일은 다음과 같습니다.

module.exports = {
    parserPreset: 'conventional-changelog-conventionalcommits',
    rules: {
        'body-leading-blank': [1, 'always'],
        'body-max-line-length': [2, 'always', 100],
        'footer-leading-blank': [1, 'always'],
        'footer-max-line-length': [2, 'always', 100],
        'header-max-length': [2, 'always', 100],
        'scope-case': [2, 'always', 'lower-case'],
        'subject-case': [
            2,
            'never',
            ['sentence-case', 'start-case', 'pascal-case', 'upper-case'],
        ],
        'subject-empty': [2, 'never'],
        'subject-full-stop': [2, 'never', '.'],
        'type-case': [2, 'always', 'lower-case'],
        'type-empty': [2, 'never'],
        'type-enum': [
            2,
            'always',
            [
                'build',
                'chore',
                'ci',
                'docs',
                'feat',
                'fix',
                'perf',
                'refactor',
                'revert',
                'style',
                'test',
            ],
        ],
    },
};

package.json의 commitlint.extends 부분을 직접 작성한 옵션으로 변경하면, 프로젝트에 적합한 commit convention을 적용할 수 있습니다.

'공부' 카테고리의 다른 글

CRA를 사용하지 않고 React 프로젝트 생성하기  (0) 2020.08.16

+ Recent posts