-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck-dead-code.sh
More file actions
executable file
·112 lines (100 loc) · 4.25 KB
/
Copy pathcheck-dead-code.sh
File metadata and controls
executable file
·112 lines (100 loc) · 4.25 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
#!/usr/bin/env bash
#
# Dead-code gate. Canonical copy: offworldlabs/ops, check-dead-code.sh.
#
# Consumed by other repos as a pre-commit hook, pinned by rev:
#
# - repo: https://github.com/offworldlabs/ops
# rev: <latest hooks-v*.* tag — see the repo's tag list or README>
# hooks:
# - id: dead-code
#
# No version is named here on purpose. This file is frozen inside whatever tag
# a consumer pinned, so any version written here is guaranteed wrong for every
# release after it. The README on main is the current reference.
#
# Do not vendor this file. Change it here, publish a hooks-v<MAJOR>.<MINOR>
# tag (the dot matters — pre-commit warns "mutable reference" without one), then
# bump rev in the consumers (`pre-commit autoupdate` does that for you).
#
# check-dead-code.sh # fail if anything unwhitelisted is dead
# check-dead-code.sh --list # print findings without failing
# check-dead-code.sh backend # scan a subdirectory
#
# Why this wraps vulture rather than calling it directly:
#
# Tests are SCANNED but not REPORTED. Excluding tests entirely — the obvious
# setup — makes anything used only by tests look dead, which is the largest
# single source of false positives. Scanning them fixes that, but then unused
# test helpers become findings in their own right. So we scan everything and
# drop findings whose location is a test file.
#
# Build artefacts are excluded because they contain a stale copy of the source,
# which doubles every finding.
set -euo pipefail
# Scan the current directory by default; pre-commit sets CWD to the consumer
# repo root. An optional positional argument scopes it (retina-server passes
# "backend"). This replaces a cd relative to the script's own location, which
# is meaningless now the script lives in a pre-commit cache.
LIST_ONLY=0
TARGET="."
for arg in "$@"; do
case "$arg" in
--list) LIST_ONLY=1 ;;
-*) echo "check-dead-code: unknown option: $arg" >&2; exit 2 ;;
*) TARGET="$arg" ;;
esac
done
cd "$TARGET" || { echo "check-dead-code: cannot enter target: $TARGET" >&2; exit 2; }
# Fail closed (ops README convention 4: fail loudly). A missing tool is not a
# clean scan, and this gate used to report one as the other: the shell's
# "command not found" went to /dev/null and `|| true` discarded exit 127.
if ! command -v vulture >/dev/null 2>&1; then
echo "check-dead-code: vulture is not installed or not on PATH" >&2
echo " install it with: pip install vulture==2.14" >&2
exit 127
fi
EXCLUDE=".venv,scripts,htmlcov,__pycache__,node_modules,build,dist,*.egg-info"
# Framework-dispatched handlers: Flask (@bp/@app) and FastAPI (@router/@app).
DECORATORS="@app.*,@bp.*,@router.*"
WHITELIST=""
# Redundant in practice: vulture already picks this up when it walks ".", so
# passing it explicitly changes nothing (verified against vulture 2.14). Kept
# as an explicit statement of intent; removing it is safe but would need a
# version bump to reach consumers.
[ -f vulture_whitelist.py ] && WHITELIST="vulture_whitelist.py"
stderr_file="$(mktemp)"
trap 'rm -f "$stderr_file"' EXIT
set +e
raw="$(vulture . $WHITELIST \
--min-confidence 60 \
--exclude "$EXCLUDE" \
--ignore-decorators "$DECORATORS" \
2>"$stderr_file")"
status=$?
set -e
# vulture 2.x exit codes (vulture.utils.ExitCode): 0 NoDeadCode, 1 InvalidInput,
# 2 InvalidCmdlineArguments, 3 DeadCode. Only 0 and 3 mean vulture ran fine —
# 1 and 2 are real failures and must propagate rather than read as "clean".
case "$status" in
0|3) ;;
*) echo "check-dead-code: vulture exited $status" >&2
cat "$stderr_file" >&2
exit "$status" ;;
esac
# `|| true` is correct here and only here: grep exits 1 when it filters
# everything out, which is the clean case. The bug this script had was applying
# the same `|| true` to the whole pipeline, where it also swallowed exit 127.
findings="$(printf '%s\n' "$raw" | grep -vE '(^|/)tests?/|/test_|conftest\.py' || true)"
if [ -z "$findings" ]; then
echo "no dead code found"
exit 0
fi
echo "$findings"
if [ "$LIST_ONLY" = "1" ]; then
exit 0
fi
echo >&2
echo "Dead code found. Delete it, or — only if it is referenced dynamically and" >&2
echo "vulture cannot see that — add it to vulture_whitelist.py with a reason." >&2
exit 1