AnyBot/deploy/ci/lint-sh.sh

45 lines
1.6 KiB
Bash
Raw Normal View History

#!/bin/sh
# Shell lint for the install scripts. Two checks:
# 1. POSIX syntax (sh -n) for every .sh we ship.
# 2. $VAR or ${VAR} glued to a non-ASCII character, which macOS's /bin/sh
# (bash 3.2) reads as part of the variable name: "($X;…" is an unbound
# variable there even when X is set, and install.sh runs with set -u.
# Write ${X}與… — braces fix it.
# Run: make lint-sh
set -u
cd "$(dirname "$0")/../.." || exit 1
fail=0
for f in install.sh $(find deploy -name '*.sh' | sort); do
if sh -n "$f" 2>/tmp/anybot-sh-lint.log; then
printf ' ✓ %s\n' "$f"
else
printf ' ✗ %s\n' "$f"; sed 's/^/ /' /tmp/anybot-sh-lint.log; fail=1
fi
done
printf '\n'
python3 - <<'PY' || fail=1
import glob, re, os, sys
pat = re.compile(r'(?<![A-Za-z0-9_$\\])\$([A-Za-z_][A-Za-z0-9_]*)([^\x00-\x7f])')
root = os.getcwd()
files = []
for d, dirs, fs in os.walk('.'):
dirs[:] = [x for x in dirs if x not in ('target', '.git', 'node_modules')]
files += [os.path.join(d, x) for x in fs if x.endswith('.sh')]
bad = 0
for f in sorted(files):
for i, line in enumerate(open(f, encoding='utf-8'), 1):
if line.strip().startswith('#'):
continue
for m in pat.finditer(line):
print(f' ✗ {f}:{i}: ${m.group(1)}{m.group(2)} → 在 macOS 的 /bin/sh 是未設定變數(改用 ${{{m.group(1)}}}{m.group(2)})')
print(f' {line.strip()[:100]}')
bad += 1
print(' ✓ no $VAR glued to Chinese punctuation' if not bad else f' {bad} places to fix')
sys.exit(1 if bad else 0)
PY
[ "$fail" = 0 ] && printf '\n 都過了。\n' || printf '\n 有東西要修。\n'
exit $fail