blob: 99add68561d486d8788fc52054afcb8550046965 (
plain)
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
|
#!/usr/bin/env bash
# リポジトリの整合性チェック。push 前に実行する: bash tests/check.sh
set -uo pipefail
cd "$(dirname "$0")/.."
FAIL=0
ok() { echo " ok: $*"; }
ng() { echo " NG: $*"; FAIL=1; }
echo "=== シェルスクリプト構文 ==="
while IFS= read -r f; do
if bash -n "$f" 2>/dev/null; then
ok "$f"
else
ng "$f"
bash -n "$f" || true
fi
done < <(find . -name '*.sh' -not -path './.git/*' | sort)
while IFS= read -r f; do
if bash -n "$f" 2>/dev/null; then
ok "$f"
else
ng "$f"
bash -n "$f" || true
fi
done < <(find git/hooks -type f -name 'post-receive' | sort)
echo ""
echo "=== Python 構文 ==="
for f in hetzner-admin/app.py mail/dns/setup-route53.py; do
if python3 -m py_compile "$f" 2>/dev/null; then
ok "$f"
else
ng "$f"
python3 -m py_compile "$f" || true
fi
done
echo ""
echo "=== repos.txt と git/hooks/ の整合性 ==="
mapfile -t repos < <(grep -vE '^\s*(#|$)' git/repos.txt | cut -d: -f1)
for repo in "${repos[@]}"; do
if [[ -f "git/hooks/$repo/post-receive" ]]; then
ok "repos.txt: $repo → hooks あり"
else
ng "repos.txt: $repo のフックがない (git/hooks/$repo/post-receive)"
fi
done
for dir in git/hooks/*/; do
name="$(basename "$dir")"
if printf '%s\n' "${repos[@]}" | grep -qx "$name"; then
ok "hooks: $name → repos.txt に定義あり"
else
ng "hooks: $name が repos.txt に定義されていない"
fi
done
echo ""
echo "=== sessions.txt のリポジトリが repos.txt に存在するか ==="
while IFS=: read -r user repo; do
[[ "$user" =~ ^#.*$ || -z "$user" ]] && continue
if printf '%s\n' "${repos[@]}" | grep -qx "$repo"; then
ok "sessions.txt: $user:$repo"
else
ng "sessions.txt: $repo が repos.txt に定義されていない"
fi
done < claude/sessions.txt
echo ""
echo "=== hetzner-admin: app.py の COMMANDS が run-command.sh で許可されているか ==="
while IFS= read -r cmd; do
if grep -qF "\"$cmd\")" hetzner-admin/run-command.sh; then
ok "$cmd"
else
ng "run-command.sh のホワイトリストにない: $cmd"
fi
done < <(python3 - <<'EOF'
import ast
tree = ast.parse(open("hetzner-admin/app.py").read())
for node in ast.walk(tree):
if isinstance(node, ast.Assign) and getattr(node.targets[0], "id", "") == "COMMANDS":
for elt in node.value.elts:
print(elt.elts[1].value)
EOF
)
echo ""
echo "=== 秘密ファイルがコミットされていないか ==="
for name in users.conf id_rsa id_rsa.pub .env; do
regex="(^|/)$(printf '%s' "$name" | sed 's/\./\\./g')\$"
if git ls-files | grep -qE "$regex"; then
ng "コミットされている: $(git ls-files | grep -E "$regex")"
else
ok "$name は未コミット"
fi
done
echo ""
echo "=== Caddyfile 検証(docker が使える場合のみ) ==="
if docker info >/dev/null 2>&1 && docker image inspect caddy-caddy:latest >/dev/null 2>&1; then
if docker run --rm -v "$PWD/caddy:/etc/caddy:ro" caddy-caddy:latest \
caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then
ok "Caddyfile valid"
else
ng "Caddyfile が無効"
fi
else
echo " skip: docker にアクセスできない(root で実行すると検証される)"
fi
echo ""
if [[ "$FAIL" -eq 0 ]]; then
echo "All checks passed."
else
echo "FAILED: 上記の NG を修正してください。"
exit 1
fi
|