Skip to content

Commit d844c1d

Browse files
authored
feat: Merge pull request #22 from zopiolabs/feat/git-hooks
feat: add pre-commit and pre-push git hooks
2 parents a37a6e0 + cdb5990 commit d844c1d

File tree

5 files changed

+615
-5
lines changed

5 files changed

+615
-5
lines changed

.husky/pre-commit

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Colors for output
2+
RED='\033[0;31m'
3+
YELLOW='\033[1;33m'
4+
GREEN='\033[0;32m'
5+
NC='\033[0m' # No Color
6+
7+
echo "🚀 Running pre-commit checks..."
8+
9+
# Check for merge conflicts
10+
if git diff --cached --name-only | xargs grep -E "^(<<<<<<<|=======|>>>>>>>)" 2>/dev/null; then
11+
echo "${RED}❌ Merge conflict markers detected!${NC}"
12+
echo "Please resolve merge conflicts before committing."
13+
exit 1
14+
fi
15+
16+
# Check for console.log statements (warning only)
17+
CONSOLE_LOGS=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|jsx|ts|tsx)$' | xargs grep -n "console\.log" 2>/dev/null || true)
18+
if [ -n "$CONSOLE_LOGS" ]; then
19+
echo "${YELLOW}⚠️ Warning: console.log statements found:${NC}"
20+
echo "$CONSOLE_LOGS" | while IFS= read -r line; do
21+
echo " $line"
22+
done
23+
echo "${YELLOW}Consider removing console.log statements before committing.${NC}"
24+
fi
25+
26+
# Check for large files (>5MB)
27+
LARGE_FILES=$(git diff --cached --name-only | while read file; do
28+
if [ -f "$file" ]; then
29+
SIZE=$(wc -c < "$file" 2>/dev/null || echo 0)
30+
if [ "$SIZE" -gt 5242880 ]; then
31+
echo "$file ($(($SIZE / 1048576))MB)"
32+
fi
33+
fi
34+
done)
35+
36+
if [ -n "$LARGE_FILES" ]; then
37+
echo "${YELLOW}⚠️ Warning: Large files detected:${NC}"
38+
echo "$LARGE_FILES"
39+
echo "${YELLOW}Consider using Git LFS for large files.${NC}"
40+
fi
41+
42+
# Run lint-staged for fast checks on staged files
43+
echo "📝 Running lint and format checks on staged files..."
44+
pnpm exec lint-staged
45+
46+
if [ $? -ne 0 ]; then
47+
echo "${RED}❌ Pre-commit checks failed!${NC}"
48+
echo "Please fix the issues above and try again."
49+
exit 1
50+
fi
51+
52+
echo "${GREEN}✅ Pre-commit checks passed!${NC}"

.husky/pre-push

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Colors for output
2+
RED='\033[0;31m'
3+
YELLOW='\033[1;33m'
4+
GREEN='\033[0;32m'
5+
BLUE='\033[0;34m'
6+
NC='\033[0m' # No Color
7+
8+
echo "🚀 Running pre-push checks..."
9+
10+
# Get current branch name
11+
BRANCH=$(git rev-parse --abbrev-ref HEAD)
12+
13+
# Branch naming validation (matching PR validation rules)
14+
VALID_BRANCH_REGEX="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert|release|hotfix|deps|wip)\/[a-z0-9._-]+$|^(main|develop|staging|release\/v[0-9]+\.[0-9]+\.[0-9]+|version\/[0-9]+)$"
15+
16+
if ! echo "$BRANCH" | grep -qE "$VALID_BRANCH_REGEX"; then
17+
echo "${RED}❌ Invalid branch name: $BRANCH${NC}"
18+
echo "Branch names must follow the pattern: type/description"
19+
echo "Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert, release, hotfix, deps, wip"
20+
echo "Or be one of: main, develop, staging, release/vX.Y.Z, version/X"
21+
exit 1
22+
fi
23+
24+
# Get the remote and branch being pushed to
25+
while read local_ref local_sha remote_ref remote_sha
26+
do
27+
# Check commit messages for conventional commit format
28+
echo "${BLUE}📋 Validating commit messages...${NC}"
29+
30+
# Get all commits that will be pushed
31+
if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
32+
# New branch, check commits not in origin/develop
33+
COMMITS=$(git rev-list origin/develop..HEAD 2>/dev/null || git rev-list HEAD)
34+
else
35+
# Existing branch, check new commits only
36+
COMMITS=$(git rev-list "$remote_sha..$local_sha")
37+
fi
38+
39+
INVALID_COMMITS=""
40+
for commit in $COMMITS; do
41+
MSG=$(git log --format=%s -n 1 "$commit")
42+
# Check conventional commit format
43+
if ! echo "$MSG" | grep -qE "^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+$|^Merge |^Initial commit$"; then
44+
INVALID_COMMITS="$INVALID_COMMITS\n - $commit: $MSG"
45+
fi
46+
done
47+
48+
if [ -n "$INVALID_COMMITS" ]; then
49+
echo "${RED}❌ Invalid commit messages found:${NC}"
50+
echo "$INVALID_COMMITS"
51+
echo "${YELLOW}Commit messages must follow conventional commit format:${NC}"
52+
echo " type(scope?): description"
53+
echo " Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
54+
exit 1
55+
fi
56+
done
57+
58+
echo "${GREEN}✅ Branch name and commit messages are valid${NC}"
59+
60+
# Run comprehensive checks
61+
echo "${BLUE}🧹 Running lint checks...${NC}"
62+
pnpm lint
63+
if [ $? -ne 0 ]; then
64+
echo "${RED}❌ Linting failed!${NC}"
65+
echo "Run 'pnpm lint:fix' to auto-fix issues"
66+
exit 1
67+
fi
68+
69+
echo "${BLUE}🔍 Running type checks...${NC}"
70+
pnpm typecheck
71+
if [ $? -ne 0 ]; then
72+
echo "${RED}❌ Type checking failed!${NC}"
73+
echo "Please fix TypeScript errors before pushing"
74+
exit 1
75+
fi
76+
77+
echo "${BLUE}🧪 Running tests...${NC}"
78+
CI=true pnpm test
79+
if [ $? -ne 0 ]; then
80+
echo "${RED}❌ Tests failed!${NC}"
81+
echo "Please fix failing tests before pushing"
82+
exit 1
83+
fi
84+
85+
echo "${BLUE}🏗️ Building project...${NC}"
86+
pnpm build
87+
if [ $? -ne 0 ]; then
88+
echo "${RED}❌ Build failed!${NC}"
89+
echo "Please fix build errors before pushing"
90+
exit 1
91+
fi
92+
93+
echo "${GREEN}✅ All pre-push checks passed!${NC}"
94+
echo "${GREEN}🎉 Ready to push to $BRANCH${NC}"

.vscode/tasks.json

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "Dev: Start All Services",
6+
"type": "shell",
7+
"command": "pnpm",
8+
"args": ["dev"],
9+
"group": {
10+
"kind": "none",
11+
"isDefault": false
12+
},
13+
"presentation": {
14+
"reveal": "always",
15+
"panel": "new",
16+
"focus": true,
17+
"echo": true,
18+
"showReuseMessage": false,
19+
"clear": false
20+
},
21+
"problemMatcher": [],
22+
"isBackground": true,
23+
"detail": "Start all applications and packages in development mode using Turborepo"
24+
},
25+
{
26+
"label": "Build: Entire Monorepo",
27+
"type": "shell",
28+
"command": "pnpm",
29+
"args": ["build"],
30+
"group": {
31+
"kind": "build",
32+
"isDefault": true
33+
},
34+
"presentation": {
35+
"reveal": "always",
36+
"panel": "shared",
37+
"focus": false,
38+
"echo": true,
39+
"showReuseMessage": false,
40+
"clear": true
41+
},
42+
"problemMatcher": ["$tsc"],
43+
"detail": "Build all packages and applications in dependency order"
44+
},
45+
{
46+
"label": "Test: Run All Tests",
47+
"type": "shell",
48+
"command": "pnpm",
49+
"args": ["test"],
50+
"group": {
51+
"kind": "test",
52+
"isDefault": true
53+
},
54+
"presentation": {
55+
"reveal": "always",
56+
"panel": "shared",
57+
"focus": false,
58+
"echo": true,
59+
"showReuseMessage": false,
60+
"clear": true
61+
},
62+
"problemMatcher": [],
63+
"detail": "Run all tests across the entire monorepo using Vitest"
64+
},
65+
{
66+
"label": "Code Check: Full Validation",
67+
"dependsOrder": "sequence",
68+
"dependsOn": ["Code Check: Lint", "Code Check: Format", "Code Check: Type Check"],
69+
"group": {
70+
"kind": "none",
71+
"isDefault": false
72+
},
73+
"presentation": {
74+
"reveal": "always",
75+
"panel": "shared",
76+
"focus": false,
77+
"echo": true,
78+
"showReuseMessage": false,
79+
"clear": false
80+
},
81+
"problemMatcher": [],
82+
"detail": "Run linting, formatting, and type checking across the entire codebase"
83+
},
84+
{
85+
"label": "Code Check: Lint",
86+
"type": "shell",
87+
"command": "pnpm",
88+
"args": ["lint"],
89+
"group": "none",
90+
"presentation": {
91+
"reveal": "silent",
92+
"panel": "shared",
93+
"focus": false,
94+
"echo": true,
95+
"showReuseMessage": false,
96+
"clear": false
97+
},
98+
"problemMatcher": [],
99+
"detail": "Run Biome linter"
100+
},
101+
{
102+
"label": "Code Check: Format",
103+
"type": "shell",
104+
"command": "pnpm",
105+
"args": ["format"],
106+
"group": "none",
107+
"presentation": {
108+
"reveal": "silent",
109+
"panel": "shared",
110+
"focus": false,
111+
"echo": true,
112+
"showReuseMessage": false,
113+
"clear": false
114+
},
115+
"problemMatcher": [],
116+
"detail": "Format code using Biome"
117+
},
118+
{
119+
"label": "Code Check: Type Check",
120+
"type": "shell",
121+
"command": "pnpm",
122+
"args": ["typecheck"],
123+
"group": "none",
124+
"presentation": {
125+
"reveal": "silent",
126+
"panel": "shared",
127+
"focus": false,
128+
"echo": true,
129+
"showReuseMessage": false,
130+
"clear": false
131+
},
132+
"problemMatcher": ["$tsc"],
133+
"detail": "Run TypeScript type checking"
134+
},
135+
{
136+
"label": "Code Check: Full Validation + Autofix",
137+
"dependsOrder": "sequence",
138+
"dependsOn": [
139+
"Code Check: Lint Autofix",
140+
"Code Check: Format Autofix",
141+
"Code Check: Type Check"
142+
],
143+
"group": {
144+
"kind": "none",
145+
"isDefault": false
146+
},
147+
"presentation": {
148+
"reveal": "always",
149+
"panel": "shared",
150+
"focus": false,
151+
"echo": true,
152+
"showReuseMessage": false,
153+
"clear": false
154+
},
155+
"problemMatcher": [],
156+
"detail": "Run linting, formatting with autofix, and type checking across the entire codebase"
157+
},
158+
{
159+
"label": "Code Check: Lint Autofix",
160+
"type": "shell",
161+
"command": "pnpm",
162+
"args": ["lint:fix"],
163+
"group": "none",
164+
"presentation": {
165+
"reveal": "silent",
166+
"panel": "shared",
167+
"focus": false,
168+
"echo": true,
169+
"showReuseMessage": false,
170+
"clear": false
171+
},
172+
"problemMatcher": [],
173+
"detail": "Run Biome linter with autofix"
174+
},
175+
{
176+
"label": "Code Check: Format Autofix",
177+
"type": "shell",
178+
"command": "pnpm",
179+
"args": ["format:fix"],
180+
"group": "none",
181+
"presentation": {
182+
"reveal": "silent",
183+
"panel": "shared",
184+
"focus": false,
185+
"echo": true,
186+
"showReuseMessage": false,
187+
"clear": false
188+
},
189+
"problemMatcher": [],
190+
"detail": "Format code using Biome with autofix"
191+
}
192+
]
193+
}

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "aicd",
33
"version": "0.2.1",
4-
"private": true,
4+
"private": false,
55
"description": "AI-powered continuous deployment platform",
66
"author": "zopio",
77
"license": "MIT",
@@ -33,10 +33,17 @@
3333
"check": "biome check .",
3434
"prepare": "husky install"
3535
},
36+
"lint-staged": {
37+
"**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
38+
"biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
39+
],
40+
"**/*.{js,jsx,ts,tsx}": ["bash -c 'tsc --noEmit --skipLibCheck'"]
41+
},
3642
"devDependencies": {
3743
"@biomejs/biome": "^1.5.0",
3844
"@types/node": "^20.11.0",
3945
"husky": "^9.0.0",
46+
"lint-staged": "^16.1.2",
4047
"tsup": "^8.0.0",
4148
"turbo": "^1.12.0",
4249
"typescript": "^5.3.0",

0 commit comments

Comments
 (0)