1
0

feat: 原生 Git hooks 方案,增强版本升迁工作流

This commit is contained in:
2026-05-05 21:58:30 +08:00
parent 5655fc5560
commit a2751eab31
8 changed files with 476 additions and 18 deletions

134
scripts/git-hooks/test-hooks.sh Executable file
View File

@@ -0,0 +1,134 @@
#!/bin/sh
set -eu
ROOT_DIR=$(git rev-parse --show-toplevel)
cd "$ROOT_DIR"
TMP_DIR=${TMPDIR:-/tmp}/nex-hooks-test.$$
mkdir -p "$TMP_DIR"
cleanup() {
rm -f \
backend/pkg/buildinfo/hook_bad_test_fixture.go \
frontend/src/hook_bad_fixture.ts \
frontend/src/hook_format_fixture.ts \
docs/hook-doc-fixture.md \
docs/hook-conflict-fixture.md \
docs/hook-large-fixture.txt
rm -rf "$TMP_DIR"
}
trap cleanup EXIT HUP INT TERM
pass() {
printf 'OK: %s\n' "$1"
}
fail() {
printf 'FAIL: %s\n' "$1" >&2
exit 1
}
write_msg() {
file=$1
shift
printf '%s\n' "$*" > "$file"
}
expect_success() {
name=$1
shift
if "$@" > "$TMP_DIR/out" 2>&1; then
pass "$name"
else
cat "$TMP_DIR/out" >&2
fail "$name"
fi
}
expect_failure() {
name=$1
shift
if "$@" > "$TMP_DIR/out" 2>&1; then
cat "$TMP_DIR/out" >&2
fail "$name"
fi
pass "$name"
}
run_precommit_for() {
index=$TMP_DIR/index
rm -f "$index"
GIT_INDEX_FILE=$index git read-tree HEAD
for file in "$@"; do
GIT_INDEX_FILE=$index git add -f "$file"
done
GIT_INDEX_FILE=$index make _hooks-pre-commit
}
MSG_FILE=$TMP_DIR/commit-msg.txt
write_msg "$MSG_FILE" 'feat: 添加 hook 测试'
expect_success 'commit-msg accepts Chinese description' scripts/git-hooks/commit-msg "$MSG_FILE"
write_msg "$MSG_FILE" 'feat: add hook tests'
expect_failure 'commit-msg rejects English-only description' scripts/git-hooks/commit-msg "$MSG_FILE"
write_msg "$MSG_FILE" 'update: 添加 hook 测试'
expect_failure 'commit-msg rejects invalid type' scripts/git-hooks/commit-msg "$MSG_FILE"
write_msg "$MSG_FILE" 'Merge branch feature'
expect_success 'commit-msg accepts merge commits' scripts/git-hooks/commit-msg "$MSG_FILE"
cat > backend/pkg/buildinfo/hook_bad_test_fixture.go <<'EOF'
package buildinfo
import "fmt"
func hookBadTestFixture() {
fmt.Println("bad")
}
EOF
expect_failure 'pre-commit rejects Go lint errors' run_precommit_for backend/pkg/buildinfo/hook_bad_test_fixture.go
rm -f backend/pkg/buildinfo/hook_bad_test_fixture.go
cat > frontend/src/hook_bad_fixture.ts <<'EOF'
console.log('bad')
EOF
expect_failure 'pre-commit rejects frontend lint errors' run_precommit_for frontend/src/hook_bad_fixture.ts
rm -f frontend/src/hook_bad_fixture.ts
cat > frontend/src/hook_format_fixture.ts <<'EOF'
const hookFormatFixture={foo:"bar"}
export { hookFormatFixture }
EOF
expect_failure 'pre-commit rejects frontend format errors' run_precommit_for frontend/src/hook_format_fixture.ts
rm -f frontend/src/hook_format_fixture.ts
cat > docs/hook-doc-fixture.md <<'EOF'
hook doc fixture
EOF
expect_success 'pre-commit skips non-code staged files' run_precommit_for docs/hook-doc-fixture.md
rm -f docs/hook-doc-fixture.md
cat > docs/hook-conflict-fixture.md <<'EOF'
<<<<<<< HEAD
conflict
=======
other
>>>>>>> branch
EOF
expect_failure 'pre-commit rejects conflict markers' run_precommit_for docs/hook-conflict-fixture.md
rm -f docs/hook-conflict-fixture.md
i=0
while [ "$i" -lt 40000 ]; do
printf 'large hook fixture line\n'
i=$((i + 1))
done > docs/hook-large-fixture.txt
if run_precommit_for docs/hook-large-fixture.txt > "$TMP_DIR/out" 2>&1 && grep -q 'Warning: large staged text file' "$TMP_DIR/out"; then
pass 'pre-commit warns for large text files'
else
cat "$TMP_DIR/out" >&2
fail 'pre-commit warns for large text files'
fi
rm -f docs/hook-large-fixture.txt