forked from mcuadros/ofelia
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathlefthook.yml
More file actions
214 lines (185 loc) · 6.48 KB
/
lefthook.yml
File metadata and controls
214 lines (185 loc) · 6.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# Ofelia Git Hooks - Powered by lefthook
# https://github.com/evilmartians/lefthook
#
# Fast, Go-native git hooks with automatic installation
# Run 'make setup' after git clone to install hooks
# Skip hooks on specific branches or conditions
skip_output:
- meta
- success
colors: true
pre-commit:
parallel: true
commands:
go-mod-tidy:
priority: 1
run: |
if ! go mod tidy -diff >/dev/null 2>&1; then
echo "❌ go.mod not clean. Run: go mod tidy"
exit 1
fi
go-vet:
glob: "*.go"
run: go vet ./...
gofmt:
glob: "*.go"
run: |
unformatted=$(gofmt -l $(git ls-files '*.go') 2>/dev/null || true)
if [ -n "$unformatted" ]; then
echo "❌ Unformatted: $unformatted"
exit 1
fi
yaml-lint:
glob: "*.{yml,yaml}"
run: |
if ! python3 -c "import yaml" 2>/dev/null; then
echo "⚠️ python3/PyYAML not found, skipping YAML lint"
exit 0
fi
python3 -c "
import yaml, sys
for f in sys.argv[1:]:
try:
list(yaml.safe_load_all(open(f)))
except yaml.YAMLError as e:
print(f'❌ Invalid YAML: {f}')
print(e)
sys.exit(1)
" {staged_files}
actionlint:
glob: ".github/workflows/*.{yml,yaml}"
run: |
if ! command -v actionlint >/dev/null 2>&1; then
echo "⚠️ actionlint not found, skipping workflow lint"
echo " Install: go install github.com/rhysd/actionlint/cmd/actionlint@latest"
exit 0
fi
actionlint {staged_files}
secrets:
run: |
code_files=$(git diff --cached --name-only | grep -E '\.(go|js|ts|py|java|rb|php)$' || true)
[ -z "$code_files" ] && exit 0
if echo "$code_files" | xargs grep -E "(password|secret|api_key|apikey|token|access_key)(\s*=\s*|\s*:\s*)['\"][^'\"]{8,}['\"]" 2>/dev/null | grep -v "example\|test\|mock\|dummy"; then
echo "❌ Potential secrets detected!"
exit 1
fi
commit-msg:
commands:
# Validate commit message format
message-format:
run: |
echo "📝 Validating commit message format..."
# Read commit message
msg=$(cat {1})
# Skip merge commits
if echo "$msg" | grep -q "^Merge"; then
echo "✅ Merge commit - skipping validation"
exit 0
fi
# Check for minimum length (at least 10 characters)
if [ ${#msg} -lt 10 ]; then
echo "❌ Commit message too short (minimum 10 characters)"
echo "Current: ${#msg} characters"
exit 1
fi
# Check for conventional commit format (optional but recommended)
# Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert
if ! echo "$msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .+"; then
echo "⚠️ Commit message doesn't follow conventional commits format"
echo "Recommended format: <type>(<scope>): <subject>"
echo "Example: feat(core): add new scheduler algorithm"
echo "Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert"
echo ""
echo "Your message: $msg"
echo ""
echo "Continuing anyway, but consider using conventional commits for better changelog generation."
fi
# Block WIP commits to main/master
current_branch=$(git rev-parse --abbrev-ref HEAD)
if echo "$msg" | grep -qiE "^(wip|WIP|fixup|squash)"; then
if [ "$current_branch" = "main" ] || [ "$current_branch" = "master" ]; then
echo "❌ WIP/fixup/squash commits are not allowed on main/master branch"
echo "Current branch: $current_branch"
exit 1
fi
echo "⚠️ WIP commit detected on feature branch - remember to squash before merging"
fi
echo "✅ Commit message format validated"
# Enforce Developer Certificate of Origin (DCO)
dco-signoff:
run: |
msg=$(cat {1})
# Skip merge commits
if echo "$msg" | grep -q "^Merge"; then
exit 0
fi
if ! echo "$msg" | grep -qE "^Signed-off-by: .+ <.+>"; then
echo "❌ Missing DCO sign-off!"
echo ""
echo "All commits must include a Signed-off-by trailer."
echo "Use: git commit --signoff -m \"your message\""
echo ""
echo "See CONTRIBUTING.md for details."
exit 1
fi
pre-push:
parallel: true
commands:
golangci-lint:
glob: "*.go"
run: golangci-lint run --timeout=3m
smoke-tests:
run: |
if ! go test -short -timeout=60s ./core/... ./cli/... ./middlewares/...; then
echo "❌ Smoke tests failed!"
exit 1
fi
post-checkout:
commands:
# Check for dependency changes and remind to update
dependency-check:
run: |
echo "🔄 Checking for dependency changes..."
# Check if go.mod or go.sum changed
if git diff --name-only HEAD@{1} HEAD 2>/dev/null | grep -qE "^go\.(mod|sum)$"; then
echo ""
echo "⚠️ Dependencies changed! Run:"
echo " go mod download"
echo ""
fi
# Check if hooks are installed (in case this is first checkout)
if [ ! -f .git/hooks/pre-commit ] || ! grep -q "lefthook" .git/hooks/pre-commit 2>/dev/null; then
echo ""
echo "⚠️ Git hooks not installed! Run:"
echo " make setup"
echo ""
fi
post-merge:
commands:
# Auto-update dependencies if go.mod changed
dependency-update:
run: |
echo "🔄 Checking for dependency changes after merge..."
# Check if go.mod or go.sum changed in the merge
if git diff --name-only HEAD@{1} HEAD | grep -qE "^go\.(mod|sum)$"; then
echo ""
echo "📦 Dependencies changed in merge. Updating..."
if ! go mod download; then
echo "❌ Failed to download dependencies"
echo "Please run manually: go mod download"
exit 1
fi
echo "✅ Dependencies updated successfully"
echo ""
echo "💡 Tip: Run 'make test' to verify everything still works"
else
echo "✅ No dependency changes detected"
fi
# Output configuration
output:
- summary
- success
# Skip configuration
skip:
- merge
- rebase