diff --git a/CLAUDE.md b/CLAUDE.md index 5a4462c..a1943a2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -388,6 +388,31 @@ ssh keinafarm-claude 'sudo -u keinasystem git -C /home/keinasystem/keinasystem_t sudo -u keinasystem docker compose -f docker-compose.prod.yml --env-file .env.production up -d' ``` +### 本番確認手順(デプロイ後の必須チェック) + +**⚠️ Playwright(ビジュアルテスト)を使う前に、必ずcurlで先に確認すること。** +curlはキャッシュの影響を受けず、偽装不可能な確認手段。 + +```bash +# ステップ1: curlヘルスチェック(全9項目、所要約10秒) +bash scripts/check_prod.sh claude keina1234 +# → 全 9 項目 PASS が出れば本番が正常稼働中 + +# ステップ2(任意): Playwrightでビジュアル確認する場合のプロンプト原則 +# - 「認証できなければ即中止して報告せよ」を必ず明記 +# - 「スクリーンショットには今日の日付が画面内に見えること」を要求 +# - 「成功の証跡(HTTP レスポンスの実テキスト)を必ず添付すること」を要求 +``` + +**本番バックエンドのマイグレーション適用(バックエンド変更時のみ):** +```bash +ssh keinafarm-claude 'cd /home/keinasystem/keinasystem_t02 && \ + sudo -u keinasystem docker compose -f docker-compose.prod.yml --env-file .env.production build backend && \ + sudo -u keinasystem docker compose -f docker-compose.prod.yml --env-file .env.production up -d && \ + sleep 5 && \ + sudo -u keinasystem docker compose -f docker-compose.prod.yml --env-file .env.production exec backend python manage.py migrate' +``` + ### マイグレーションエラー ```bash diff --git a/scripts/check_prod.sh b/scripts/check_prod.sh new file mode 100644 index 0000000..3b023e2 --- /dev/null +++ b/scripts/check_prod.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# 本番環境ヘルスチェック +# 使い方: bash scripts/check_prod.sh [username] [password] +# 例: bash scripts/check_prod.sh claude keina1234 + +BASE="https://main.keinafarm.net" +USER="${1:-claude}" +PASS="${2:-keina1234}" + +OK=0 +NG=0 + +check() { + local label="$1" + local expected="$2" + local actual="$3" + if [ "$actual" = "$expected" ]; then + echo " PASS $label (HTTP $actual)" + OK=$((OK+1)) + else + echo " FAIL $label (expected $expected, got $actual)" + NG=$((NG+1)) + fi +} + +echo "=== 本番ヘルスチェック: $BASE ===" +echo "--- $(date '+%Y-%m-%d %H:%M:%S') ---" +echo "" + +# 1. フロントエンド到達確認 +echo "[1] フロントエンド" +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$BASE/") +check "トップページ" "200" "$STATUS" + +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$BASE/login") +check "ログインページ" "200" "$STATUS" + +# 2. バックエンドAPI(認証不要) +echo "" +echo "[2] バックエンドAPI(認証なし)" +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$BASE/api/auth/jwt/create/") +check "認証エンドポイント到達" "405" "$STATUS" # GETは405が正常 + +# 3. JWT取得 +echo "" +echo "[3] JWT認証" +TOKEN_RESP=$(curl -s --max-time 10 -X POST "$BASE/api/auth/jwt/create/" \ + -H "Content-Type: application/json" \ + -d "{\"username\":\"$USER\",\"password\":\"$PASS\"}") +ACCESS=$(echo "$TOKEN_RESP" | grep -o '"access":"[^"]*"' | cut -d'"' -f4) + +if [ -n "$ACCESS" ]; then + echo " PASS JWTトークン取得" + OK=$((OK+1)) +else + echo " FAIL JWTトークン取得失敗 (レスポンス: $TOKEN_RESP)" + NG=$((NG+1)) + echo "" + echo "=== 結果: PASS $OK / FAIL $NG (認証失敗のため以降の確認をスキップ) ===" + exit 1 +fi + +# 4. 認証が必要なAPI +echo "" +echo "[4] 認証済みAPI" +AUTH="Authorization: Bearer $ACCESS" + +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -H "$AUTH" "$BASE/api/fields/") +check "圃場一覧 API" "200" "$STATUS" + +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -H "$AUTH" "$BASE/api/plans/crops/") +check "品種一覧 API" "200" "$STATUS" + +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -H "$AUTH" "$BASE/api/fertilizer/fertilizers/") +check "肥料マスタ API" "200" "$STATUS" + +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -H "$AUTH" "$BASE/api/fertilizer/plans/?year=2026") +check "施肥計画一覧 API" "200" "$STATUS" + +STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -H "$AUTH" "$BASE/api/weather/summary/?year=2025") +check "気象データサマリー API" "200" "$STATUS" + +# 5. 結果サマリー +echo "" +TOTAL=$((OK+NG)) +if [ $NG -eq 0 ]; then + echo "=== 結果: 全 $TOTAL 項目 PASS ===" +else + echo "=== 結果: PASS $OK / FAIL $NG (合計 $TOTAL) ===" + exit 1 +fi