July 24, 2023
Git hooks는 사용하고 싶고, pre-commit
이나 husky
는 설치하고 싶지 않았다
어떻게 해야할까?
prepare-commit-msg hook을 사용해 커밋 메세지 컨벤션을 체크한다
#!/bin/sh
commit_msg_file="$1"
commit_msg_type="$2"
commit_msg="$3"
if [ "$commit_msg_type" = "-m" ]; then
echo "$commit_msg" > "$commit_msg_file"
fi
commit_msg=$(cat "$commit_msg_file")
# 정규표현식 파일을 참조한다
commit_msg_regex=$(cat "$(dirname "$0")/../../.github/commit-regular.txt")
if ! echo "$commit_msg" | grep -Eq "$commit_msg_regex"; then
echo "Invalid commit message format."
exit 1
fi
간단히 말해 해당 파일을 .git/hooks/prepare-commit-msg
위치에 작성하면, Git이 알아서 git commit
마다 컨벤션 체크가 동작한다!
(feat|fix|refactor|style|docs|test|chore):.{1,50}(\n.{1,72})?$
위 파일은 정규표현식으로 향후 커밋 메세지를 체크할때 사용한다
Git Actions
를 통한 CI 작업에도 사용하기 때문이다.git
폴더는 숨김 폴더이기 때문에 github
에 올라가지 않는다.
따라서 해당 파일을 모든 개발자가 셋업 하기에는 너무 귀찮은 일이다.
특정 IDE 마다 다르겠지만 대부분 훅을 제공해 여러 설정을 자동으로 세팅할 수 있다.
devcontainer
는 Codespace
개발환경 세팅을 위한 규칙이라고 생각하면 편하다!
가장 간단한 예시로는 레퍼지토리에 devcontainer
규칙에 맞는 파일을 정의하면, 어떤 누구나 코드스페이스를 실행할때 설정해놓은 Ubuntu Image 위에 Java, Docker가 설치되며 Extenstion도 자동으로 설치된다!
{
// ...
"postCreateCommand": "bash ./.devcontainer/postCreateCommand.sh",
}
cp .github/hooks/prepare-commit-msg .git/hooks/prepare-commit-msg
chmod +x .git/hooks/prepare-commit-msg
postCreateCommand.sh
을 이용해 쉘 스크립트 파일을 .git/hooks
로 복사한다
인텔리제이를 포함해서 모든 에디터에서 공통이다.
val installLocalGitHook = tasks.register<Copy>("installLocalGitHook") {
from("${rootProject.rootDir}/.github/hooks")
into(File("${rootProject.rootDir}/.git/hooks"))
eachFile {
mode = "755".toInt(radix = 8)
}
}
tasks.build {
dependsOn(installLocalGitHook)
}
해당 파일은 코틀린으로 작성되었으며 특정 Gradle 버전마다 다른 형식을 사용할 수 있다
단점: graldew build
실행시 세팅되기 때문에 만약 빌드를 안하면 세팅되지 않는다!
위 커밋 컨벤션 체크 쉘 스크립트 파일을 그대로 이용했다
name: Commit Message Check
on: [push]
jobs:
commit_message_check:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Read Commit Regular Expression
id: read_commit_regex
run: |
commit_msg_regex=$(cat ./.github/commit-regular.txt)
echo "Commit Regular Expression: $commit_msg_regex"
echo "::set-output name=commit_regex::$commit_msg_regex"
- name: Validate Commit Message
run: |
commit_msg=$(git log --format=%B -n 1 ${{ github.sha }})
echo "Commit Message: $commit_msg"
commit_regex="${{ steps.read_commit_regex.outputs.commit_regex }}"
if [[ ! "$commit_msg" =~ $commit_regex ]]; then
echo "Invalid commit message format."
exit 1
else
echo "Commit message is valid."
fi
./gradlew ktlintCheck --daemon
status=$?
echo "$status"
if [ "$status" = 0 ] ; then
echo "> Completed ktlint hook."
exit 0
else
echo "> Error ktlint hook."
echo "============================"
exit 1
fi
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Ktlint check
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629
with:
arguments: ktlintCheck
Ktlint
를 예시로 사용했다!