summaryrefslogtreecommitdiff
path: root/tests/check.sh
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