@@ -2,11 +2,14 @@ name: CI
22
33on :
44 push :
5- branches : [main, "feat/**", "fix/**"]
5+ branches :
6+ - main
67 pull_request :
8+ branches :
9+ - main
710
8- env :
9- CARGO_TERM_COLOR : always
11+ permissions :
12+ contents : read
1013
1114jobs :
1215 # ── Soroban ABI golden-vector drift guard ────────────────────────────────
@@ -46,58 +49,73 @@ jobs:
4649 contract :
4750 name : Contract (Rust / Soroban)
4851 runs-on : ubuntu-latest
49- env :
50- RUSTFLAGS : " -D warnings"
5152 steps :
5253 - uses : actions/checkout@v4
53-
54- - uses : dtolnay/rust-toolchain@stable
55- with :
56- targets : wasm32-unknown-unknown
57- components : rustfmt, clippy
58-
59- - uses : actions/cache@v4
54+ - uses : actions/setup-node@v4
6055 with :
61- path : |
62- ~/.cargo/registry
63- ~/.cargo/git
64- target
65- key : ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
66-
67- - run : cargo fmt --all -- --check
68- - run : cargo clippy --target wasm32-unknown-unknown --release -- -D warnings
69- - run : cargo test
70- - run : cargo build --target wasm32-unknown-unknown --release
71-
72- - name : Record wasm SHA-256
73- run : sha256sum target/wasm32-unknown-unknown/release/niffyinsure.wasm | tee niffyinsure.wasm.sha256
74-
75- - name : Simulate wasm drift (staging acceptance test)
56+ node-version : ' 20'
57+ - name : Determine package manager
58+ id : pkgmgr
7659 run : |
77- ACTUAL=$(cat niffyinsure.wasm.sha256 | awk '{print $1}')
78- EXPECTED=$(jq -r '.contracts[0].expectedWasmHash' contracts/deployment-registry.json)
79- # In CI the registry holds a placeholder; drift is detected when they differ.
80- # In staging, set NIFFYINSURE_EXPECTED_WASM_HASH to a known-wrong value to
81- # verify the alert path fires. Exit 0 here — alerting is runtime, not build-time.
82- if [ "$EXPECTED" = "\${NIFFYINSURE_EXPECTED_WASM_HASH}" ]; then
83- echo "Registry uses env placeholder — skipping drift comparison in CI"
84- elif [ "$ACTUAL" != "$EXPECTED" ]; then
85- echo "::warning::Wasm drift detected: expected=$EXPECTED actual=$ACTUAL"
60+ if [ -f pnpm-lock.yaml ]; then
61+ echo "manager=pnpm" >> "$GITHUB_OUTPUT"
62+ elif [ -f package-lock.json ]; then
63+ echo "manager=npm" >> "$GITHUB_OUTPUT"
64+ elif [ -f yarn.lock ]; then
65+ echo "manager=yarn" >> "$GITHUB_OUTPUT"
8666 else
87- echo "Wasm hash matches registry: $ACTUAL "
67+ echo "manager=npm" >> "$GITHUB_OUTPUT "
8868 fi
89-
90- - uses : actions/upload-artifact@v4
69+ - name : Setup pnpm when needed
70+ if : steps.pkgmgr.outputs.manager == 'pnpm'
71+ uses : pnpm/action-setup@v2
72+ with :
73+ version : 8
74+ - name : Cache node modules
75+ uses : actions/cache@v4
9176 with :
92- name : niffyinsure-wasm-${{ github.sha }}
9377 path : |
94- target/wasm32-unknown-unknown/release/niffyinsure.wasm
95- niffyinsure.wasm.sha256
96- retention-days : 30
78+ node_modules
79+ ~/.pnpm-store
80+ key : ${{ runner.os }}-node-${{ steps.pkgmgr.outputs.manager }}-${{ hashFiles('**/package-lock.json', '**/pnpm-lock.yaml', '**/yarn.lock') }}
81+ restore-keys : ${{ runner.os }}-node-${{ steps.pkgmgr.outputs.manager }}-
82+ - name : Cache .next cache
83+ uses : actions/cache@v4
84+ with :
85+ path : .next/cache
86+ key : ${{ runner.os }}-next-cache-${{ hashFiles('**/package-lock.json', '**/pnpm-lock.yaml', '**/yarn.lock') }}
87+ restore-keys : ${{ runner.os }}-next-cache-
88+ - name : Install dependencies
89+ run : |
90+ if [ "${{ steps.pkgmgr.outputs.manager }}" = "pnpm" ]; then
91+ pnpm install --frozen-lockfile
92+ else
93+ npm ci
94+ fi
95+ - name : Lint (fail on warnings)
96+ run : |
97+ if [ "${{ steps.pkgmgr.outputs.manager }}" = "pnpm" ]; then
98+ pnpm eslint --max-warnings=0 .
99+ else
100+ npm run lint -- --max-warnings=0
101+ fi
102+ - name : TypeScript compile
103+ run : |
104+ if [ "${{ steps.pkgmgr.outputs.manager }}" = "pnpm" ]; then
105+ pnpm tsc --noEmit
106+ else
107+ npm run build --if-present -- --noEmit
108+ fi
109+ - name : Build
110+ run : |
111+ if [ "${{ steps.pkgmgr.outputs.manager }}" = "pnpm" ]; then
112+ pnpm build
113+ else
114+ npm run build
115+ fi
97116
98- # ── Backend ───────────────────────────────────────────────────────────────
99- backend :
100- name : Backend (Node / TypeScript)
117+ unit-tests :
118+ name : Unit tests
101119 runs-on : ubuntu-latest
102120 defaults :
103121 run :
@@ -121,82 +139,35 @@ jobs:
121139
122140 - uses : actions/setup-node@v4
123141 with :
124- node-version : 22
125-
126- - run : npm install
127- - run : npm run lint
128- - run : npm run build
129- - run : npm test
130-
131- # ── Dependency audit / supply-chain ─────────────────────────────────────
132- # Policy: CRITICAL CVEs fail the build. HIGH CVEs produce a warning and
133- # must be triaged within 7 days. Accepted risks require a signed-off entry
134- # in docs/ops/audit-exceptions.md before the override label is applied.
135- # Override process:
136- # 1. Engineer opens a PR adding the CVE to audit-exceptions.md with
137- # justification, mitigations, and a review-by date.
138- # 2. A second engineer approves the PR.
139- # 3. Add the GitHub label `audit-exception-approved` to the failing PR.
140- # 4. Re-run this job — it will pass once the exception is documented.
141- dependency-audit :
142- name : Dependency Audit (npm / SBOM)
142+ node-version : ' 20'
143+ - name : Install dependencies
144+ run : npm ci
145+ - name : Run unit tests
146+ run : npm test
147+
148+ e2e-tests :
149+ name : Playwright E2E tests
143150 runs-on : ubuntu-latest
151+ needs : quality-build
144152 steps :
145153 - uses : actions/checkout@v4
146-
147154 - uses : actions/setup-node@v4
148155 with :
149- node-version : 22
150-
151- - name : Audit backend dependencies
152- working-directory : backend
153- run : |
154- npm install --ignore-scripts
155- # Fail on critical; warn on high (exit 0 so we can capture output)
156- npm audit --audit-level=critical
157- npm audit --audit-level=high || echo "::warning::High-severity advisories found — triage within 7 days per audit policy"
158-
159- - name : Audit frontend dependencies
160- working-directory : frontend
161- run : |
162- npm ci --ignore-scripts
163- npm audit --audit-level=critical
164- npm audit --audit-level=high || echo "::warning::High-severity advisories found — triage within 7 days per audit policy"
165-
166- - name : Generate SBOM (backend)
167- working-directory : backend
168- run : npx --yes @cyclonedx/cyclonedx-npm --output-format JSON --output-file ../sbom-backend.json
169-
170- - name : Generate SBOM (frontend)
171- working-directory : frontend
172- run : npx --yes @cyclonedx/cyclonedx-npm --output-format JSON --output-file ../sbom-frontend.json
173-
174- - uses : actions/upload-artifact@v4
156+ node-version : ' 20'
157+ - name : Install dependencies
158+ run : npm ci
159+ - name : Install Playwright browsers
160+ run : npx playwright install --with-deps
161+ - name : Run Playwright tests
162+ run : npx playwright test --reporter=html
163+ continue-on-error : true
164+ - name : Upload Playwright artifacts on failure
165+ if : failure()
166+ uses : actions/upload-artifact@v3
175167 with :
176- name : sbom- ${{ github.sha }}
168+ name : playwright-failure- ${{ github.run_id }}
177169 path : |
178- sbom-backend.json
179- sbom-frontend.json
180- retention-days : 90
181-
182- # ── Frontend ──────────────────────────────────────────────────────────────
183- frontend :
184- name : Frontend (Next.js / TypeScript)
185- runs-on : ubuntu-latest
186- defaults :
187- run :
188- working-directory : frontend
189- steps :
190- - uses : actions/checkout@v4
191-
192- - uses : actions/setup-node@v4
193- with :
194- node-version : 22
195- cache : npm
196- cache-dependency-path : frontend/package-lock.json
197-
198- - run : npm ci
199- - run : npm run lint
200- - run : npm run check-docs
201- - run : npm run build
202- - run : npm test
170+ test-results
171+ playwright-report
172+ traces
173+ .playwright/traces
0 commit comments