Skip to content

Commit 58906bf

Browse files
authored
Merge pull request #38 from pinchtab/improve/dev-tooling
chore: add gotestsum support with fallback for test output
2 parents 6eaa8dd + 0647e3e commit 58906bf

4 files changed

Lines changed: 551 additions & 121 deletions

File tree

dev

Lines changed: 81 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4+
# dev — idpishield developer toolkit
5+
# Usage: dev [command] Run a command directly
6+
# dev Show help
7+
48
cd "$(dirname "$0")"
59

610
BOLD=$'\033[1m'
@@ -10,129 +14,101 @@ SUCCESS=$'\033[38;2;0;229;204m'
1014
ERROR=$'\033[38;2;230;57;70m'
1115
NC=$'\033[0m'
1216

13-
commands=(
17+
# ── Commands ─────────────────────────────────────────────────────────
18+
COMMANDS=(
19+
"build:📦:Build binary"
20+
"check:✅:All checks (format, vet, build, lint)"
21+
"test:🧪:Run tests"
1422
"doctor:🩺:Setup dev environment"
15-
"test:🧪:Run unit tests"
16-
"test verbose:🧪:Run unit tests (verbose)"
17-
"test race:🧪:Run unit tests with race detector"
18-
"coverage:📊:Run tests with coverage report"
19-
"lint:🔍:Run golangci-lint"
2023
"fmt:✨:Format code"
2124
"vet:🔬:Run go vet"
22-
"check:✅:Run all checks (fmt + vet + lint + test)"
23-
"build:📦:Build CLI binary"
25+
"lint:🔍:Run golangci-lint"
26+
"coverage:📊:Run tests with coverage"
2427
"benchmark:🏋:Run benchmarks"
2528
)
2629

2730
show_help() {
2831
echo ""
29-
echo " ${BOLD}${ACCENT}idpishield${NC} ${MUTED}— development tool${NC}"
32+
echo " ${ACCENT}${BOLD}🛡️ idpishield Dev${NC}"
3033
echo ""
31-
for entry in "${commands[@]}"; do
32-
IFS=: read -r cmd icon desc <<< "$entry"
33-
printf " ${ACCENT}%-22s${NC} %s %s\n" "./dev $cmd" "$icon" "$desc"
34+
for cmd in "${COMMANDS[@]}"; do
35+
IFS=':' read -r name emoji desc <<< "$cmd"
36+
printf " ${SUCCESS}%s${NC} ${BOLD}%-12s${NC} ${MUTED}%s${NC}\n" "$emoji" "$name" "$desc"
3437
done
3538
echo ""
36-
}
37-
38-
run_test() {
39-
echo " ${ACCENT}${BOLD}🧪 Running tests${NC}"
40-
go test ./... -count=1
41-
echo " ${SUCCESS}${NC} Tests passed"
42-
}
43-
44-
run_test_verbose() {
45-
echo " ${ACCENT}${BOLD}🧪 Running tests (verbose)${NC}"
46-
go test ./... -count=1 -v
47-
}
48-
49-
run_test_race() {
50-
echo " ${ACCENT}${BOLD}🧪 Running tests with race detector${NC}"
51-
go test ./... -count=1 -race
52-
echo " ${SUCCESS}${NC} Tests passed (race)"
53-
}
54-
55-
run_coverage() {
56-
echo " ${ACCENT}${BOLD}📊 Running tests with coverage${NC}"
57-
go test ./... -count=1 -coverprofile=coverage.out -covermode=atomic
58-
go tool cover -func=coverage.out | tail -1
39+
echo " ${MUTED}Usage: ./dev [command]${NC}"
5940
echo ""
60-
echo " ${MUTED}HTML report: go tool cover -html=coverage.out${NC}"
6141
}
6242

63-
run_lint() {
64-
echo " ${ACCENT}${BOLD}🔍 Running linter${NC}"
65-
golangci-lint run
66-
echo " ${SUCCESS}${NC} Lint clean"
67-
}
43+
run_command() {
44+
local target="$1"
6845

69-
run_fmt() {
70-
echo " ${ACCENT}${BOLD}✨ Formatting code${NC}"
71-
gofmt -w .
72-
echo " ${SUCCESS}${NC} Formatted"
73-
}
74-
75-
run_vet() {
76-
echo " ${ACCENT}${BOLD}🔬 Running go vet${NC}"
77-
go vet ./...
78-
echo " ${SUCCESS}${NC} Vet clean"
79-
}
80-
81-
run_check() {
82-
echo " ${ACCENT}${BOLD}✅ Running all checks${NC}"
8346
echo ""
8447

85-
echo " ${MUTED}1/4 Format check${NC}"
86-
unformatted=$(gofmt -l .)
87-
if [ -n "$unformatted" ]; then
88-
echo " ${ERROR}${NC} Unformatted files:"
89-
echo "$unformatted"
90-
exit 1
91-
fi
92-
echo " ${SUCCESS}${NC} Format"
93-
94-
echo " ${MUTED}2/4 Vet${NC}"
95-
go vet ./...
96-
echo " ${SUCCESS}${NC} Vet"
97-
98-
echo " ${MUTED}3/4 Lint${NC}"
99-
golangci-lint run
100-
echo " ${SUCCESS}${NC} Lint"
101-
102-
echo " ${MUTED}4/4 Tests${NC}"
103-
go test ./... -count=1 -race
104-
echo " ${SUCCESS}${NC} Tests"
105-
106-
echo ""
107-
echo " ${SUCCESS}${BOLD}All checks passed${NC}"
48+
case "$target" in
49+
"build")
50+
echo " ${ACCENT}${BOLD}📦 Building idpishield${NC}"
51+
echo ""
52+
go build -o idpishield ./cmd/idpishield
53+
echo " ${SUCCESS}${NC} Built: ./idpishield"
54+
;;
55+
"check")
56+
exec bash scripts/check.sh
57+
;;
58+
"test")
59+
exec bash scripts/test.sh
60+
;;
61+
"doctor")
62+
exec bash scripts/doctor.sh
63+
;;
64+
"fmt")
65+
echo " ${ACCENT}${BOLD}✨ Formatting code${NC}"
66+
echo ""
67+
gofmt -w .
68+
echo " ${SUCCESS}${NC} Formatted"
69+
;;
70+
"vet")
71+
echo " ${ACCENT}${BOLD}🔬 Running go vet${NC}"
72+
echo ""
73+
go vet ./...
74+
echo " ${SUCCESS}${NC} Vet clean"
75+
;;
76+
"lint")
77+
echo " ${ACCENT}${BOLD}🔍 Running linter${NC}"
78+
echo ""
79+
golangci-lint run
80+
echo " ${SUCCESS}${NC} Lint clean"
81+
;;
82+
"coverage")
83+
echo " ${ACCENT}${BOLD}📊 Running tests with coverage${NC}"
84+
echo ""
85+
go test ./... -count=1 -coverprofile=coverage.out -covermode=atomic
86+
go tool cover -func=coverage.out | tail -1
87+
echo ""
88+
echo " ${MUTED}HTML report: go tool cover -html=coverage.out${NC}"
89+
;;
90+
"benchmark")
91+
echo " ${ACCENT}${BOLD}🏋 Running benchmarks${NC}"
92+
echo ""
93+
go test ./benchmark/ -count=1 -v
94+
;;
95+
*)
96+
echo " ${ERROR}Unknown command: $target${NC}"
97+
show_help
98+
exit 1
99+
;;
100+
esac
108101
}
109102

110-
run_build() {
111-
echo " ${ACCENT}${BOLD}📦 Building CLI${NC}"
112-
go build -o idpishield ./cmd/idpishield
113-
echo " ${SUCCESS}${NC} Built: ./idpishield"
114-
}
103+
# ── Main ─────────────────────────────────────────────────────────────
115104

116-
run_benchmark() {
117-
echo " ${ACCENT}${BOLD}🏋 Running benchmarks${NC}"
118-
go test ./benchmark/ -count=1 -v
119-
}
105+
if [ $# -gt 0 ]; then
106+
case "$1" in
107+
-h|--help|help) show_help; exit 0 ;;
108+
*) run_command "$1" ;;
109+
esac
110+
exit 0
111+
fi
120112

121-
case "${1:-help}" in
122-
doctor) exec bash scripts/doctor.sh ;;
123-
test)
124-
case "${2:-}" in
125-
verbose) run_test_verbose ;;
126-
race) run_test_race ;;
127-
*) run_test ;;
128-
esac
129-
;;
130-
coverage) run_coverage ;;
131-
lint) run_lint ;;
132-
fmt) run_fmt ;;
133-
vet) run_vet ;;
134-
check) run_check ;;
135-
build) run_build ;;
136-
benchmark) run_benchmark ;;
137-
help|*) show_help ;;
138-
esac
113+
# No args → show help
114+
show_help

scripts/check.sh

Lines changed: 91 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,102 @@
1-
#!/usr/bin/env bash
2-
set -euo pipefail
1+
#!/bin/bash
2+
set -e
3+
4+
# check.sh — Local pre-push checks matching GitHub Actions CI
5+
# Runs: format → vet → build → lint
6+
37
cd "$(dirname "$0")/.."
48

5-
echo "=== Format check ==="
9+
BOLD=$'\033[1m'
10+
ACCENT=$'\033[38;2;251;191;36m'
11+
SUCCESS=$'\033[38;2;0;229;204m'
12+
ERROR=$'\033[38;2;230;57;70m'
13+
MUTED=$'\033[38;2;90;100;128m'
14+
NC=$'\033[0m'
15+
16+
ok() { echo -e " ${SUCCESS}${NC} $1"; }
17+
fail() { echo -e " ${ERROR}${NC} $1"; [ -n "${2:-}" ] && echo -e " ${MUTED}$2${NC}"; }
18+
hint() { echo -e " ${MUTED}$1${NC}"; }
19+
20+
section() {
21+
echo ""
22+
echo -e " ${ACCENT}${BOLD}$1${NC}"
23+
}
24+
25+
trap 'rm -f idpishield coverage.out 2>/dev/null' EXIT
26+
27+
echo ""
28+
echo -e " ${ACCENT}${BOLD}🛡️ idpishield Check${NC}"
29+
echo -e " ${MUTED}Running pre-push checks (matches GitHub Actions CI)...${NC}"
30+
31+
# ── Format ───────────────────────────────────────────────────────────
32+
33+
section "Format"
34+
635
unformatted=$(gofmt -l .)
736
if [ -n "$unformatted" ]; then
8-
echo "Unformatted files:"
9-
echo "$unformatted"
37+
fail "gofmt" "Files not formatted:"
38+
echo "$unformatted" | while read f; do hint " $f"; done
39+
echo ""
40+
printf " Fix formatting now? (Y/n) "
41+
read -r answer
42+
if [ "$answer" != "n" ] && [ "$answer" != "N" ]; then
43+
gofmt -w .
44+
ok "gofmt (fixed)"
45+
else
46+
hint "Run: gofmt -w ."
47+
exit 1
48+
fi
49+
else
50+
ok "gofmt"
51+
fi
52+
53+
# ── Vet ──────────────────────────────────────────────────────────────
54+
55+
section "Vet"
56+
57+
if ! go vet ./... 2>&1; then
58+
fail "go vet"
59+
exit 1
60+
fi
61+
ok "go vet"
62+
63+
# ── Build ────────────────────────────────────────────────────────────
64+
65+
section "Build"
66+
67+
if ! go build -o idpishield ./cmd/idpishield 2>&1; then
68+
fail "go build"
1069
exit 1
1170
fi
12-
echo "OK"
71+
ok "go build"
72+
73+
# ── Lint ─────────────────────────────────────────────────────────────
74+
75+
section "Lint"
1376

14-
echo "=== Vet ==="
15-
go vet ./...
16-
echo "OK"
77+
LINT_CMD=""
78+
if command -v golangci-lint >/dev/null 2>&1; then
79+
LINT_CMD="golangci-lint"
80+
elif [ -x "$HOME/bin/golangci-lint" ]; then
81+
LINT_CMD="$HOME/bin/golangci-lint"
82+
elif [ -x "/usr/local/bin/golangci-lint" ]; then
83+
LINT_CMD="/usr/local/bin/golangci-lint"
84+
fi
1785

18-
echo "=== Lint ==="
19-
golangci-lint run
20-
echo "OK"
86+
if [ -n "$LINT_CMD" ]; then
87+
if ! $LINT_CMD run ./...; then
88+
fail "golangci-lint"
89+
exit 1
90+
fi
91+
ok "golangci-lint"
92+
else
93+
echo -e " ${ACCENT}·${NC} golangci-lint not installed — skipping"
94+
hint "Install: brew install golangci-lint"
95+
fi
2196

22-
echo "=== Tests ==="
23-
go test ./... -count=1 -race
24-
echo "OK"
97+
# ── Summary ──────────────────────────────────────────────────────────
2598

99+
section "Summary"
100+
echo ""
101+
echo -e " ${SUCCESS}${BOLD}All checks passed!${NC} Ready to push."
26102
echo ""
27-
echo "All checks passed."

scripts/doctor.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,44 @@ fi
174174

175175
section "Optional Tools"
176176

177+
# ── gotestsum (for better test output) ──────────────────────────────
178+
179+
TOOLS_BIN="$ROOT_DIR/.tools/bin"
180+
GOTESTSUM_FOUND=false
181+
182+
if command -v gotestsum &>/dev/null; then
183+
GOTESTSUM_FOUND=true
184+
ok "gotestsum $(gotestsum --version 2>/dev/null | head -1)"
185+
elif [ -x "$TOOLS_BIN/gotestsum" ]; then
186+
GOTESTSUM_FOUND=true
187+
ok "gotestsum (local .tools/bin)"
188+
elif [ -x "$(go env GOPATH 2>/dev/null)/bin/gotestsum" ]; then
189+
GOTESTSUM_FOUND=true
190+
ok "gotestsum (GOPATH/bin)"
191+
fi
192+
193+
if ! $GOTESTSUM_FOUND; then
194+
warn "gotestsum not found" "Optional — provides cleaner test output."
195+
if command -v go &>/dev/null && confirm "Install gotestsum via go install?"; then
196+
go install gotest.tools/gotestsum@latest && ok "gotestsum installed" && WARNINGS=$((WARNINGS - 1))
197+
else
198+
hint "go install gotest.tools/gotestsum@latest"
199+
fi
200+
fi
201+
202+
# ── jq (for test summary parsing) ───────────────────────────────────
203+
204+
if command -v jq &>/dev/null; then
205+
ok "jq $(jq --version 2>/dev/null)"
206+
else
207+
warn "jq not found" "Optional — needed for test summary when gotestsum unavailable."
208+
if $HAS_BREW && confirm "Install jq via brew?"; then
209+
brew install jq && ok "jq installed" && WARNINGS=$((WARNINGS - 1))
210+
else
211+
hint "brew install jq"
212+
fi
213+
fi
214+
177215
# ── Docker (for E2E) ────────────────────────────────────────────────
178216

179217
if command -v docker &>/dev/null; then

0 commit comments

Comments
 (0)