blob: e0c9bed53f04a3066d1fbecc99b8474f66bdebd3 (
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
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
|
#!/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 status/app.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 "=== hetzner-admin: SERVICES が run-command.sh / status/targets.txt と一致するか ==="
admin_services=$(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", "") == "SERVICES":
print(" ".join(e.value for e in node.value.elts))
EOF
)
script_services=$(sed -n 's/^SERVICES="\(.*\)"$/\1/p' hetzner-admin/run-command.sh)
if [[ "$admin_services" == "$script_services" ]]; then
ok "app.py と run-command.sh の SERVICES が一致"
else
ng "SERVICES 不一致: app.py=[$admin_services] run-command.sh=[$script_services]"
fi
for name in $admin_services; do
if ! grep -qE "^ +$name\) " hetzner-admin/run-command.sh; then
ng "run-command.sh の service_compose に $name がない"
elif ! grep -qE "^$name\s" status/targets.txt; then
ng "status/targets.txt に $name がない(ステータスページと連動しない)"
else
ok "service: $name"
fi
done
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
|