Skip to content

[Fix-94] [INT][CH] Story 10.4 풀스택 스모크 리허설과 릴리스 증적 게이트를 구현#21

Open
kyuoogle wants to merge 21 commits into
mainfrom
Integration/FIX-94-Story-10.4-Integration-Test-Full-stack-Smoke-Rehearsal
Open

[Fix-94] [INT][CH] Story 10.4 풀스택 스모크 리허설과 릴리스 증적 게이트를 구현#21
kyuoogle wants to merge 21 commits into
mainfrom
Integration/FIX-94-Story-10.4-Integration-Test-Full-stack-Smoke-Rehearsal

Conversation

@kyuoogle
Copy link
Copy Markdown
Contributor

@kyuoogle kyuoogle commented Mar 25, 2026

목적

Story 10.4의 풀스택 리허설을 루트 저장소 기준 자동화해,
compose cold-start, API/docs, observability, 5세션 격리, rollback rehearsal, go/no-go 판단까지 하나의 릴리스 증적 흐름으로 검증할 수 있도록 정리했습니다.

변경 요약

  • observability stack validator와 회귀 테스트를 추가했습니다.
  • docker compose cold-start, 필수 API/docs, observability 확인을 수행하는 full-stack smoke 스크립트를 추가했습니다.
  • 5개 인증 세션의 쿠키/XSRF/order session 격리를 검증하는 rehearsal 스크립트를 추가했습니다.
  • rollback rehearsal 스크립트, runbook, go/no-go checklist template을 추가했습니다.
  • Story 10.4 증적을 matrix-summary.md/json으로 집계하는 assembler와 회귀 테스트를 추가했습니다.
  • 루트 GitHub Actions workflow를 추가해 Story 10.4 full-stack smoke/rehearsal을 artifact 업로드까지 포함한 게이트로 연결했습니다.

관련 이슈

Closes #94

Related: #93

리뷰 포인트

  • 새 workflow가 smoke -> edge validation -> session isolation -> rollback -> evidence assemble 순서로 실패 시에도 증적을 남기고 마지막에 gate를 fail 시키는 구조가 맞는지 확인 부탁드립니다.
  • Story 10.4 evidence assembler가 cold-start, docs, observability, session isolation, rollback, go/no-go를 빠짐없이 집계하고 fail-closed로 동작하는지 봐주시면 됩니다.
  • 이 PR은 Story 10.4의 루트 자산을 다루므로, BE 서브모듈의 선행 변경과 실제 GitHub Actions 실주행 결과를 함께 확인해야 합니다.

테스트 결과

  • 로컬 테스트 통과

  • CI 통과

  • 수동 검증 완료

로컬 검증:

  • npm.cmd run test:observability
  • npm.cmd run lint:observability
  • npm.cmd run test:release-readiness
  • npm.cmd run lint:release-readiness
  • Story 10.4 workflow YAML 파싱 확인 완료

일반 PR 전용 체크리스트

  • self-review를 완료했습니다.

  • 머지 전 필수 작업이 모두 완료되었습니다.

  • 필요한 문서(README/API/주석)를 업데이트했습니다.

  • 브레이킹 체인지 여부를 확인했고 필요 시 명시했습니다.

브레이킹 체인지:

  • 없음

머지 전 남은 확인:

  • GitHub Actions에서 story-10-4-full-stack-smoke-rehearsal 실제 실행 결과 확인
  • BE 서브모듈 선행 변경과의 연결 상태 확인

Summary by CodeRabbit

  • New Features

    • End-to-end release‑readiness automation: full‑stack smoke, observability & edge validation, multi‑session isolation, rollback rehearsal, and evidence assembly.
  • Documentation

    • Added full‑stack smoke rehearsal runbook and a release go/no‑go checklist template.
  • Tests

    • New runtime E2E tests covering smoke, observability/edge validation, session isolation, rollback rehearsal, and evidence assembly.
  • Chores

    • Package scripts updated; repository ignores/attributes adjusted for consistent shell script handling and LF line endings; default edge validation host fallback set to 127.0.0.1.

@kyuoogle kyuoogle requested a review from yeomin4242 March 25, 2026 01:44
@kyuoogle kyuoogle self-assigned this Mar 25, 2026
@kyuoogle kyuoogle added the Story label Mar 25, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 25, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Summary
Repo metadata
\.gitattributes, \.gitignore
Mark specific release-readiness and observability shell scripts as text with eol=lf and un-ignore those *.sh files.
CI workflow
.github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
New GitHub Actions workflow to lint/run release-readiness tests, run full-stack smoke (allow controlled failures), optionally run edge validation and session isolation, perform rollback rehearsal, assemble/upload evidence, teardown compose, and enforce aggregated go/no-go gating.
Documentation
docs/ops/full-stack-smoke-rehearsal-runbook.md, docs/ops/release-go-no-go-checklist-template.md
Add runbook and checklist template detailing prereqs, canonical commands, evidence layout, acceptance criteria, rollback modes, and go/no-go procedures.
Package scripts
package.json
Add test:release-readiness, lint:release-readiness, assemble:story-10-4:evidence; integrate release-readiness into main test sequence and narrow observability lint target.
Observability validator
scripts/observability/validate-observability-stack.sh
New Bash script for static and optional runtime validation of Prometheus/Grafana provisioning, config invariants, and runtime health using docker compose and Grafana API checks.
Full-stack smoke
scripts/release-readiness/run-full-stack-smoke.sh
New Bash smoke runner that brings up compose (unless skipped), waits for healthy containers, measures cold-start timing, validates API/docs, invokes observability validator, and always emits JSON evidence artifacts/logs.
Edge validation
scripts/release-readiness/run-edge-gateway-validation.sh
Wrapper that runs an external edge validator, captures logs, writes edge-summary.json (with relative evidence paths) and exits non-zero on failure.
Session isolation
scripts/release-readiness/run-five-session-isolation.mjs
Node script to run concurrent dashboard provisioning sessions, normalize per-session results (cookie/XSRF/order hashes), check uniqueness/readiness, and emit a session-isolation summary JSON.
Rollback rehearsal
scripts/release-readiness/run-rollback-rehearsal.sh
Bash script supporting simulate/execute modes, reads prior summaries, optionally executes compose-based rollback, aggregates blockers, decides go/no-go, and writes summary JSON/MD artifacts.
Evidence assembly
scripts/release-readiness/assemble-story-10-4-evidence.mjs
Node assembler that reads per-check summaries, normalizes scenario results, computes gating, writes matrix-summary.json/.md, and exits non-zero on failures or contract inconsistencies.
Test helpers
tests/helpers/bash-script-test-utils.js
New test utilities to build/run bash commands with safe quoting, env normalization, PATH prepending, and sync/async runners used by runtime tests.
Tests — runtime & unit
tests/observability/..., tests/release-readiness/*
Add runtime tests for observability validator, full-stack smoke, edge validation, session isolation, rollback rehearsal, evidence assembler, and docs assertions; tests use temp dirs and mock bin tooling.
Subproject pointer
BE
Updated BE submodule commit pointer.
Misc
docker/nginx/scripts/validate-edge-gateway.sh
Default BASE_URL fallback changed from https://localhost to https://127.0.0.1.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through scripts and YAML bright,
Smoke checked the stack by candlelight.
Five sessions bounced with cookies true,
Rollback rehearsed — the evidence grew.
Story 10.4, hop to release delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title is written in Korean and refers to Story 10.4 full-stack smoke rehearsal and release evidence gate implementation, which aligns with the comprehensive changes across observability validation, smoke testing, session isolation, rollback rehearsal, and evidence assembly scripts.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Integration/FIX-94-Story-10.4-Integration-Test-Full-stack-Smoke-Rehearsal

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4e9bf60a-594c-489f-8c62-987ef70333fb

📥 Commits

Reviewing files that changed from the base of the PR and between 7546bbb and 8971c9c.

📒 Files selected for processing (17)
  • .gitattributes
  • .github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
  • .gitignore
  • docs/ops/full-stack-smoke-rehearsal-runbook.md
  • docs/ops/release-go-no-go-checklist-template.md
  • package.json
  • scripts/observability/validate-observability-stack.sh
  • scripts/release-readiness/assemble-story-10-4-evidence.mjs
  • scripts/release-readiness/run-five-session-isolation.mjs
  • scripts/release-readiness/run-full-stack-smoke.sh
  • scripts/release-readiness/run-rollback-rehearsal.sh
  • tests/observability/observability-runtime.test.js
  • tests/release-readiness/full-stack-smoke-runtime.test.js
  • tests/release-readiness/release-readiness-docs.test.js
  • tests/release-readiness/rollback-rehearsal-runtime.test.js
  • tests/release-readiness/session-isolation-runtime.test.js
  • tests/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 *.sh ignore 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. The fail() 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 runBashScript with the OBSERVABILITY_SKIP_RUNTIME environment variable to test the static checks path.


358-386: LGTM!

The runtime validation test comprehensively verifies the reprovision flow using mocked docker and curl binaries. The prependPathEntries option 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 .gitignore negation 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 writePassingEvidence helper 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-go to no-go. The assertions verify the assembler exits with status 1, sets overallResult to FAILED, and marks the missing scenario as MISSING.


121-138: LGTM!

This test catches an important edge case: when decision: "go" but releaseReady: 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.json and go-no-go-summary.json with 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 -d with the expected services when ROLLBACK_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 pipefail for strict error handling, and clear separation of status tracking variables from output paths.


54-82: LGTM!

The append_compose_profile function correctly handles deduplication of compose profiles and properly updates the COMPOSE_ENV array 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 in docker compose up may not align with REQUIRED_SERVICES.

The services started in compose up (lines 347-357) include mysql, mysql-grant-repair, and redis which should be verified against the REQUIRED_SERVICES definition 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.

Comment thread .github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
Comment thread docs/ops/release-go-no-go-checklist-template.md Outdated
Comment thread scripts/observability/validate-observability-stack.sh
Comment thread scripts/observability/validate-observability-stack.sh
Comment thread scripts/release-readiness/run-five-session-isolation.mjs Outdated
Comment thread scripts/release-readiness/run-full-stack-smoke.sh
Comment thread scripts/release-readiness/run-full-stack-smoke.sh Outdated
Comment thread scripts/release-readiness/run-rollback-rehearsal.sh
Comment thread scripts/release-readiness/run-rollback-rehearsal.sh
Comment thread tests/release-readiness/rollback-rehearsal-runtime.test.js Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ddff620e-f829-4ed9-8ab8-73a0810f8aa4

📥 Commits

Reviewing files that changed from the base of the PR and between 8971c9c and 588ffe7.

📒 Files selected for processing (3)
  • .github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
  • BE
  • scripts/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 (branch FIX-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/health on respective management ports
  • Service ports and Dockerfile context

Ensure the BE branch changes do not introduce breaking changes to these service definitions before merge.

Comment thread .github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
Comment thread .github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
Comment thread scripts/release-readiness/run-full-stack-smoke.sh
Comment thread scripts/release-readiness/run-full-stack-smoke.sh
Comment thread scripts/release-readiness/run-full-stack-smoke.sh
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

♻️ Duplicate comments (3)
scripts/release-readiness/run-five-session-isolation.mjs (1)

153-232: ⚠️ Potential issue | 🟠 Major

Wrap 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 | 🟠 Major

Include .gitmodules in 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 | 🟠 Major

Move 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

📥 Commits

Reviewing files that changed from the base of the PR and between 588ffe7 and af68b54.

📒 Files selected for processing (19)
  • .gitattributes
  • .github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
  • .gitignore
  • docs/ops/full-stack-smoke-rehearsal-runbook.md
  • docs/ops/release-go-no-go-checklist-template.md
  • package.json
  • scripts/observability/validate-observability-stack.sh
  • scripts/release-readiness/assemble-story-10-4-evidence.mjs
  • scripts/release-readiness/run-edge-gateway-validation.sh
  • scripts/release-readiness/run-five-session-isolation.mjs
  • scripts/release-readiness/run-full-stack-smoke.sh
  • scripts/release-readiness/run-rollback-rehearsal.sh
  • tests/helpers/bash-script-test-utils.js
  • tests/observability/observability-runtime.test.js
  • tests/release-readiness/edge-gateway-validation-runtime.test.js
  • tests/release-readiness/full-stack-smoke-runtime.test.js
  • tests/release-readiness/release-readiness-docs.test.js
  • tests/release-readiness/rollback-rehearsal-runtime.test.js
  • tests/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 *.sh ignore 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=lf for 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 runBashScript helper, improving consistency with other release-readiness tests.


238-243: LGTM!

Extended the mock curl to 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. The json_escape function 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:

  1. Correctly propagates validator exit status
  2. Writes structured evidence with appropriate status values
  3. 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_ID from multiple environment variable fallbacks and sets up output paths consistently. The use of node:* prefixed imports follows modern Node.js ESM conventions.


61-78: LGTM!

The safeReadJson function properly handles missing files (returns null) and parse errors (returns a structured error object with parseError: true), ensuring downstream logic can distinguish between different failure modes.


80-92: LGTM!

The normalizeResult function correctly normalizes status strings to PASSED, FAILED, or MISSING, handling both passed/go and failed/no-go variants case-insensitively.


269-319: LGTM!

The gate logic is correctly fail-closed: overallResult is PASSED only when all scenarios pass AND goNoGoResult === "PASSED" AND releaseReady === 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 finalizeSessionResult function 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 as PASSED.


104-143: LGTM!

The fail-closed test cases properly validate that:

  1. Missing evidence (session-isolation-summary.json removed) results in MISSING status for the corresponding scenario
  2. no-go decision propagates to overallResult: "FAILED"
  3. Inconsistent state (decision: "go" with releaseReady: false) also fails the gate

These tests enforce the fail-closed contract.

scripts/release-readiness/run-rollback-rehearsal.sh (3)

46-51: LGTM!

The fail() function now correctly calls add_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's json module for proper JSON parsing with type validation, avoiding the fragile awk-based extraction. The fallback to node is 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. The main() 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: true on 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-readiness runs the test suite
  • assemble:story-10-4:evidence invokes the evidence assembler
  • lint:release-readiness validates all bash and node files for syntax

The test script chain now includes test:release-readiness in the correct position.

scripts/observability/validate-observability-stack.sh (3)

123-128: LGTM!

The prometheus_query function now uses curl -G --data-urlencode to 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 when OBSERVABILITY_SKIP_RUNTIME=1.

scripts/release-readiness/run-full-stack-smoke.sh (7)

145-147: Potential portability issue with date +%s%3N.

The %3N format is a GNU coreutils extension not available on BSD/macOS default date. This may fail on macOS runners or developer machines.


168-172: http_status() lacks timeout and connection failure handling.

With set -euo pipefail enabled, if curl fails (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_ENV array with COMPOSE_PROFILES is not passed to the validator invocation. The validator script checks for COMPOSE_PROFILES in 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 after wait_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 the COMPOSE_ENV array.


313-381: LGTM!

The emit_reports() function correctly generates JSON evidence with proper escaping and relative paths. The withinTarget logic 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-go decision 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.

Comment thread scripts/release-readiness/run-full-stack-smoke.sh
Comment thread scripts/release-readiness/run-rollback-rehearsal.sh
Comment thread tests/helpers/bash-script-test-utils.js
Comment thread tests/helpers/bash-script-test-utils.js
Comment thread tests/release-readiness/edge-gateway-validation-runtime.test.js
Comment thread tests/release-readiness/full-stack-smoke-runtime.test.js
Comment thread tests/release-readiness/rollback-rehearsal-runtime.test.js
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (5)
scripts/release-readiness/run-full-stack-smoke.sh (3)

168-171: ⚠️ Potential issue | 🔴 Critical

Don't let curl abort the retry loop.

A transport failure here exits the whole script under set -euo pipefail before wait_for_mandatory_api() can retry or check_docs_endpoints() can emit structured evidence. Bound each probe with connect/request timeouts and coerce transport errors to 000 instead.

🔧 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 | 🟠 Major

Start the cold-start timer before the readiness wait.

The timer starts inside wait_for_mandatory_api() after wait_for_required_services() has already consumed the stack bootstrap time, so durationMs and withinTarget can report a passing cold start after a slow compose boot. Pass a timestamp from main() 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 | 🟠 Major

Pass COMPOSE_PROFILES into the validator subprocess.

append_compose_profile() guarantees the profile in COMPOSE_ENV, not in the exported environment. That means local/manual runs can launch scripts/observability/validate-observability-stack.sh without the observability profile, even though its own compose_cmd up -d prometheus grafana depends on the profile-gated services in docker-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 | 🟠 Major

Include .gitmodules in the trigger paths.

This workflow always checks out submodules recursively, but the path filter only catches the BE gitlink itself. A PR that only rewires the BE submodule in .gitmodules can 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 | 🟠 Major

Move SESSION_ISOLATION_PASSWORD out 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

📥 Commits

Reviewing files that changed from the base of the PR and between af68b54 and b95e0ce.

📒 Files selected for processing (4)
  • .github/workflows/story-10-4-full-stack-smoke-rehearsal.yml
  • BE
  • docker/nginx/scripts/validate-edge-gateway.sh
  • scripts/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 f93df02c7053c75d7708c4f87f7853020640d744 is 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.1 is 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 on localhost resolving 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

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