Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/env bash

set -e

if ((BASH_VERSINFO[0] < 4)); then
echo "[pre-push] Error: bash 4.0+ is required. Install with: brew install bash"
exit 1
fi

MAIN_BRANCH="origin/develop"
MERGE_BASE=$(git merge-base HEAD "$MAIN_BRANCH" 2>/dev/null || git merge-base HEAD develop 2>/dev/null || true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Major] pre-push 훅의 stdin 입력을 무시하고 있습니다

Git pre-push 훅은 stdin으로 실제 push되는 ref 정보를 전달합니다:

<local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF

현재 스크립트는 이 입력을 전혀 읽지 않고 항상 HEAD vs origin/develop을 비교합니다. 이는 다음 문제를 야기합니다:

  • 이미 develop에 병합된 커밋도 매번 재검사됩니다.
  • 실제로 push되는 커밋 범위와 무관한 파일이 검사될 수 있습니다.

stdin을 읽어 실제 push 범위를 기반으로 변경 파일을 탐지하는 방식을 권장합니다:

while read local_ref local_sha remote_ref remote_sha; do
  if [ "$local_sha" = "0000000000000000000000000000000000000000" ]; then
    continue  # branch deletion, skip
  fi
  if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
    # new branch being pushed
    RANGE="$local_sha"
  else
    RANGE="$remote_sha..$local_sha"
  fi
  CHANGED_FILES=$(git diff --name-only "$RANGE")
done


if [ -z "$MERGE_BASE" ]; then
echo "[pre-push] Could not determine merge base. Running full check..."
./gradlew spotlessCheck ktlintCheck detekt
exit 0
fi

CHANGED_FILES=$(git diff --name-only "$MERGE_BASE" HEAD)

if [ -z "$CHANGED_FILES" ]; then
echo "[pre-push] No changed files. Skipping checks."
exit 0
fi

echo "[pre-push] Changed files:"
echo "$CHANGED_FILES" | sed 's/^/ /'

# Parse modules from settings.gradle dynamically
declare -A MODULE_PATHS # module -> dir path
while IFS= read -r line; do
for token in $line; do
token="${token//\'/}"
token="${token//,/}"
if [[ "$token" == :* ]]; then
dir="${token//://}"
dir="${dir#/}"
MODULE_PATHS["$token"]="$dir"
fi
done
done < <(grep "^include" settings.gradle)

# Map changed files to affected modules
declare -A MODULES
RUN_ALL=false

while IFS= read -r file; do
case "$file" in
build-logic/*|build.gradle|build.gradle.kts|gradle.properties|settings.gradle|settings.gradle.kts|gradle/libs.versions.toml)
RUN_ALL=true
break
;;
esac
matched_module=""
matched_len=0
for module in "${!MODULE_PATHS[@]}"; do
dir="${MODULE_PATHS[$module]}"
if [[ "$file" == "$dir/"* ]]; then
if (( ${#dir} > matched_len )); then
matched_module="$module"
matched_len=${#dir}
fi
fi
done
if [[ -n "$matched_module" ]]; then
MODULES["$matched_module"]=1
fi
done <<< "$CHANGED_FILES"

if [ "$RUN_ALL" = true ]; then
echo "[pre-push] Build-level changes detected. Running full check..."
./gradlew spotlessCheck ktlintCheck detekt
exit 0
fi

if [ ${#MODULES[@]} -eq 0 ]; then
echo "[pre-push] No affected modules detected. Skipping checks."
exit 0
fi

echo "[pre-push] Affected modules: ${!MODULES[*]}"

TASKS=("spotlessCheck")
for module in "${!MODULES[@]}"; do
TASKS+=("${module}:ktlintCheck")
if ./gradlew "${module}:tasks" --quiet 2>/dev/null | grep -q "^detekt "; then
TASKS+=("${module}:detekt")
fi
done
echo "[pre-push] Running: ./gradlew ${TASKS[*]}"
./gradlew --continue "${TASKS[@]}"
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal fun Project.configureDetekt(
}

tasks.named<Detekt>("detekt") {
jvmTarget = "17"
reports {
html.required.set(true)
xml.required.set(true)
Expand Down
8 changes: 8 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,11 @@ spotless {
tasks.named<Delete>("clean") {
delete(rootProject.buildDir)
}
tasks.register("installGitHooks") {
doLast {
exec {
commandLine("git", "config", "core.hooksPath", ".githooks")
}
println("Git hooks installed!")
}
}
Loading