forked from jhd3197/ServerKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreflight.sh
More file actions
149 lines (136 loc) · 6.06 KB
/
Copy pathpreflight.sh
File metadata and controls
149 lines (136 loc) · 6.06 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
#!/usr/bin/env bash
# Run the checks that fail CI without running the whole suite.
#
# Every red backend-CI round on 2026-08-21 was a ratchet, not a broken feature:
# a floor measured on a dev box, a fingerprint baseline left unregenerated after
# a refactor, a ceiling that moved with the code, a generated doc gone stale,
# and a text-grep guard that matched a docstring. None of them need the 4-shard
# suite to catch -- they are AST and text scans over the tree, and they all run
# here in about two minutes.
#
# Usage (from anywhere):
#
# bash scripts/preflight.sh
# PYTHON=~/sk-venv/bin/python bash scripts/preflight.sh
#
# The interpreter needs the backend's dependencies (flask, sqlalchemy, pytest).
# On the Windows dev box that means the WSL venv, which also reaches Windows
# node through interop, so one invocation covers both halves:
#
# wsl -e bash -lc "cd /mnt/c/Users/<you>/Documents/GitHub/ServerKit && \
# PYTHON=~/sk-venv/bin/python bash scripts/preflight.sh"
#
# Exit code is 0 only when every check that ran passed.
set -uo pipefail
cd "$(dirname "$0")/.." || exit 1
REPO=$(pwd)
PYTHON=${PYTHON:-python3}
command -v "$PYTHON" >/dev/null 2>&1 || PYTHON=python
if ! command -v "$PYTHON" >/dev/null 2>&1; then
echo "preflight: no python interpreter found (set PYTHON=/path/to/python)" >&2
exit 2
fi
# node, or Windows node.exe reached from WSL. In the latter case every path
# handed to it has to be a Windows path or it resolves against C:\.
NODE=''
NODE_NEEDS_WINPATH=0
if command -v node >/dev/null 2>&1; then
NODE=node
elif command -v node.exe >/dev/null 2>&1 && command -v wslpath >/dev/null 2>&1; then
NODE=node.exe
NODE_NEEDS_WINPATH=1
elif [ -x /mnt/c/nvm4w/nodejs/node.exe ] && command -v wslpath >/dev/null 2>&1; then
NODE=/mnt/c/nvm4w/nodejs/node.exe
NODE_NEEDS_WINPATH=1
fi
node_path() {
if [ "$NODE_NEEDS_WINPATH" -eq 1 ]; then
wslpath -w "$1"
else
printf '%s' "$1"
fi
}
FAILED=''
SKIPPED=''
note_fail() { FAILED="${FAILED}${1}"$'\n'; }
note_skip() { SKIPPED="${SKIPPED}${1}"$'\n'; }
banner() { printf '\n\033[1m== %s\033[0m\n' "$1"; }
# ---------------------------------------------------------------------------
# 1. Test-count ratchet -- the floor CI compares against.
# ---------------------------------------------------------------------------
banner 'test-count ratchet'
if ! (cd "$REPO/backend" && "$PYTHON" tests/check_test_count.py); then
note_fail 'test-count ratchet'
fi
# ---------------------------------------------------------------------------
# 2. Backend ratchets, censuses, and guards.
#
# Matched by filename rather than listed, so a new ratchet is covered the day it
# lands instead of the day someone remembers to add it here.
# ---------------------------------------------------------------------------
banner 'backend ratchets and guards'
guard_files=$(cd "$REPO/backend" && ls tests/test_*ratchet*.py tests/test_*census*.py \
tests/test_*guard*.py tests/test_*boundar*.py tests/test_*inventory*.py \
tests/test_*drift*.py tests/test_*spec*.py 2>/dev/null | tr '\n' ' ')
if [ -n "$guard_files" ]; then
# shellcheck disable=SC2086
if ! (cd "$REPO/backend" && PYTHONPATH=. FLASK_ENV=testing "$PYTHON" -m pytest \
$guard_files -q -p no:cacheprovider -p no:warnings); then
note_fail 'backend ratchets and guards'
fi
else
echo 'no matching test files'
note_skip 'backend ratchets and guards (no matching test files)'
fi
# ---------------------------------------------------------------------------
# 3. Frontend boundary check + the generated inventory that reads it.
#
# test_migration_inventory.py SKIPS when node is missing, which is how the
# inventory reached CI stale: the check that would have caught it never ran.
# ---------------------------------------------------------------------------
if [ -n "$NODE" ]; then
banner 'frontend boundaries'
if ! (cd "$REPO/frontend" && "$NODE" "$(node_path "$REPO/frontend/scripts/check-frontend-boundaries.mjs")"); then
note_fail 'frontend boundaries'
fi
banner 'builtin frontend drift'
# Extensions CI red on 2026-08-30: a builtin-extensions/ manifest changed
# without re-running the sync, and nothing local caught it. Same contract
# as the inventory below: a fixable failure is fixed, then flagged so the
# diff gets reviewed and committed.
if (cd "$REPO" && "$NODE" "$(node_path "$REPO/scripts/sync-builtin-frontends.mjs")" --check >/dev/null 2>&1); then
echo 'pre-bundled copies match builtin-extensions/ sources'
elif (cd "$REPO" && "$NODE" "$(node_path "$REPO/scripts/sync-builtin-frontends.mjs")"); then
echo 'pre-bundled copies were stale and have been re-synced -- review and commit the diff' >&2
note_fail 'builtin frontend drift (re-synced; commit the diff)'
else
note_fail 'builtin frontend drift (sync script failed)'
fi
banner 'migration inventory is regenerated'
# Compared against a snapshot of the file, NOT against HEAD: an uncommitted
# but correct regeneration is a pass, and only a number that actually moved
# is a failure.
doc="$REPO/docs/MIGRATION_INVENTORY.md"
before=$(mktemp)
cp "$doc" "$before" 2>/dev/null
if ! "$PYTHON" "$REPO/scripts/generate-migration-inventory.py" >/dev/null; then
note_fail 'migration inventory (generator failed)'
elif cmp -s "$doc" "$before"; then
echo 'docs/MIGRATION_INVENTORY.md matches the measured state'
else
echo 'docs/MIGRATION_INVENTORY.md was stale and has been regenerated -- review and commit the diff' >&2
note_fail 'migration inventory (regenerated; commit the diff)'
fi
rm -f "$before"
else
note_skip 'frontend boundaries + builtin frontend drift + migration inventory (no node on PATH)'
fi
# ---------------------------------------------------------------------------
banner 'preflight summary'
[ -n "$SKIPPED" ] && printf '%s' "$SKIPPED" | sed 's/^/ SKIPPED /'
if [ -z "$FAILED" ]; then
echo ' PASS everything CI checks outside the sharded suite'
exit 0
fi
printf '%s' "$FAILED" | sed 's/^/ FAILED /'
exit 1