[Fix-94] [INT][CH] Story 10.4 풀스택 스모크 리허설과 릴리스 증적 게이트를 구현#21
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a Story 10.4 release-readiness feature set: CI workflow, runbook/checklist docs, Bash and Node release-readiness scripts (smoke, observability, edge validation, session isolation, rollback rehearsal, evidence assembly), test helpers and runtime tests, and repo metadata updates for shell script handling. Changes
Sequence DiagramsequenceDiagram
participant GH as GitHub Actions
participant Lint as Lint & Test Runner
participant Smoke as Full-Stack Smoke
participant Observ as Observability Validator
participant Isolation as Session Isolation
participant Rollback as Rollback Rehearsal
participant Assemble as Evidence Assembler
participant Gate as Release Gate
GH->>Lint: run lint:release-readiness & tests
Lint-->>GH: results
GH->>Smoke: run-full-stack-smoke.sh
Smoke->>Observ: validate-observability-stack.sh
Observ-->>Smoke: observability results
Smoke-->>GH: emit cold-start/docs/smoke summaries
GH->>Isolation: run-five-session-isolation.mjs
Isolation-->>GH: emit session-isolation-summary.json
GH->>Rollback: run-rollback-rehearsal.sh
Rollback-->>GH: emit rollback-rehearsal-summary.json & go-no-go
GH->>Assemble: assemble-story-10-4-evidence.mjs
Assemble-->>GH: emit matrix-summary.json / matrix-summary.md
GH->>Gate: Enforce Story 10.4 Gate (aggregate outcomes)
Gate-->>GH: final pass/fail
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4e9bf60a-594c-489f-8c62-987ef70333fb
📒 Files selected for processing (17)
.gitattributes.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml.gitignoredocs/ops/full-stack-smoke-rehearsal-runbook.mddocs/ops/release-go-no-go-checklist-template.mdpackage.jsonscripts/observability/validate-observability-stack.shscripts/release-readiness/assemble-story-10-4-evidence.mjsscripts/release-readiness/run-five-session-isolation.mjsscripts/release-readiness/run-full-stack-smoke.shscripts/release-readiness/run-rollback-rehearsal.shtests/observability/observability-runtime.test.jstests/release-readiness/full-stack-smoke-runtime.test.jstests/release-readiness/release-readiness-docs.test.jstests/release-readiness/rollback-rehearsal-runtime.test.jstests/release-readiness/session-isolation-runtime.test.jstests/release-readiness/story-10-4-evidence-runtime.test.js
📜 Review details
⏰ 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: story-10-4-full-stack-smoke-rehearsal
🧰 Additional context used
🪛 Checkov (3.2.508)
.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
[low] 38-39: Base64 High Entropy String
(CKV_SECRET_6)
[low] 39-40: Base64 High Entropy String
(CKV_SECRET_6)
🪛 GitHub Actions: Story 10.4 Full-Stack Smoke Rehearsal
scripts/release-readiness/run-five-session-isolation.mjs
[error] 1-1: Release readiness step failed. Command 'node ./scripts/release-readiness/run-five-session-isolation.mjs' completed with exit code 1.
scripts/release-readiness/run-full-stack-smoke.sh
[error] 1-1: full-stack smoke failed: docker compose up failed (exit code 1).
🪛 LanguageTool
docs/ops/release-go-no-go-checklist-template.md
[style] ~38-~38: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...passedkeeps the release atno-go`. - Any undocumented degraded path or missing r...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
docs/ops/full-stack-smoke-rehearsal-runbook.md
[style] ~48-~48: Consider removing “of” to be more concise
Context: ...et The release gate is green only when all of the following are true: 1. `docker compose...
(ALL_OF_THE)
🪛 Shellcheck (0.11.0)
scripts/release-readiness/run-rollback-rehearsal.sh
[info] 255-255: Double quote to prevent globbing and word splitting.
(SC2086)
🔇 Additional comments (19)
.gitignore (1)
44-47: LGTM!The negation rules correctly re-include the three shell scripts that serve as entry points for the Story 10.4 release-readiness workflow. This pattern properly overrides the broader
*.shignore rule.scripts/observability/validate-observability-stack.sh (1)
1-38: LGTM!The script follows shell best practices with
set -euo pipefail, properly handles cross-platform paths for Windows/WSL, and uses environment variable overrides for flexibility. Thefail()helper centralizes error handling effectively.tests/observability/observability-runtime.test.js (3)
60-104: LGTM!The Bash command construction helpers are well-designed with proper single-quote escaping, Windows-to-WSL path normalization, and correct PATH handling. The pattern at line 99 (
export PATH='prepended:'"$PATH") correctly expands the existing PATH within the bash session.
185-192: LGTM!The static validation test correctly uses
runBashScriptwith theOBSERVABILITY_SKIP_RUNTIMEenvironment variable to test the static checks path.
358-386: LGTM!The runtime validation test comprehensively verifies the reprovision flow using mocked
dockerandcurlbinaries. TheprependPathEntriesoption correctly injects the mock binaries directory..gitattributes (1)
1-3: LGTM!Enforcing LF line endings for these shell scripts is essential to prevent execution failures that would occur with CRLF endings. This correctly complements the
.gitignorenegation rules for the same files.docs/ops/release-go-no-go-checklist-template.md (1)
1-51: LGTM!The checklist template is well-structured with clear sections for metadata, linked evidence, mandatory checks, blocking rules, and decision documentation. All expected Story 10.4 evidence artifacts are referenced.
tests/release-readiness/release-readiness-docs.test.js (1)
1-41: LGTM!These documentation regression tests ensure the runbook and checklist template stay synchronized with the canonical script names, artifact paths, and blocking rule wording. The regex patterns correctly escape special characters.
tests/release-readiness/story-10-4-evidence-runtime.test.js (3)
40-78: LGTM!The
writePassingEvidencehelper creates a comprehensive fixture covering all expected evidence files (cold-start, docs, smoke, session-isolation, rollback, go-no-go). The scenario IDs align with the expected evidence assembler output structure.
99-119: LGTM!This test correctly validates fail-closed behavior by removing required evidence and setting
go-no-gotono-go. The assertions verify the assembler exits with status 1, setsoverallResulttoFAILED, and marks the missing scenario asMISSING.
121-138: LGTM!This test catches an important edge case: when
decision: "go"butreleaseReady: false, the assembler should detect the inconsistency and fail. This ensures the gate cannot be bypassed with conflicting inputs.tests/release-readiness/rollback-rehearsal-runtime.test.js (2)
79-112: LGTM!The simulate mode test correctly validates that the script produces both
rollback-rehearsal-summary.jsonandgo-no-go-summary.jsonwith expected values when all upstream evidence is passing.
140-179: LGTM!The execute mode test uses a mock docker binary to verify that the rollback rehearsal actually invokes
docker compose up -dwith the expected services whenROLLBACK_REHEARSAL_CONFIRM_EXECUTE=1. The mock captures calls for assertion without performing real container operations.scripts/release-readiness/run-full-stack-smoke.sh (6)
1-52: LGTM!Configuration setup is well-structured with sensible defaults, proper use of
set -euo pipefailfor strict error handling, and clear separation of status tracking variables from output paths.
54-82: LGTM!The
append_compose_profilefunction correctly handles deduplication of compose profiles and properly updates theCOMPOSE_ENVarray with the modified value.
84-136: LGTM!Helper functions are well-implemented with proper cross-platform support for WSL/Windows environments and appropriate Docker CLI resolution fallbacks.
163-196: LGTM!The polling logic correctly handles the timeout with proper edge case detection for responses received at the deadline boundary. The dual duration check ensures strict enforcement of the timing target.
198-246: LGTM!Service health checks correctly handle both containers with and without health checks by falling back to
State.Status. The docs endpoint validation properly verifies both HTTP status and expected content markers.
346-365: Service list indocker compose upmay not align withREQUIRED_SERVICES.The services started in
compose up(lines 347-357) includemysql,mysql-grant-repair, andrediswhich should be verified against theREQUIRED_SERVICESdefinition to ensure consistency. This mismatch could indicate either intentional separation of required vs. ancillary services, or a configuration gap.If these service lists are meant to be maintained in sync, consider consolidating the definitions or adding a comment explaining the deliberate difference.
There was a problem hiding this comment.
Actionable comments posted: 5
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ddff620e-f829-4ed9-8ab8-73a0810f8aa4
📒 Files selected for processing (3)
.github/workflows/story-10-4-full-stack-smoke-rehearsal.ymlBEscripts/release-readiness/run-full-stack-smoke.sh
📜 Review details
⏰ 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: story-10-4-full-stack-smoke-rehearsal
🧰 Additional context used
🪛 Checkov (3.2.508)
.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
[low] 38-39: Base64 High Entropy String
(CKV_SECRET_6)
[low] 39-40: Base64 High Entropy String
(CKV_SECRET_6)
🔇 Additional comments (1)
BE (1)
1-1: Verify BE submodule compatibility with smoke/rehearsal scripts.The submodule pointer update to
93f88929f56178485c08be7a1d7c949749276db1(branchFIX-94-Story-10.4-INT-CH-Full-stack-Smoke-Rehearsal) is legitimate. However, the smoke test scripts depend on specific service configurations remaining consistent:
- Container names:
corebank-service,fep-gateway,fep-simulator,channel-service- Healthcheck endpoints:
/actuator/healthon respective management ports- Service ports and Dockerfile context
Ensure the BE branch changes do not introduce breaking changes to these service definitions before merge.
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (3)
scripts/release-readiness/run-five-session-isolation.mjs (1)
153-232:⚠️ Potential issue | 🟠 MajorWrap top-level execution in try/catch to emit evidence on setup failures.
If the helper module import fails (line 155-156), the export assertion throws (line 158-160), or environment parsing throws (lines 169-171), the script exits without writing
session-isolation-summary.json. This breaks the "leave evidence on failure" contract that downstream steps (rollback rehearsal, evidence assembler) depend on.🛠️ Proposed fix
-async function main() { +async function main() { + try { const helperModuleUrl = resolveHelperModuleUrl(); const helperModule = await import(helperModuleUrl.href); // ... rest of main logic ... if (status !== "passed") { process.exitCode = 1; } + } catch (error) { + fs.mkdirSync(outputDir, { recursive: true }); + fs.writeFileSync(summaryPath, JSON.stringify({ + storyId: "10.4", + criterion: "AC6", + startedAt, + completedAt: new Date().toISOString(), + status: "failed", + message: `Session isolation setup failed: ${error instanceof Error ? error.message : String(error)}`, + checks: { + expectedSessionCount: DEFAULT_SESSION_COUNT, + actualSessionCount: 0, + allSessionsSucceeded: false, + dashboardReady: false, + uniqueAccounts: false, + uniqueSessionCookies: false, + uniqueXsrfTokens: false, + uniqueOrderSessions: false, + }, + sessions: [], + }, null, 2)); + process.exitCode = 1; + } }.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml (2)
7-19:⚠️ Potential issue | 🟠 MajorInclude
.gitmodulesin the trigger paths.A PR that only changes the BE submodule wiring (via
.gitmodules) can skip this rehearsal gate entirely since lines 55-59 always check out submodules recursively.➕ Proposed fix
- '.env.example' + - '.gitmodules' - 'package.json'
43-45:⚠️ Potential issue | 🟠 MajorMove the session-isolation password out of the workflow file.
Line 44 hardcodes a credential-like value into version control. Even for rehearsal data, this is harder to rotate and exposes the fixture to everyone with repository access.
🔐 Proposed fix
- SESSION_ISOLATION_PASSWORD: LiveVideo115! + SESSION_ISOLATION_PASSWORD: ${{ secrets.SESSION_ISOLATION_PASSWORD }}
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 986e3f90-992c-41a8-98ca-bab40c35aabd
📒 Files selected for processing (19)
.gitattributes.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml.gitignoredocs/ops/full-stack-smoke-rehearsal-runbook.mddocs/ops/release-go-no-go-checklist-template.mdpackage.jsonscripts/observability/validate-observability-stack.shscripts/release-readiness/assemble-story-10-4-evidence.mjsscripts/release-readiness/run-edge-gateway-validation.shscripts/release-readiness/run-five-session-isolation.mjsscripts/release-readiness/run-full-stack-smoke.shscripts/release-readiness/run-rollback-rehearsal.shtests/helpers/bash-script-test-utils.jstests/observability/observability-runtime.test.jstests/release-readiness/edge-gateway-validation-runtime.test.jstests/release-readiness/full-stack-smoke-runtime.test.jstests/release-readiness/release-readiness-docs.test.jstests/release-readiness/rollback-rehearsal-runtime.test.jstests/release-readiness/story-10-4-evidence-runtime.test.js
📜 Review details
⏰ 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: story-10-4-full-stack-smoke-rehearsal
🧰 Additional context used
🪛 Checkov (3.2.508)
.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
[low] 38-39: Base64 High Entropy String
(CKV_SECRET_6)
[low] 39-40: Base64 High Entropy String
(CKV_SECRET_6)
🪛 LanguageTool
docs/ops/full-stack-smoke-rehearsal-runbook.md
[style] ~53-~53: Consider removing “of” to be more concise
Context: ...et The release gate is green only when all of the following are true: 1. `docker compose...
(ALL_OF_THE)
🪛 Shellcheck (0.11.0)
scripts/release-readiness/run-rollback-rehearsal.sh
[info] 312-312: Double quote to prevent globbing and word splitting.
(SC2086)
🔇 Additional comments (40)
.gitignore (1)
44-48: LGTM!The negation patterns correctly un-ignore the four release-readiness shell scripts that need to be tracked in version control. The order is correct—negations appear after the
*.shignore rule.docs/ops/release-go-no-go-checklist-template.md (1)
1-54: LGTM!The checklist template comprehensively covers all Story 10.4 evidence artifacts (smoke, cold-start, docs, edge, session-isolation, rollback, go-no-go, matrix summaries) and enforces fail-closed blocking rules. The mandatory checks align with the workflow sequence described in the PR objectives.
.gitattributes (1)
1-4: LGTM!Enforcing
eol=lffor shell scripts prevents CRLF line ending issues that would break script execution on Linux (GitHub Actions runners).tests/observability/observability-runtime.test.js (4)
10-10: LGTM!Import of the shared bash helper utilities enables consistent script execution across test files.
128-135: LGTM!Refactored to use the shared
runBashScripthelper, improving consistency with other release-readiness tests.
238-243: LGTM!Extended the mock
curlto handle additional options (--data-urlencode,-G) that the validation script uses for Prometheus queries.
302-313: LGTM!Using
prependPathEntries: [binDir]is cleaner than manual PATH string manipulation and correctly shadows system binaries with mock implementations during test execution.scripts/release-readiness/run-edge-gateway-validation.sh (1)
1-60: LGTM!The script follows bash best practices with
set -euo pipefail, properly handles validator failures while still generating evidence, and correctly exits with status 1 on failure to satisfy the fail-closed gate requirement. Thejson_escapefunction covers the common special characters needed for the status messages.tests/release-readiness/release-readiness-docs.test.js (1)
16-43: LGTM!These contract tests ensure the runbook and checklist template stay in sync with the actual release-readiness scripts and evidence artifacts. This prevents documentation drift and ensures operators can rely on documented procedures.
tests/release-readiness/edge-gateway-validation-runtime.test.js (1)
24-62: LGTM!Good coverage of both success and failure paths. The tests verify that the wrapper script:
- Correctly propagates validator exit status
- Writes structured evidence with appropriate
statusvalues- Captures log paths in the expected format
docs/ops/full-stack-smoke-rehearsal-runbook.md (1)
1-119: LGTM!The runbook is well-structured with clear preconditions, canonical execution sequence, expected evidence outputs, rollback strategy (simulate/execute modes), and failure handling procedures. The documentation aligns with the script implementations and evidence assembler contract.
scripts/release-readiness/assemble-story-10-4-evidence.mjs (4)
1-17: LGTM!The script correctly derives
BUILD_IDfrom multiple environment variable fallbacks and sets up output paths consistently. The use ofnode:*prefixed imports follows modern Node.js ESM conventions.
61-78: LGTM!The
safeReadJsonfunction properly handles missing files (returnsnull) and parse errors (returns a structured error object withparseError: true), ensuring downstream logic can distinguish between different failure modes.
80-92: LGTM!The
normalizeResultfunction correctly normalizes status strings toPASSED,FAILED, orMISSING, handling bothpassed/goandfailed/no-govariants case-insensitively.
269-319: LGTM!The gate logic is correctly fail-closed:
overallResultisPASSEDonly when all scenarios pass ANDgoNoGoResult === "PASSED"ANDreleaseReady === true. The script exits with code 1 on any failure, logging the failing scenario identifiers for traceability.scripts/release-readiness/run-five-session-isolation.mjs (1)
82-118: LGTM!The
finalizeSessionResultfunction correctly extracts and hashes sensitive identifiers (identity, account, session cookie, XSRF token, order session) rather than storing raw values. The hash-based approach preserves uniqueness verification while avoiding PII exposure in the evidence artifacts.tests/release-readiness/story-10-4-evidence-runtime.test.js (3)
1-39: LGTM!The test setup is clean with proper helper functions for temp directory creation, JSON read/write, and assembler invocation with configurable environment variables.
84-102: LGTM!The all-green test case validates that when all evidence files pass, the assembler exits with code 0 and produces
overallResult: "PASSED"with all 6 scenarios marked asPASSED.
104-143: LGTM!The fail-closed test cases properly validate that:
- Missing evidence (
session-isolation-summary.jsonremoved) results inMISSINGstatus for the corresponding scenariono-godecision propagates tooverallResult: "FAILED"- Inconsistent state (
decision: "go"withreleaseReady: false) also fails the gateThese tests enforce the fail-closed contract.
scripts/release-readiness/run-rollback-rehearsal.sh (3)
46-51: LGTM!The
fail()function now correctly callsadd_blocker "$1"before exiting, ensuring the blocker is captured in the evidence artifacts via the EXIT trap.
126-143: LGTM!The
extract_status()function now uses Python'sjsonmodule for proper JSON parsing with type validation, avoiding the fragileawk-based extraction. The fallback tonodeis not present in this version, but Python availability is sufficient for CI environments.
279-346: LGTM!The EXIT trap at line 279 ensures
emit_reports()is always called, preserving evidence artifacts even when the script fails. Themain()function properly aggregates blockers and computes the go/no-go decision based on all prerequisite checks..github/workflows/story-10-4-full-stack-smoke-rehearsal.yml (2)
87-144: LGTM!The workflow correctly uses
continue-on-error: trueon all rehearsal steps to collect outcomes without aborting, then assembles evidence and uploads artifacts regardless of individual step results. The step dependencies (if: steps.smoke.outcome == 'success') correctly gate edge and session isolation on smoke success.
153-184: LGTM!The "Enforce Story 10.4 gate" step correctly aggregates all step outcomes: smoke must succeed, edge and session isolation are only checked if smoke succeeded, rollback and assemble must succeed regardless. This aligns with the evidence assembler's gate semantics.
package.json (1)
9-34: LGTM!The new npm scripts are correctly defined:
test:release-readinessruns the test suiteassemble:story-10-4:evidenceinvokes the evidence assemblerlint:release-readinessvalidates all bash and node files for syntaxThe
testscript chain now includestest:release-readinessin the correct position.scripts/observability/validate-observability-stack.sh (3)
123-128: LGTM!The
prometheus_queryfunction now usescurl -G --data-urlencodeto properly URL-encode the query parameter, handling special characters like{,}, and=correctly.
130-164: LGTM!The comment at lines 131-132 clarifies that Prometheus/Grafana containers are intentionally kept running because downstream smoke and evidence assembly steps rely on the rehearsal stack. The function properly validates health endpoints, Prometheus queries, and Grafana API access, including a security check that the public actuator prometheus endpoint is not exposed.
166-187: LGTM!The
main()function correctly normalizes Windows paths for mock logging support and conditionally skips runtime validation whenOBSERVABILITY_SKIP_RUNTIME=1.scripts/release-readiness/run-full-stack-smoke.sh (7)
145-147: Potential portability issue withdate +%s%3N.The
%3Nformat is a GNU coreutils extension not available on BSD/macOS defaultdate. This may fail on macOS runners or developer machines.
168-172:http_status()lacks timeout and connection failure handling.With
set -euo pipefailenabled, ifcurlfails (e.g., connection refused), the command substitution will cause the script to abort before retry logic can execute. The function also lacks per-request timeouts.
302-311: Observability validator doesn't receive the computed compose profile.The
COMPOSE_ENVarray withCOMPOSE_PROFILESis not passed to the validator invocation. The validator script checks forCOMPOSE_PROFILESin its environment but won't receive it, potentially causing it to validate against a different compose configuration.
420-422: Cold-start timing excludes service boot time.The timer in
wait_for_mandatory_api()starts afterwait_for_required_services()completes, which can take up to 300 seconds. This means actual cold-start latency (boot + API readiness) is not accurately captured in the evidence.
1-90: LGTM!The script initialization, environment handling, and
append_compose_profile()utility are well-structured. The compose profile management correctly handles existing profiles and updates theCOMPOSE_ENVarray.
313-381: LGTM!The
emit_reports()function correctly generates JSON evidence with proper escaping and relative paths. ThewithinTargetlogic properly validates duration bounds and status.
383-429: LGTM!The exit trap ensures evidence is always emitted regardless of success or failure, supporting the fail-closed evidence gate requirement. The
main()function orchestrates the smoke checks in the correct order.tests/release-readiness/full-stack-smoke-runtime.test.js (2)
136-191: LGTM!The success scenario test is comprehensive: it validates exit code, stdout message, all JSON evidence files, scenario IDs, and verifies mock tool invocations through log inspection.
193-225: LGTM!The failure scenario test properly validates the fail-closed evidence behavior: the script writes failed evidence even when mandatory API readiness fails, ensuring downstream evidence assembly can report blockers.
tests/release-readiness/rollback-rehearsal-runtime.test.js (3)
67-94: LGTM!The test correctly verifies that a failed smoke summary propagates to a
no-godecision with appropriate blocker messaging.
96-138: LGTM!The execute mode test properly validates that Docker Compose re-apply is invoked with confirmation, and verifies the expected service list in the logged commands.
140-163: LGTM!The test correctly validates fail-closed behavior when edge validation evidence is missing, ensuring the go/no-go gate catches missing prerequisites.
There was a problem hiding this comment.
♻️ Duplicate comments (5)
scripts/release-readiness/run-full-stack-smoke.sh (3)
168-171:⚠️ Potential issue | 🔴 CriticalDon't let
curlabort the retry loop.A transport failure here exits the whole script under
set -euo pipefailbeforewait_for_mandatory_api()can retry orcheck_docs_endpoints()can emit structured evidence. Bound each probe with connect/request timeouts and coerce transport errors to000instead.🔧 Suggested fix
http_status() { local url="$1" local body_path="$2" - curl -k -sS -o "${body_path}" -w '%{http_code}' "${url}" + local status + status="$( + curl \ + -k \ + -sS \ + --connect-timeout "${SMOKE_HTTP_CONNECT_TIMEOUT_SECONDS:-5}" \ + --max-time "${SMOKE_HTTP_TIMEOUT_SECONDS:-10}" \ + -o "${body_path}" \ + -w '%{http_code}' \ + "${url}" || true + )" + printf '%s' "${status:-000}" }#!/bin/bash set -euo pipefail tmp="$(mktemp)" http_status() { curl -k -sS --connect-timeout 1 --max-time 1 -o "${tmp}" -w '%{http_code}' https://127.0.0.1:1 } echo "before" status="$(http_status)" echo "after=${status}"
174-183:⚠️ Potential issue | 🟠 MajorStart the cold-start timer before the readiness wait.
The timer starts inside
wait_for_mandatory_api()afterwait_for_required_services()has already consumed the stack bootstrap time, sodurationMsandwithinTargetcan report a passing cold start after a slow compose boot. Pass a timestamp frommain()instead.📏 Suggested fix
+ COLD_START_STARTED_MS="$(now_ms)" + if [[ "${SKIP_COMPOSE_UP}" != "1" ]]; then if ! compose_cmd up -d \ mysql \ @@ wait_for_required_services - wait_for_mandatory_api + wait_for_mandatory_api "${COLD_START_STARTED_MS}"wait_for_mandatory_api() { + local start_ms="${1:-$(now_ms)}" local deadline_seconds="${SMOKE_START_TIMEOUT_SECONDS}" - local start_ms local current_ms local deadline_ms local body_path="${OUTPUT_DIR}/mandatory-api-response.json" local url="${EDGE_BASE_URL}${MANDATORY_API_PATH}" - start_ms="$(now_ms)" deadline_ms="$((start_ms + (deadline_seconds * 1000)))"Also applies to: 420-421
302-305:⚠️ Potential issue | 🟠 MajorPass
COMPOSE_PROFILESinto the validator subprocess.
append_compose_profile()guarantees the profile inCOMPOSE_ENV, not in the exported environment. That means local/manual runs can launchscripts/observability/validate-observability-stack.shwithout theobservabilityprofile, even though its owncompose_cmd up -d prometheus grafanadepends on the profile-gated services indocker-compose.yml.🧭 Suggested fix
- if ! OBSERVABILITY_COMPOSE_FILE="${COMPOSE_FILE}" "${OBSERVABILITY_VALIDATOR_PATH}" >"${OBSERVABILITY_LOG_PATH}" 2>&1; then + if ! env "${COMPOSE_ENV[@]}" \ + OBSERVABILITY_COMPOSE_FILE="${COMPOSE_FILE}" \ + "${OBSERVABILITY_VALIDATOR_PATH}" >"${OBSERVABILITY_LOG_PATH}" 2>&1; then.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml (2)
7-19:⚠️ Potential issue | 🟠 MajorInclude
.gitmodulesin the trigger paths.This workflow always checks out submodules recursively, but the path filter only catches the
BEgitlink itself. A PR that only rewires the BE submodule in.gitmodulescan bypass the Story 10.4 rehearsal gate.➕ Suggested fix
- 'docs/ops/**' - '.env.example' + - '.gitmodules' - 'package.json' - '.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml'Also applies to: 57-60
43-45:⚠️ Potential issue | 🟠 MajorMove
SESSION_ISOLATION_PASSWORDout of version control.This is a reusable credential-like value committed in the workflow file. Even for rehearsal data, that makes rotation harder and broadens exposure unnecessarily; prefer an Actions secret or minting a fresh password during the run.
🔐 Suggested fix
- SESSION_ISOLATION_PASSWORD: LiveVideo115! + SESSION_ISOLATION_PASSWORD: ${{ secrets.SESSION_ISOLATION_PASSWORD }}
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: fc9e5e66-12ce-4c28-b44c-49885c6ac020
📒 Files selected for processing (4)
.github/workflows/story-10-4-full-stack-smoke-rehearsal.ymlBEdocker/nginx/scripts/validate-edge-gateway.shscripts/release-readiness/run-full-stack-smoke.sh
📜 Review details
🧰 Additional context used
🪛 Checkov (3.2.508)
.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
[low] 38-39: Base64 High Entropy String
(CKV_SECRET_6)
[low] 39-40: Base64 High Entropy String
(CKV_SECRET_6)
🔇 Additional comments (3)
BE (1)
1-1: Verify the BE submodule commit is stable and contains only the intended changes.Submodule pointer updates lack visibility in diffs. Confirm that commit
f93df02c7053c75d7708c4f87f7853020640d744is merged to a stable branch in the BE repository and contains only the loopback address alignment changes mentioned in the PR objective. Check the BE repository directly to inspect the commit details and verify it's not from an unstable or work-in-progress branch.docker/nginx/scripts/validate-edge-gateway.sh (1)
7-7:127.0.0.1is the right fallback here.This now matches the dev certificate SAN generated by
docker/nginx/scripts/generate-dev-cert.sh, so the validator no longer depends onlocalhostresolving to the same TLS identity..github/workflows/story-10-4-full-stack-smoke-rehearsal.yml (1)
88-145: The fail-late control flow is well structured.Keeping the rehearsal steps non-blocking and enforcing success in a single final gate step is the right pattern here. The
always()conditions also make sure teardown and evidence handling still run after earlier failures.Also applies to: 154-185
목적
Story 10.4의 풀스택 리허설을 루트 저장소 기준 자동화해,
compose cold-start, API/docs, observability, 5세션 격리, rollback rehearsal, go/no-go 판단까지 하나의 릴리스 증적 흐름으로 검증할 수 있도록 정리했습니다.
변경 요약
docker composecold-start, 필수 API/docs, observability 확인을 수행하는 full-stack smoke 스크립트를 추가했습니다.matrix-summary.md/json으로 집계하는 assembler와 회귀 테스트를 추가했습니다.관련 이슈
Closes #94
Related: #93
리뷰 포인트
smoke -> edge validation -> session isolation -> rollback -> evidence assemble순서로 실패 시에도 증적을 남기고 마지막에 gate를 fail 시키는 구조가 맞는지 확인 부탁드립니다.cold-start,docs,observability,session isolation,rollback,go/no-go를 빠짐없이 집계하고 fail-closed로 동작하는지 봐주시면 됩니다.테스트 결과
로컬 테스트 통과
CI 통과
수동 검증 완료
로컬 검증:
npm.cmd run test:observabilitynpm.cmd run lint:observabilitynpm.cmd run test:release-readinessnpm.cmd run lint:release-readiness일반 PR 전용 체크리스트
self-review를 완료했습니다.
머지 전 필수 작업이 모두 완료되었습니다.
필요한 문서(README/API/주석)를 업데이트했습니다.
브레이킹 체인지 여부를 확인했고 필요 시 명시했습니다.
브레이킹 체인지:
머지 전 남은 확인:
story-10-4-full-stack-smoke-rehearsal실제 실행 결과 확인Summary by CodeRabbit
New Features
Documentation
Tests
Chores