-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck_codebase.sh
More file actions
executable file
·212 lines (187 loc) · 5.85 KB
/
Copy pathcheck_codebase.sh
File metadata and controls
executable file
·212 lines (187 loc) · 5.85 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
#!/usr/bin/env bash
# check_codebase.sh - run the codebase check gate (no build).
#
# Runs (in order):
# 1. TypeScript typecheck via tsconfig.json (src/).
# 2. Wider typecheck via tsconfig.lint.json (tests/, tools/).
# 3. ESLint (zero warnings).
# 4. Prettier --check.
# 5. Node unit tests under tests/ (node --import tsx --test
# tests/test_*.mjs). The --import flag loads the tsx npm package
# (https://www.npmjs.com/package/tsx) as a runtime loader so .mjs
# tests can import .ts source modules directly. Note: tsx is the
# runtime loader npm package; tsc is the TypeScript compiler binary
# (shipped with the typescript package) and is not a separate npm
# package -- the two names look alike but are unrelated.
#
# Each step invokes its tool directly (npx tsc, npx eslint, npx prettier,
# node --test). No dependency on package.json scripts; the package.json
# "check" alias points at this script and stays canonical, but every
# individual step is owned by the shell script.
#
# Build is not part of this gate. Run ./build_github_pages.sh (or
# npm run build) for that. Playwright is not part of this gate either;
# run npm run test:playwright manually after bash run_web_server.sh.
#
# Flags:
# -h, --help Print usage and exit 0.
#
# A per-run summary is printed on exit (after preflight succeeds) listing
# PASS / FAIL / SKIP for each step. Exit code is 0 only when no step
# failed; preflight failures exit non-zero without a summary.
set -euo pipefail
# Usage
usage() {
cat <<'USAGE'
Usage: check_codebase.sh [-h|--help]
-h, --help Print this help and exit 0.
Each step runs its tool directly; package.json is not consulted.
USAGE
}
# Parse flags
while [ "$#" -gt 0 ]; do
case "$1" in
-h|--help)
usage
exit 0
;;
*)
echo "ERROR: unknown flag: $1" >&2
usage >&2
exit 2
;;
esac
done
# Preflight (no summary on failure)
cd "$(git rev-parse --show-toplevel)"
if ! command -v node >/dev/null 2>&1; then
echo "ERROR: node not found on PATH." >&2
exit 1
fi
if ! command -v npm >/dev/null 2>&1; then
echo "ERROR: npm not found on PATH." >&2
exit 1
fi
echo "node $(node --version), npm $(npm --version)"
if [ ! -f package.json ]; then
echo "ERROR: package.json missing." >&2
exit 1
fi
if [ ! -d node_modules ]; then
echo "ERROR: node_modules missing. Run 'npm install' first." >&2
exit 1
fi
if [ ! -f package-lock.json ]; then
echo "WARN: package-lock.json missing; npm install will not produce a reproducible install." >&2
fi
# Step tracking (bash 3.2 compatible)
STEP_NAMES=()
STEP_STATUS=()
STEP_NOTES=()
SUMMARY_ENABLED=0
# step_record <name> <status> [note]
step_record() {
STEP_NAMES+=("$1")
STEP_STATUS+=("$2")
if [ "$#" -ge 3 ]; then
STEP_NOTES+=("$3")
else
STEP_NOTES+=("")
fi
}
# step_skip <name> <reason>
step_skip() {
local name="$1"
local reason="$2"
echo "==> SKIP $name ($reason)"
step_record "$name" "SKIP" "$reason"
}
# step_run <name> <command...>
# Runs the given command. Records PASS or FAIL+summary+exit 1.
step_run() {
local name="$1"
shift
echo "==> $name"
local rc=0
set +e
"$@"
rc=$?
set -e
if [ "$rc" -eq 0 ]; then
step_record "$name" "PASS"
else
step_record "$name" "FAIL"
print_summary
trap - EXIT
exit 1
fi
}
# Summary
print_summary() {
if [ "$SUMMARY_ENABLED" != "1" ]; then
return 0
fi
local total=${#STEP_NAMES[@]}
local failed=0
local i=0
echo "Summary:"
while [ "$i" -lt "$total" ]; do
local name="${STEP_NAMES[$i]}"
local status="${STEP_STATUS[$i]}"
local note="${STEP_NOTES[$i]}"
if [ "$status" = "FAIL" ]; then
failed=$((failed + 1))
fi
if [ "$status" = "SKIP" ] && [ -n "$note" ]; then
echo " [$status] $name ($note)"
else
echo " [$status] $name"
fi
i=$((i + 1))
done
if [ "$failed" -eq 0 ]; then
echo "PASS: $total checks passed."
else
echo "FAIL: $failed of $total checks failed."
fi
}
trap print_summary EXIT
# Steps
SUMMARY_ENABLED=1
# 1. typecheck (always)
step_run typecheck npx tsc --noEmit -p tsconfig.json
# 2. typecheck:lint
# Wider typecheck covers tests/ and tools/ via tsconfig.lint.json.
# That file ships from the template's noexist/ bucket so every typescript
# consumer has it at bootstrap; no SKIP fallback needed.
# Note: `tsc -p tsconfig.lint.json` exits 2 with TS18003 if its include list
# matches no files. A consumer with no tests/*.ts and no tools/*.ts will hit
# this. Workaround: seed a stub `.ts` in either tree, or extend the include
# list locally in the consumer-owned tsconfig.lint.json.
step_run typecheck:lint npx tsc --noEmit -p tsconfig.lint.json
# 3. lint
# Single recursive glob covers every JS/TS extension from cwd: catches src/,
# tests/, tests/playwright/, tools/, root-level files, and any deeper monorepo
# layout (packages/*/src/, etc.) without code changes. --no-error-on-unmatched-pattern
# is deliberately not passed so an empty-match repo fails loudly instead of
# silently passing -- false-confidence prevention.
step_run lint npx eslint --max-warnings 0 '**/*.{ts,tsx,mts,cts,js,mjs,cjs}'
# 4. format:check
step_run format:check npx prettier --check '**/*.{ts,tsx,mts,cts,js,mjs,cjs}'
# 5. test:node
# Loads the tsx npm package as a runtime loader so .mjs tests can import
# .ts source modules. Not to be confused with tsc, which is the
# TypeScript compiler binary shipped inside the typescript package.
#
# compgen -G is used to check whether any tests/test_*.mjs files exist
# before invoking node --test. A fresh consumer with no test files emits a
# loud SKIP rather than failing the gate ("Could not find any tests") or
# silently passing -- same honesty principle as the lint step above.
if compgen -G 'tests/test_*.mjs' >/dev/null; then
step_run test:node node --import tsx --test 'tests/test_*.mjs'
else
step_skip test:node "no tests/test_*.mjs files present"
fi
# All steps complete; summary prints via EXIT trap. Exit 0 (no failures
# reach here -- failure paths exit 1 directly).
exit 0