Skip to content

Add production post-deploy validation script and README guidance for Cloudflare Tunnel#83

Open
MEECHAIN1 wants to merge 8 commits into
mainfrom
codex/check-docker-container-status
Open

Add production post-deploy validation script and README guidance for Cloudflare Tunnel#83
MEECHAIN1 wants to merge 8 commits into
mainfrom
codex/check-docker-container-status

Conversation

@MEECHAIN1

@MEECHAIN1 MEECHAIN1 commented May 6, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Provide a repeatable post-deploy validation flow to verify app shell, health endpoints, RPC proxy, network config, DNS and Cloudflare Tunnel targets after docker compose up -d.
  • Document and recommend using a named Cloudflare Tunnel (meechain-connect) for stable production hostnames instead of ephemeral quick tunnels.
  • Offer guidance for environments behind Cloudflare Access and for quick-tunnel vs named-tunnel cutovers.
  • Make it easy to run these checks locally or in CI with a single script and environment variables to control strictness and timeouts.

Description

  • Added a new production validation script scripts/test-production.sh that performs DNS resolution checks, optional CNAME target verification, app shell content check, /health, /api/health, /rpc/health, RPC JSON-RPC calls (eth_chainId, eth_blockNumber), and /api/network and /api/web3/status checks.
  • The script supports flags --insecure, --skip-network, --skip-app, --also, --timeout and env vars EXPECTED_CNAME_TARGET, EXPECTED_CNAME_STRICT, EXPECT_UPSTREAM_CONNECTED, CF_ACCESS_CLIENT_ID, and CF_ACCESS_CLIENT_SECRET for Cloudflare Access headers.
  • Updated README.md with a new "Production post-deploy validation" section, usage examples for npm run test:prod and bash scripts/test-production.sh, and detailed guidance on switching DNS to a named Cloudflare Tunnel and handling quick-tunnel caveats.
  • The script normalizes origin URLs, emits machine-friendly pass/warn/fail messages, and exits non-zero on failures so it can be used in CI pipelines.

Testing

  • No automated tests were run as part of this change.

Codex Task

Summary by CodeRabbit

บันทึกประจำรุ่น

  • Documentation

    • เพิ่มส่วน “Production post-deploy validation” พร้อมขั้นตอนตรวจสุขภาพหลายจุด (รวมถึง RPC, เครือข่าย, Web3) และตัวอย่างคำสั่ง
    • ขยายคู่มือการสลับ routing ไปใช้ Named Tunnel รวมถึงขั้นตอนตรวจสอบและตัวอย่างการ cutover
    • เสริมแนวทางการใช้งานหลังเปิด Cloudflare Access ด้วย service tokens และการตรวจ RPC หลัง Cloudflare
  • Tests

    • เพิ่มชุดทดสอบอัตโนมัติสำหรับสคริปต์ตรวจสอบ production ครอบคลุมโหมด CLI, การ normalize URL, การตรวจ endpoint/ฟิลด์, timeout, Cloudflare Access headers และตรรกะ warn vs fail ตามค่า CNAME

@vercel

vercel Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
connect.meechain Error Error May 6, 2026 11:05am
mee-chain-connect Ready Ready Preview, Comment May 6, 2026 11:05am
meebot Error Error May 6, 2026 11:05am
meechain Error Error May 6, 2026 11:05am
meechain-connect Error Error May 6, 2026 11:05am

Request Review

@railway-app

railway-app Bot commented May 6, 2026

Copy link
Copy Markdown

🚅 Deployed to the MeeChain-Connect-pr-83 environment in meechain

5 services not affected by this PR
  • Redis-wHAO
  • Postgres-X79I
  • Postgres
  • MeeChain
  • Redis

@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

PR นี้นำเสนอโครงสร้างพื้นฐานสำหรับตรวจสอบหลังการปรับใช้ระบบโปรดักชั่น: สคริปต์ Bash ใหม่ (scripts/test-production.sh) ที่ดำเนินการตรวจสอบความสมบูรณ์ที่ครอบคลุม (health endpoints, RPC proxy, network config, DNS/CNAME) พร้อมเอกสาร README ที่อัปเดต (คำแนะนำการย้าย Named Tunnel, การตั้งค่า Cloudflare Access) และชุดทดสอบ integration ที่ยืนยัน CLI behavior, happy paths, และ failure modes ทั้งหมด

This PR introduces production post-deployment validation infrastructure: a new Bash script (scripts/test-production.sh) that orchestrates comprehensive health checks (health endpoints, RPC proxy, network config, DNS/CNAME), and updated README documentation guiding Named Tunnel migration, Cloudflare Access configuration, and validation procedures.


Changes

Production Validation Checkpoint / จุดตรวจสอบโปรดักชั่น

Layer / File(s) Summary
Documentation and script bootstrap
README.md, scripts/test-production.sh (lines 1–94)
อัปเดต README ด้วยส่วน post-deploy validation, Named Tunnel switching, Cloudflare Access setup; สคริปต์เริ่มต้นด้วย usage(), default config, argument parsing, และ helper functions สำหรับ output/command validation.

README updated with post-deploy validation section, Named Tunnel switching guidance, and Cloudflare Access configuration; script bootstraps with usage(), default config, argument parsing, and helper functions for output and command validation.
HTTP and JSON validation utilities
scripts/test-production.sh (lines 122–266)
URL normalization ผ่าน Node.js origin extraction, curl args setup พร้อม timeout/-k handling, Cloudflare Access header assembly; assertion functions สำหรับ HTTP status, JSON field equality/presence/truthiness ตามตรรกะ fail/warn, และ body text content matching.

URL normalization via Node.js origin extraction, curl args with timeout/-k handling, Cloudflare Access header setup; assertion functions for HTTP status, JSON field equality/presence/truthiness by fail/warn logic, and body text matching.
Health, RPC proxy, and network config checks
scripts/test-production.sh (lines 268–331)
check_app_shell() ตรวจ / สำหรับ brand text (ยืนยัน --skip-app); check_health_endpoints() เรียก /health, /api/health, /rpc/health พร้อม status/version/chainId verify; check_rpc_proxy() POST eth_chainId และ eth_blockNumber; check_network_config() ตรวจ /api/network chainId และ /api/web3/status upstream connectivity.

check_app_shell() verifies / for brand text (respects --skip-app); check_health_endpoints() calls /health, /api/health, /rpc/health with status/version/chainId verification; check_rpc_proxy() POSTs eth_chainId and eth_blockNumber; check_network_config() verifies /api/network chainId and /api/web3/status upstream connectivity.
DNS resolution and CNAME validation
scripts/test-production.sh (lines 334–397)
normalize_dns_name() ปรับรูปแบบ DNS names; check_expected_cname_target() ดึง CNAME ด้วย dig/nslookup และเปรียบเทียบกับ EXPECTED_CNAME_TARGET โดย fail/warn ตาม EXPECTED_CNAME_STRICT; check_external_network() ดึง hostname และตรวจ DNS resolution.

normalize_dns_name() normalizes DNS formats; check_expected_cname_target() retrieves CNAME via dig/nslookup and compares against EXPECTED_CNAME_TARGET with fail/warn logic by EXPECTED_CNAME_STRICT; check_external_network() extracts hostname and verifies DNS resolution.
Validation orchestration and main entry
scripts/test-production.sh (lines 399–444)
run_checks_for_base_url() ทำให้ BASE_URL เป็น origin, รันเช็คตามลำดับ (network → app → health → RPC → network config), พิมพ์ข้อความสรุป; main() รวม primary และ additional URLs, ต้องการ curl/node, สรุปผลรวมทั้งหมด.

run_checks_for_base_url() normalizes BASE_URL to origin, runs checks in sequence (network → app → health → RPC → network config), prints summary; main() aggregates primary and additional URLs, requires curl/node, outputs total summary.
Test harness and mock server
test/test-production-script.test.js (lines 1–136)
runScript() helper เรียก bash sync พร้อม env overrides; mock server factory สร้าง default handlers สำหรับ /, /health, /api/health, /rpc/health, POST /rpc, /api/network, /api/web3/status พร้อมรองรับ override; random port allocation และ error handling.

runScript() helper invokes bash sync with env overrides; mock server factory creates default handlers for /, /health, /api/health, /rpc/health, POST /rpc, /api/network, /api/web3/status with override support; random port and error handling.
CLI and URL normalization tests
test/test-production-script.test.js (lines 137–259)
ทดสอบ --help/-h, unknown flags, missing arguments, script existence/executability, default BASE_URL; URL normalization ด้วย origin, trailing slash strip, trycloudflare path removal; PROD_TEST_ADDITIONAL_URLS comma-separated parsing.

Tests --help/-h, unknown flags, missing arguments, script existence/executability, default BASE_URL; URL normalization with origin, trailing slash strip, trycloudflare path removal; PROD_TEST_ADDITIONAL_URLS comma-separated parsing.
Integration happy-path and skip behavior
test/test-production-script.test.js (lines 260–327)
happy-path integration พร้อม mock server (--skip-network) ตรวจ exit 0, pass signals, "Base URL:" output, "all production validation checklists passed" summary; --skip-app tests ยืนยัน app content check ข้ามหรือรัน ตามการตั้ง flag.

happy-path integration with mock server (--skip-network) verifies exit 0, pass signals, "Base URL:" output, "all production validation checklists passed" summary; --skip-app tests confirm app content check skipped/run by flag.
HTTP error and JSON field mismatch tests
test/test-production-script.test.js (lines 328–456)
ทดสอบ non-200 responses (500 /health, 404 /, 503 /api/health) และ JSON field mismatches (status ≠ ok, chainId wrong, eth_chainId mismatch, missing version) พร้อมตรวจ stderr messages.

Tests non-200 responses (500 /health, 404 /, 503 /api/health) and JSON field mismatches (status ≠ ok, chainId wrong, eth_chainId mismatch, missing version) with stderr message verification.
Upstream connectivity and redirect detection
test/test-production-script.test.js (lines 457–539)
EXPECT_UPSTREAM_CONNECTED fail/warn logic ตาม env setting และ data.connected value; Cloudflare Access redirect detection โดยจำลอง 302 + Location ไป cloudflareaccess.com พร้อมตรวจ non-zero exit.

EXPECT_UPSTREAM_CONNECTED fail/warn logic by env setting and data.connected value; Cloudflare Access redirect detection by simulating 302 + Location to cloudflareaccess.com with non-zero exit verification.
Multi-URL orchestration and env overrides
test/test-production-script.test.js (lines 540–696)
--also flag multi-URL run (pass when both succeed, fail when secondary fails); PROD_TEST_ADDITIONAL_URLS parsing/execution; EXPECTED_CHAIN_ID_HEX/DEC override tests; EXPECTED_APP_TEXT custom brand text override.

--also flag multi-URL run (pass when both succeed, fail when secondary fails); PROD_TEST_ADDITIONAL_URLS parsing/execution; EXPECTED_CHAIN_ID_HEX/DEC override tests; EXPECTED_APP_TEXT custom brand text override.
Cloudflare Access headers and DNS CNAME strict mode
test/test-production-script.test.js (lines 697–824)
CF_ACCESS_CLIENT_ID/CF_ACCESS_CLIENT_SECRET header forwarding tests; EXPECTED_CNAME_TARGET/EXPECTED_CNAME_STRICT fail/warn logic; --timeout flag acceptance; regression test สำหรับ --skip-network --skip-app combined case.

CF_ACCESS_CLIENT_ID/CF_ACCESS_CLIENT_SECRET header forwarding tests; EXPECTED_CNAME_TARGET/EXPECTED_CNAME_STRICT fail/warn logic; --timeout flag acceptance; regression test for --skip-network --skip-app combined case.

Sequence Diagram

sequenceDiagram
    actor User as ผู้ใช้ / User
    participant Script as test-production.sh
    participant App as MeeChain App / MeeChain แอป
    participant RPC as RPC Proxy
    participant DNS as DNS Resolver
    participant CF as Cloudflare Access

    User->>Script: npm run test:prod [--options]
    Script->>App: GET /health (root health check)
    App-->>Script: 200 + {status, version}
    Script->>App: GET /api/health
    App-->>Script: 200 + {status, chainId}
    Script->>RPC: GET /health
    RPC-->>Script: 200 + {chainId, mode}
    Script->>RPC: POST eth_chainId (JSON-RPC call)
    RPC-->>Script: 200 + {result: "0x..."}
    Script->>RPC: POST eth_blockNumber
    RPC-->>Script: 200 + {result: "0x..."}
    Script->>DNS: Resolve DNS name / แก้ไขชื่อ DNS
    DNS-->>Script: A/CNAME records
    Script->>DNS: Verify CNAME target / ตรวจสอบเป้าหมาย CNAME
    DNS-->>Script: Expected target confirmed / ยืนยันเป้าหมายที่คาดไว้
    alt Cloudflare Access Required / จำเป็นต้องมี Cloudflare Access
        Script->>CF: Include CF_ACCESS tokens in headers / รวมโทเค็น CF_ACCESS ในส่วนหัว
        CF-->>Script: Access granted / ได้รับอนุญาตการเข้าถึง
    end
    Script-->>User: ✓ All checks passed / ✓ ผ่านการตรวจสอบทั้งหมด
Loading

Estimated Code Review Effort

🎯 3 (Moderate / ปานกลาง) | ⏱️ ~25 minutes


Possibly Related PRs

  • MEECHAIN1/MeeChain-Connect#16: Both PRs add bash-based verification scripts that validate RPC/API health responses—main PR's test-production.sh checks eth_chainId plus /api/health//api/web3/status using EXPECTED_CHAIN_ID_HEX/DEC, matching the retrieved PR's verify-onboarding.sh flow and EXPECTED_CHAIN_ID_HEX-based chainId verification.
  • MEECHAIN1/MeeChain-Connect#44: Main PR adds a production post-deploy validation script/tests that exercise the same RPC proxy/health endpoints (e.g., /rpc and health/status routes) whose behavior was changed and documented in #44 (RPC proxy timeout/circuit-breaker fixes and related health/RPC diagnostics), so the changes are directly connected.
  • MEECHAIN1/MeeChain-Connect#90: The main PR's scripts/test-production.sh/test-production-script.test.js validates the /api/network response, and PR #90 updates that same endpoint to include the rpcGateway profile metadata—so the production validation logic is directly impacted by the network payload changes.

Poem

🚀 Production checks now flow with grace / การตรวจสอบโปรดักชั่นไหลได้อย่างสวยงาม
Health endpoints dance through cyberspace / ปลายทางความสุขเต้นในอวกาศไซเบอร์
DNS resolved, RPC calls ring true / DNS แก้ไขแล้ว การเรียก RPC ดังกึ่งเสียง
Cloudflare gates let the right requests through / ประตู Cloudflare ปล่อยให้คำขอที่ถูกต้องผ่าน
Deploy with confidence, validate with care / ปรับใช้ด้วยความมั่นใจ ตรวจสอบด้วยความดูแล
Safety and speed blend in the air ✨ / ความปลอดภัยและความเร็วผสมกันในอากาศ ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly describes the main changes: adding a production post-deploy validation script and README guidance for Cloudflare Tunnel, which aligns perfectly with the file changes (test-production.sh, README updates).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/check-docker-container-status
⚔️ Resolve merge conflicts

❌ Error resolving conflicts.

  • Resolve merge conflict in branch codex/check-docker-container-status

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 6, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
meechain-connect 33be238 May 06 2026, 11:06 AM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/test-production.sh`:
- Around line 308-320: The join of multiple CNAME targets uses "$(printf '%s'
"$targets" | paste -sd ', ' -)" which incorrectly treats ', ' as alternating
single-character delimiters; update the message construction so targets are
joined with the literal string ", " instead of alternating delimiters — locate
the expression used inside the message variable (around the variables targets
and message and before the EXPECTED_CNAME_STRICT check) and replace it with a
join that produces "a, b, c" (for example: join with paste -sd',' - then insert
spaces, or use awk/printf to append ", " between entries and trim the trailing
separator) so the fail/warn output shows properly spaced comma-separated
targets.
- Around line 275-283: The assertion in check_network_config() that compares
"data.rpcUrls && data.rpcUrls[0]" to "${BASE_URL}/rpc" fails for secondary/proxy
URLs; change it to use an override ENV var (EXPECTED_RPC_URL) when present:
compute expected_rpc_url="${EXPECTED_RPC_URL:-${BASE_URL}/rpc}" and use that in
the assert_json_field_equals call for "network first rpcUrl"; keep BASE_URL
logic and other checks unchanged so callers can set EXPECTED_RPC_URL when
validating standby/Cloudflare-tunnel URLs.
- Around line 286-290: The normalize_dns_name function uses bash-only lowercase
expansion `${name,,}` which fails on macOS bash 3.2; update normalize_dns_name
to perform lowercase conversion using a POSIX-safe tr pipeline instead (preserve
the existing removal of a trailing dot via `${name%.}` then pipe the resulting
value through tr '[:upper:]' '[:lower:]'), and ensure the function still prints
the normalized name with printf '%s\n' so callers like those using
EXPECTED_CNAME_TARGET behave identically.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 98c8a11b-dd4f-4622-be77-f26a493a3b53

📥 Commits

Reviewing files that changed from the base of the PR and between 04b77e0 and 33be238.

📒 Files selected for processing (2)
  • README.md
  • scripts/test-production.sh

Comment thread scripts/test-production.sh
Comment on lines +286 to +290
normalize_dns_name() {
local name="$1"
name="${name%.}"
printf '%s\n' "${name,,}"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does bash 3.2 on macOS support ${var,,} lowercase parameter expansion?

💡 Result:

No. Bash 3.2 on macOS does not support the lowercase parameter expansion syntax ${var,,}. In bash, the case-modification parameter expansion forms ${parameter,pattern} and ${parameter,,pattern} (including ${parameter,,} to lowercase all matched characters) are defined in the “Shell Parameter Expansion” section of the Bash Reference Manual [1]. Those case-modification operators were introduced with Bash 4.0+; accordingly, they are not available in older Bash versions such as 3.2.x shipped on macOS [2][3]. What you’ll see in practice on Bash 3.2 is an error like “bad substitution” when trying ${var,,}, while Bash 4.0+ accepts it [4]. For macOS default Bash 3.2, use a different approach such as tr (e.g., echo "$VAR" | tr '[:upper:]' '[:lower:]') as suggested for Bash 3 [5].

Citations:


🏁 Script executed:

# First, check if the file exists and get its line count
wc -l scripts/test-production.sh

Repository: MEECHAIN1/MeeChain-Connect

Length of output: 101


🏁 Script executed:

# Read the relevant sections of the file to verify the claims
sed -n '275,320p' scripts/test-production.sh | cat -n

Repository: MEECHAIN1/MeeChain-Connect

Length of output: 2178


${name,,} ไม่รองรับใน bash 3.2 ที่มาพร้อม macOS ค่าเริ่มต้น

English: The ${var,,} parameter expansion for lowercase conversion requires bash 4.0+. Since macOS ships with /bin/bash 3.2.57 by default, invoking normalize_dns_name when EXPECTED_CNAME_TARGET is set will abort with bad substitution. Lines 300 and 302 in the same file already use the POSIX-portable tr '[:upper:]' '[:lower:]' idiom for the same operation.

ภาษาไทย: ${name,,} ต้องการ bash 4.0 ขึ้นไป ขณะที่ macOS ใช้ /bin/bash 3.2.57 เป็นค่าเริ่มต้น ทำให้เมื่อ EXPECTED_CNAME_TARGET ถูกตั้งค่าและเรียก normalize_dns_name จะล้มเหลวด้วย bad substitution ควรใช้ tr '[:upper:]' '[:lower:]' เหมือนที่ใช้ในบรรทัด 300 และ 302 แทน

🐛 แนวทางแก้ไข / Proposed fix
 normalize_dns_name() {
   local name="$1"
   name="${name%.}"
-  printf '%s\n' "${name,,}"
+  printf '%s\n' "$(printf '%s' "$name" | tr '[:upper:]' '[:lower:]')"
 }
📝 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.

Suggested change
normalize_dns_name() {
local name="$1"
name="${name%.}"
printf '%s\n' "${name,,}"
}
normalize_dns_name() {
local name="$1"
name="${name%.}"
printf '%s\n' "$(printf '%s' "$name" | tr '[:upper:]' '[:lower:]')"
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test-production.sh` around lines 286 - 290, The normalize_dns_name
function uses bash-only lowercase expansion `${name,,}` which fails on macOS
bash 3.2; update normalize_dns_name to perform lowercase conversion using a
POSIX-safe tr pipeline instead (preserve the existing removal of a trailing dot
via `${name%.}` then pipe the resulting value through tr '[:upper:]'
'[:lower:]'), and ensure the function still prints the normalized name with
printf '%s\n' so callers like those using EXPECTED_CNAME_TARGET behave
identically.

Comment on lines +308 to +320
fi

local message="CNAME target for $host does not visibly match $EXPECTED_CNAME_TARGET"
if [[ -n "$targets" ]]; then
message="$message (observed: $(printf '%s' "$targets" | paste -sd ', ' -))"
else
message="$message (no CNAME visible; Cloudflare orange-cloud proxy can hide the target behind edge A/AAAA records)"
fi

if [[ "$EXPECTED_CNAME_STRICT" == "1" ]]; then
fail "$message"
fi
warn "$message"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

paste -sd', ' วนซ้ำ delimiter แยกกัน , และ — ผลลัพธ์ผิดเมื่อมีหลาย CNAME targets

English: paste -d treats its argument as a list of individual delimiter characters that cycle in turn. So -d', ' means , is delimiter #1 and (space) is delimiter #2. For two targets the output is a,b (no space), and for three targets the paste command will cycle: , then alternating, producing a,b c instead of the intended a, b, c. While a single CNAME target is the overwhelming norm, the formatter should still be correct.

ภาษาไทย: paste -d', ' ใช้ , และ เป็น delimiter สองตัวสลับกัน ไม่ใช่สตริง ", " ทั้งก้อน สำหรับ 2 targets จะได้ a,b (ไม่มีช่องว่าง) สำหรับ 3 targets จะได้ a,b c แทนที่จะเป็น a, b, c

🐛 แนวทางแก้ไข / Proposed fix
-    message="$message (observed: $(printf '%s' "$targets" | paste -sd ', ' -))"
+    message="$message (observed: $(printf '%s\n' $targets | paste -sd ',' - | sed 's/,/, /g'))"

หรือวิธีที่ง่ายกว่า / alternatively:

-    message="$message (observed: $(printf '%s' "$targets" | paste -sd ', ' -))"
+    message="$message (observed: $(printf '%s\n' $targets | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g'))"
📝 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.

Suggested change
fi
local message="CNAME target for $host does not visibly match $EXPECTED_CNAME_TARGET"
if [[ -n "$targets" ]]; then
message="$message (observed: $(printf '%s' "$targets" | paste -sd ', ' -))"
else
message="$message (no CNAME visible; Cloudflare orange-cloud proxy can hide the target behind edge A/AAAA records)"
fi
if [[ "$EXPECTED_CNAME_STRICT" == "1" ]]; then
fail "$message"
fi
warn "$message"
fi
local message="CNAME target for $host does not visibly match $EXPECTED_CNAME_TARGET"
if [[ -n "$targets" ]]; then
message="$message (observed: $(printf '%s\n' $targets | paste -sd ',' - | sed 's/,/, /g'))"
else
message="$message (no CNAME visible; Cloudflare orange-cloud proxy can hide the target behind edge A/AAAA records)"
fi
if [[ "$EXPECTED_CNAME_STRICT" == "1" ]]; then
fail "$message"
fi
warn "$message"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test-production.sh` around lines 308 - 320, The join of multiple
CNAME targets uses "$(printf '%s' "$targets" | paste -sd ', ' -)" which
incorrectly treats ', ' as alternating single-character delimiters; update the
message construction so targets are joined with the literal string ", " instead
of alternating delimiters — locate the expression used inside the message
variable (around the variables targets and message and before the
EXPECTED_CNAME_STRICT check) and replace it with a join that produces "a, b, c"
(for example: join with paste -sd',' - then insert spaces, or use awk/printf to
append ", " between entries and trim the trailing separator) so the fail/warn
output shows properly spaced comma-separated targets.


json_field() {
local expression="$1"
node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); const value=($expression); if (value === undefined || value === null) process.exit(3); console.log(typeof value === 'object' ? JSON.stringify(value) : value);" "$BODY"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); const value=($expression); if (value === undefined || value === null) process.exit(3); console.log(typeof value === 'object' ? JSON.stringify(value) : value);" "$BODY"
node -e "const fs=require('fs'); const obj=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); const data = (typeof obj.data !== 'undefined') ? obj.data : obj; const value=($expression); if (value === undefined || value === null) process.exit(3); console.log(typeof value === 'object' ? JSON.stringify(value) : value);" "$BODY"

Test script expects API responses wrapped in 'data' property, but server returns unwrapped responses, causing all JSON field assertions to fail with "missing or invalid JSON field" errors

Fix on Vercel

@MEECHAIN1 MEECHAIN1 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

2 similar comments
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

✅ Unit tests committed locally. Commit: b1ae11795ebd3633a465e60908f345da30e38035

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/test-production-script.test.js (1)

277-280: ⚡ Quick win

หลีกเลี่ยงการรันสคริปต์ซ้ำใน assertion เดียว / Avoid running the script twice in one assertion

Line 279 เรียก runScript อีกรอบเพื่อเอา stderr ไปใส่ข้อความ assert ทำให้เทสต์ช้าลงและเพิ่มโอกาส flaky โดยไม่จำเป็น.
Line 279 executes a second full script run just to build the assert message, which adds avoidable runtime and flakiness risk.

♻️ Proposed refactor
-    const { status, stdout } = runScript([base, '--skip-network']);
-    assert.strictEqual(status, 0, `Expected exit 0; stderr: ${runScript([base, '--skip-network']).stderr}`);
+    const { status, stdout, stderr } = runScript([base, '--skip-network']);
+    assert.strictEqual(status, 0, `Expected exit 0; stderr: ${stderr}`);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/test-production-script.test.js` around lines 277 - 280, The test is
calling runScript twice unnecessarily - once to capture status and stdout, and
again inside the assertion message to get stderr. Store the complete result of
runScript in a single variable that captures status, stdout, and stderr
together, then reuse that stored stderr value in the assertion message instead
of executing runScript a second time. This will improve test performance and
reduce flakiness risk.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/test-production-script.test.js`:
- Around line 114-120: The startMockServer function has a type mismatch: the
default parameter handlerOverrides is set to an empty object {} on line 114, but
line 119 treats it as a function by calling handlerOverrides(base). When
startMockServer is called without arguments, this causes a TypeError. Change the
default parameter from an empty object to a function that returns an empty
object, so the default should be handlerOverrides = () => ({}) instead of
handlerOverrides = {}, ensuring it can be safely called as a function regardless
of whether an argument is provided.

---

Nitpick comments:
In `@test/test-production-script.test.js`:
- Around line 277-280: The test is calling runScript twice unnecessarily - once
to capture status and stdout, and again inside the assertion message to get
stderr. Store the complete result of runScript in a single variable that
captures status, stdout, and stderr together, then reuse that stored stderr
value in the assertion message instead of executing runScript a second time.
This will improve test performance and reduce flakiness risk.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 509e4373-fd4f-484d-bbd1-f39f4fe9a274

📥 Commits

Reviewing files that changed from the base of the PR and between 33be238 and b1ae117.

📒 Files selected for processing (1)
  • test/test-production-script.test.js

Comment thread test/test-production-script.test.js
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

✅ Created PR with unit tests: #99

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Note

Docstrings generation - SUCCESS
Generated docstrings and committed to branch codex/check-docker-container-status (commit: c012185df4b6f8428a04caab0d0e6b794db5539d)

Docstrings generation was requested by @MEECHAIN1.

* #83 (comment)

The following files were modified:

* `scripts/test-production.sh`
Docstrings generation was requested by @coderabbitai[bot].

The following files were modified:

* `scripts/test-production.sh`

These files were ignored:
* `test/test-production-script.test.js`

These file types are not supported:
* `README.md`
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Request timed out after 900000ms (requestId=958bc22e-6223-4e68-87ff-a6e60f3744be)

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Request timed out after 900000ms (requestId=1930472a-1c97-429a-b4d5-4cd0db32fb69)

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a public access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

Docstrings generation was requested by @coderabbitai[bot].

The following files were modified:

* `scripts/test-production.sh`

These files were ignored:
* `test/test-production-script.test.js`

These file types are not supported:
* `README.md`
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

✅ Created PR with unit tests: #101

Docstrings generation was requested by @MEECHAIN1.

The following files were modified:

* `scripts/test-production.sh`

These file types are not supported:
* `README.md`
MEECHAIN1 added a commit that referenced this pull request Jun 19, 2026
Unit test generation was requested by @MEECHAIN1.

*
#83 (comment)

The following files were modified:

* `test/test-production-script.test.js`
…docstrings/b1ae117

Signed-off-by: ธณวัฒน์ ประวันตา <pouaun2499@gmail.com>
Docstrings generation was requested by @MEECHAIN1.

*
#83 (comment)

The following files were modified:

* `scripts/test-production.sh`

<details>
<summary>These file types are not supported</summary>

* `README.md`

</details>

<details>
<summary>ℹ️ Note</summary><blockquote>

CodeRabbit cannot perform edits on its own pull requests yet.

</blockquote></details>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
test/test-production-script.test.js (1)

114-120: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

ค่าเริ่มต้น handlerOverrides ยังไม่สอดคล้องกับการเรียกใช้ / handlerOverrides default is still incompatible with invocation

ตอนนี้ Line 114 ตั้งค่าเริ่มต้นเป็น object แต่ Line 119 เรียกเป็นฟังก์ชัน (handlerOverrides(base)) ทำให้มีโอกาสเกิด TypeError หากเรียก startMockServer() โดยไม่ส่งอาร์กิวเมนต์
At Line 114 the default is an object, but Line 119 invokes it as a function, so startMockServer() can throw TypeError when called without overrides.

Proposed minimal fix
-function startMockServer(handlerOverrides = {}) {
+function startMockServer(handlerOverrides = () => ({})) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/test-production-script.test.js` around lines 114 - 120, The
startMockServer function has a default parameter mismatch where handlerOverrides
is initialized as an empty object on line 114, but it is invoked as a function
on line 119 with handlerOverrides(base). Change the default value of the
handlerOverrides parameter from an object literal {} to a function that returns
an empty object, so it matches the function invocation pattern used in the
handlers assignment.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/test-production.sh`:
- Around line 95-112: The functions pass(), fail(), warn(), and info() are
defined twice in the script—once before line 95 and again after line 102. The
first set of definitions is completely shadowed by the second set, making it
dead code. Remove the first set of duplicate function definitions (pass, fail,
warn, and info) that appear before the second set, keeping only one complete
definition of each function to eliminate the redundancy and clean up the script.

---

Duplicate comments:
In `@test/test-production-script.test.js`:
- Around line 114-120: The startMockServer function has a default parameter
mismatch where handlerOverrides is initialized as an empty object on line 114,
but it is invoked as a function on line 119 with handlerOverrides(base). Change
the default value of the handlerOverrides parameter from an object literal {} to
a function that returns an empty object, so it matches the function invocation
pattern used in the handlers assignment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 24639983-96cd-45a5-bf23-8b978ae9abe7

📥 Commits

Reviewing files that changed from the base of the PR and between 33be238 and d00ae7b.

📒 Files selected for processing (2)
  • scripts/test-production.sh
  • test/test-production-script.test.js

Comment thread scripts/test-production.sh
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Failed to resolve merge conflicts

Unexpected error: Sandbox execution failed: failed

Please resolve conflicts manually.

@MEECHAIN1 MEECHAIN1 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant