Repository navigation
docs: Quick Start Guide と Keycloak 自動セットアップスクリプト追加 - #37
Conversation
- Quick Start Guide (docs/QUICKSTART.md) を追加 - Docker Desktop の起動手順 - Keycloak の起動と設定手順 - Control Plane UI の起動手順 - トラブルシューティング - Keycloak 自動セットアップスクリプト (scripts/setup-keycloak.sh) を追加 - Realm と Client の自動作成 - Client Secret の自動生成と表示 - 環境変数設定の自動出力 - Keycloak README を更新 - 自動セットアップ手順を追記 - Quick Start Guide へのリンク追加 所要時間: 5〜10分で起動可能 Refs: Plan.md "NextAuth.js + Keycloak 認証統合 - 2025-11-13" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. WalkthroughAdds local Quick Start documentation and an automated Keycloak setup script; updates Keycloak README to prefer the automated flow and adds a manual fallback; applies stylistic string-quote normalizations across the control-plane frontend and introduces an explicit API early-return in middleware. Changes
Sequence Diagram(s)sequenceDiagram
actor Developer
participant Script as setup-keycloak.sh
participant Keycloak as Keycloak API
Developer->>Script: run script
Script->>Keycloak: poll /health (retry loop)
alt healthy
Keycloak-->>Script: 200 OK
end
Script->>Keycloak: POST token (master realm)
Keycloak-->>Script: admin access token
Script->>Keycloak: GET /realms/{name}
alt realm missing
Script->>Keycloak: POST create realm
Keycloak-->>Script: realm created
end
Script->>Keycloak: GET /clients?clientId={id}
alt client missing
Script->>Keycloak: POST create client (OIDC, redirects, webOrigins)
Keycloak-->>Script: client created (id)
end
Script->>Keycloak: GET /clients/{id}/client-secret
Keycloak-->>Script: client secret
Script->>Developer: print credentials + .env.local instructions
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (15)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
docs/QUICKSTART.md (1)
45-90: Consider referencing the automated setup script in this guide.The QUICKSTART guide details manual Keycloak setup (realm and client creation), but
infrastructure/docker/keycloak/scripts/setup-keycloak.shis available to automate these steps. To reduce user confusion and encourage the recommended workflow, consider:
- Adding a note at the start of section 3 suggesting users run the automated setup script first (reference:
./scripts/setup-keycloak.shfrominfrastructure/docker/keycloak).- Positioning manual steps as a fallback or troubleshooting reference.
This aligns with the PR objective to promote automated setup as the primary method.
Also applies to: 180-184
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
docs/QUICKSTART.md(1 hunks)infrastructure/docker/keycloak/README.md(1 hunks)infrastructure/docker/keycloak/scripts/setup-keycloak.sh(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude-review
🔇 Additional comments (11)
infrastructure/docker/keycloak/scripts/setup-keycloak.sh (3)
1-14: Script initialization and error handling look solid.The use of
set -e, appropriate defaults, and hardcoded development-friendly values are well-suited for this automated setup context.
19-37: Retry logic and health check are appropriate for local development.The 30-attempt retry with 2-second intervals provides ~60 seconds of wait time, which is reasonable for Keycloak startup. Using the
/health/readyendpoint is correct.
137-156: Output and user guidance are clear and helpful.The formatted output section provides all necessary credentials and next-step instructions. Users have clear guidance on populating
.env.localand generatingAUTH_SECRET.docs/QUICKSTART.md (5)
94-94: Verify relative path references are correct.The path references need verification against actual repository structure:
- Line 94:
cd ../../frontend/control-plane(from docs/)- Line 151:
cd ../../../frontend/control-plane(from script output, assuming execution location)Confirm these paths align with the actual directory structure. If the repository layout differs, these paths may fail for users following the guide.
Can you verify the actual repository structure and confirm the correct relative paths? Alternatively, I can generate a verification script to check the paths.
Also applies to: 151-151
91-119: Environment configuration section is well-structured and complete.The .env.local setup instructions are clear, with proper variable names and values. The security reminder about not committing
.env.localis appropriate and well-placed.
143-162: Verification steps are clear and follow a realistic user journey.The login/logout flow testing provides good coverage of the happy path.
164-223: Troubleshooting section provides practical guidance.Comprehensive coverage of common issues with diagnostic commands and solutions. Port conflict resolution and error message explanations are helpful.
245-248: Verify consistency of path conventions in links.Path references for internal links (e.g.,
../frontend/control-plane/README.mdon line 246) should be verified to match the directory structure. Also ensure consistency with the navigation paths mentioned in earlier sections (e.g., line 94).infrastructure/docker/keycloak/README.md (3)
13-30: Automated setup section clearly prioritizes the recommended workflow.Positioning the automated setup as "Method 1" with the "(推奨)" recommendation is effective. The integration flow is clear: docker compose up → script execution → populate environment variables.
32-34: Manual setup appropriately documented as secondary option.Directing users to the QUICKSTART guide for manual setup avoids duplication and clearly marks this as the fallback method.
36-51: Cleanup section provides helpful options for different scenarios.Documenting
docker compose down,stop, anddown -vvariants helps users manage development environment state effectively.
| TOKEN_RESPONSE=$(curl -s -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \ | ||
| -H "Content-Type: application/x-www-form-urlencoded" \ | ||
| -d "username=${ADMIN_USER}" \ | ||
| -d "password=${ADMIN_PASSWORD}" \ | ||
| -d "grant_type=password" \ | ||
| -d "client_id=admin-cli") | ||
|
|
||
| ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*' | sed 's/"access_token":"//') | ||
|
|
||
| if [ -z "$ACCESS_TOKEN" ]; then | ||
| echo "❌ 管理者トークンの取得に失敗しました" | ||
| echo "レスポンス: $TOKEN_RESPONSE" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
Replace grep/sed JSON parsing with jq for robustness.
Using grep/sed to extract JSON values (line 50) is fragile and may fail if the response contains escaped characters, line breaks, or unexpected formatting. This could silently produce an empty or incorrect token, causing misleading errors downstream.
Apply this diff to use jq for reliable JSON parsing:
-ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*' | sed 's/"access_token":"//')
+ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.access_token // empty')Verify that jq is available in your execution environment (it's typically pre-installed on most systems or easily added to Docker images).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| TOKEN_RESPONSE=$(curl -s -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \ | |
| -H "Content-Type: application/x-www-form-urlencoded" \ | |
| -d "username=${ADMIN_USER}" \ | |
| -d "password=${ADMIN_PASSWORD}" \ | |
| -d "grant_type=password" \ | |
| -d "client_id=admin-cli") | |
| ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*' | sed 's/"access_token":"//') | |
| if [ -z "$ACCESS_TOKEN" ]; then | |
| echo "❌ 管理者トークンの取得に失敗しました" | |
| echo "レスポンス: $TOKEN_RESPONSE" | |
| exit 1 | |
| fi | |
| TOKEN_RESPONSE=$(curl -s -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \ | |
| -H "Content-Type: application/x-www-form-urlencoded" \ | |
| -d "username=${ADMIN_USER}" \ | |
| -d "password=${ADMIN_PASSWORD}" \ | |
| -d "grant_type=password" \ | |
| -d "client_id=admin-cli") | |
| ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.access_token // empty') | |
| if [ -z "$ACCESS_TOKEN" ]; then | |
| echo "❌ 管理者トークンの取得に失敗しました" | |
| echo "レスポンス: $TOKEN_RESPONSE" | |
| exit 1 | |
| fi |
🤖 Prompt for AI Agents
in infrastructure/docker/keycloak/scripts/setup-keycloak.sh around lines 43 to
56, the script uses grep/sed to extract the access_token from the JSON response
which is fragile; replace that extraction with jq (e.g., TOKEN_RESPONSE stored,
then ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.access_token') ), add a
check that jq is available before use (exit with a clear message if not), and
preserve the existing failure branch by checking for empty ACCESS_TOKEN and
printing TOKEN_RESPONSE on error; ensure jq -r is used so null/empty results
produce an empty string rather than "null".
| curl -s -X POST "${KEYCLOAK_URL}/admin/realms" \ | ||
| -H "Authorization: Bearer ${ACCESS_TOKEN}" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d "{ | ||
| \"realm\": \"${REALM_NAME}\", | ||
| \"enabled\": true, | ||
| \"displayName\": \"TenkaCloud\", | ||
| \"loginTheme\": \"keycloak\", | ||
| \"sslRequired\": \"none\" | ||
| }" > /dev/null |
There was a problem hiding this comment.
Add error checking to realm and client creation requests.
The realm (line 71) and client creation (line 97) curl commands pipe output to /dev/null without checking for HTTP errors. If these POST requests fail (e.g., 400, 403), the script continues silently and may fail later with confusing errors.
Add error checking to catch failed creations early:
# Realm を作成
echo "📝 Realm '${REALM_NAME}' を作成しています..."
- curl -s -X POST "${KEYCLOAK_URL}/admin/realms" \
+ REALM_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "${KEYCLOAK_URL}/admin/realms" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"realm\": \"${REALM_NAME}\",
\"enabled\": true,
\"displayName\": \"TenkaCloud\",
\"loginTheme\": \"keycloak\",
\"sslRequired\": \"none\"
- }" > /dev/null
+ }")
+ HTTP_CODE=$(echo "$REALM_RESPONSE" | tail -1)
+ if [ "$HTTP_CODE" != "201" ]; then
+ echo "❌ Realm 作成に失敗しました (HTTP $HTTP_CODE)"
+ exit 1
+ fiApply similar checks to the client creation section.
Also applies to: 97-113
🤖 Prompt for AI Agents
in infrastructure/docker/keycloak/scripts/setup-keycloak.sh around lines 71-80
(and similarly for client creation around 97-113), the curl POSTs send output to
/dev/null and don't check HTTP status so failures are silent; change each curl
invocation to capture both response body and HTTP status (for example using -w
'%{http_code}' and storing output), check that the status is a 2xx value, and if
not log the response and an error message to stderr and exit with a non-zero
code to stop the script; apply the same pattern to the client creation block so
any 4xx/5xx responses are detected and cause an immediate, informative failure.
| CLIENT_UUID=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients?clientId=${CLIENT_ID}" \ | ||
| -H "Authorization: Bearer ${ACCESS_TOKEN}" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//') |
There was a problem hiding this comment.
Replace grep/sed JSON parsing with jq for client UUID extraction.
Client UUID extraction (lines 90, 117) suffers from the same fragility as the token parsing issue. JSON parsing via grep/sed is error-prone.
Apply this diff to both occurrences:
-CLIENT_UUID=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients?clientId=${CLIENT_ID}" \
- -H "Authorization: Bearer ${ACCESS_TOKEN}" | grep -o '"id":"[^"]*' | head -1 | sed 's/"id":"//')
+CLIENT_UUID=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients?clientId=${CLIENT_ID}" \
+ -H "Authorization: Bearer ${ACCESS_TOKEN}" | jq -r '.[0].id // empty')This is cleaner and handles the array response directly without needing head and sed.
Also applies to: 116-117
🤖 Prompt for AI Agents
in infrastructure/docker/keycloak/scripts/setup-keycloak.sh around lines 89-90
(and similarly 116-117), the client UUID is being extracted using fragile
grep/sed parsing of JSON; replace those pipelines with jq to parse the JSON
array and extract the first object's id field reliably (use jq -r '.[0].id' on
the curl output or pipe through jq to select the matching client then .id),
ensuring the curl response is passed into jq and still authenticated with the
same Authorization header; update both occurrences accordingly and handle
empty/null results if jq returns no id.
| echo "🔐 Client Secret を取得しています..." | ||
| CLIENT_SECRET=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/client-secret" \ | ||
| -H "Authorization: Bearer ${ACCESS_TOKEN}" | grep -o '"value":"[^"]*' | sed 's/"value":"//') | ||
|
|
||
| if [ -z "$CLIENT_SECRET" ]; then | ||
| echo "❌ Client Secret の取得に失敗しました" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
Replace grep/sed JSON parsing with jq for client secret extraction.
Line 127 uses the same fragile grep/sed pattern for JSON parsing.
Apply this diff:
-CLIENT_SECRET=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/client-secret" \
- -H "Authorization: Bearer ${ACCESS_TOKEN}" | grep -o '"value":"[^"]*' | sed 's/"value":"//')
+CLIENT_SECRET=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/client-secret" \
+ -H "Authorization: Bearer ${ACCESS_TOKEN}" | jq -r '.value // empty')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| echo "🔐 Client Secret を取得しています..." | |
| CLIENT_SECRET=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/client-secret" \ | |
| -H "Authorization: Bearer ${ACCESS_TOKEN}" | grep -o '"value":"[^"]*' | sed 's/"value":"//') | |
| if [ -z "$CLIENT_SECRET" ]; then | |
| echo "❌ Client Secret の取得に失敗しました" | |
| exit 1 | |
| fi | |
| echo "🔐 Client Secret を取得しています..." | |
| CLIENT_SECRET=$(curl -s "${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/client-secret" \ | |
| -H "Authorization: Bearer ${ACCESS_TOKEN}" | jq -r '.value // empty') | |
| if [ -z "$CLIENT_SECRET" ]; then | |
| echo "❌ Client Secret の取得に失敗しました" | |
| exit 1 | |
| fi |
🤖 Prompt for AI Agents
in infrastructure/docker/keycloak/scripts/setup-keycloak.sh around lines 125 to
132, the client secret is extracted using fragile grep/sed; replace that
pipeline with jq to robustly parse the JSON response: call curl as before and
pipe to jq -r '.value' to extract the client secret, assign that to
CLIENT_SECRET, and keep the subsequent empty-check/exit behavior unchanged so
failure still logs and exits with code 1.
|
PR Review: Quick Start Guide と Keycloak 自動セットアップスクリプト こんにちは! PR 37 のレビューを実施しました。全体的に非常に良い実装です。 良い点1. ドキュメントの質が高い
2. 自動化スクリプトが堅牢
3. ユーザー体験の向上
改善提案1. Critical: JSON パース処理の脆弱性ファイル: infrastructure/docker/keycloak/scripts/setup-keycloak.sh:50, 90, 127 問題: grep + sed による JSON パースは脆弱で、予期しない形式のレスポンスに対応できません 推奨修正: jq を使用した堅牢な JSON パース 理由:
依存関係: docs/QUICKSTART.md の前提条件に jq を追加してください 2. Medium: エラーメッセージの標準エラー出力すべてのエラーメッセージに >&2 を追加してください。 3. Medium: ShellCheck 導入シェルスクリプトの品質保証のため ShellCheck を導入し、CI に統合してください。 4. Medium: リンク切れの確認docs/QUICKSTART.md:246 の frontend/control-plane/README.md へのリンクが存在するか確認してください。 テストカバレッジ不足している項目
総合評価
承認条件以下の修正を実施後、承認可能です:
その他の推奨事項は、マージ後の別 PR で対応しても問題ありません。 素晴らしい実装です!特に初心者向けドキュメントの充実度が高く、TenkaCloud のオンボーディング体験を大幅に向上させるPRです 🎉 🤖 Generated with Claude Code |
PR Review - Quick Start Guide と Keycloak 自動セットアップスクリプト全体として、開発者体験を大幅に向上させる素晴らしい PR です!CLAUDE.md のコンセプトに沿った、実用的で親切なドキュメントとツールの追加になっています。以下、詳細なレビューフィードバックをお送りします。 ✅ 強み・評価ポイント1. 優れた開発者体験 (Developer Experience)
2. コードの一貫性向上
3. セキュリティ意識
4. スクリプトの堅牢性
🔍 改善提案1. Bash スクリプトのセキュリティと堅牢性🔴 Critical: JSON パース処理の脆弱性場所: 問題: 推奨: 代替案 (jq を必須にしたくない場合):
🟡 Medium: エラーメッセージの改善場所: 問題: Client が存在しない場合、CLIENT_UUID が空になり、API リクエストが失敗しますが、エラーメッセージには具体的な原因が示されません。 推奨: CLIENT_UUID の存在チェックを追加し、より詳細なエラーメッセージを表示 🟡 Medium: シェルスクリプトのベストプラクティス推奨: より厳格なエラーハンドリング
2. ドキュメントの改善🟡 Medium: Quick Start Guide のパス問題場所: 問題: 相対パス 推奨: リポジトリルートからの絶対的な手順として統一するか、両方のパターンを明記 🟢 Nice-to-Have: スクリーンショットの追加PR 説明に「スクリーンショット追加予定」とありますが、以下があると更に良いです:
後続の PR で追加予定であれば問題ありません。 3. テストカバレッジ🟡 Medium: スクリプトの自動テスト場所: 現状: スクリプトの動作確認は手動のみで、CI/CD での自動テストがありません。 推奨: bats-core を使用した自動テスト、または簡易的な smoke test スクリプトの追加 PR 説明の「次のステップ」に記載あり: 「スクリプトのテストを追加(bats など)」 → これで OK です。Issue 化して追跡することを推奨します。 4. CI/CD 統合🟢 Nice-to-Have: GitHub Actions での検証Quick Start Guide の手順が実際に動作することを CI で検証することを推奨します。 📝 細かい指摘1. タイポ・表記ゆれ
|
概要
TenkaCloud Control Plane UI を 5〜10 分で起動できる Quick Start Guide と Keycloak の自動セットアップスクリプトを追加しました。
変更内容
1. Quick Start Guide (
docs/QUICKSTART.md)含まれる内容:
対象ユーザー: 初めて TenkaCloud を動かす開発者
所要時間: 約 5〜10 分
2. Keycloak 自動セットアップスクリプト
ファイル:
infrastructure/docker/keycloak/scripts/setup-keycloak.sh機能:
control-plane-uiClient を自動作成.env.localに設定すべき環境変数を出力使い方:
cd infrastructure/docker/keycloak docker compose up -d ./scripts/setup-keycloak.sh出力例:
3. Keycloak README の更新
変更点:
テスト
chmod +x)利用シーン
新規開発者のオンボーディング
CI/CD での自動テスト
スクリーンショット
(オプション)後で追加予定:
参照
次のステップ
🤖 Generated with Claude Code
Summary by CodeRabbit
Documentation
New Features
Style