@@ -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,75 +49,78 @@ 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 :
104122 working-directory : backend
105123
106- services :
107- redis :
108- image : redis:7-alpine
109- ports :
110- - 6379:6379
111- options : >-
112- --health-cmd "redis-cli ping"
113- --health-interval 5s
114- --health-timeout 3s
115- --health-retries 5
116- --health-start-period 5s
117-
118124 env :
119125 REDIS_HOST : 127.0.0.1
120126 REDIS_PORT : 6379
@@ -123,84 +129,45 @@ jobs:
123129 steps :
124130 - uses : actions/checkout@v4
125131
132+ # Install Redis directly on the runner — avoids Docker Hub rate limits entirely
133+ - name : Start Redis
134+ run : |
135+ sudo apt-get update -qq
136+ sudo apt-get install -y redis-server
137+ sudo systemctl start redis-server
138+ redis-cli ping
139+
126140 - uses : actions/setup-node@v4
127141 with :
128- node-version : 22
129-
130- - run : npm install
131- - run : npm run lint
132- - run : npm run build
133- - run : npm test
134-
135- # ── Dependency audit / supply-chain ─────────────────────────────────────
136- # Policy: CRITICAL CVEs fail the build. HIGH CVEs produce a warning and
137- # must be triaged within 7 days. Accepted risks require a signed-off entry
138- # in docs/ops/audit-exceptions.md before the override label is applied.
139- # Override process:
140- # 1. Engineer opens a PR adding the CVE to audit-exceptions.md with
141- # justification, mitigations, and a review-by date.
142- # 2. A second engineer approves the PR.
143- # 3. Add the GitHub label `audit-exception-approved` to the failing PR.
144- # 4. Re-run this job — it will pass once the exception is documented.
145- dependency-audit :
146- 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
147150 runs-on : ubuntu-latest
151+ needs : quality-build
148152 steps :
149153 - uses : actions/checkout@v4
150-
151154 - uses : actions/setup-node@v4
152155 with :
153- node-version : 22
154-
155- - name : Audit backend dependencies
156- working-directory : backend
157- run : |
158- npm install --ignore-scripts
159- # Fail on critical; warn on high (exit 0 so we can capture output)
160- npm audit --audit-level=critical
161- npm audit --audit-level=high || echo "::warning::High-severity advisories found — triage within 7 days per audit policy"
162-
163- - name : Audit frontend dependencies
164- working-directory : frontend
165- run : |
166- npm ci --ignore-scripts
167- npm audit --audit-level=critical
168- npm audit --audit-level=high || echo "::warning::High-severity advisories found — triage within 7 days per audit policy"
169-
170- - name : Generate SBOM (backend)
171- working-directory : backend
172- run : npx --yes @cyclonedx/cyclonedx-npm --output-format JSON --output-file ../sbom-backend.json
173-
174- - name : Generate SBOM (frontend)
175- working-directory : frontend
176- run : npx --yes @cyclonedx/cyclonedx-npm --output-format JSON --output-file ../sbom-frontend.json
177-
178- - 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
179167 with :
180- name : sbom- ${{ github.sha }}
168+ name : playwright-failure- ${{ github.run_id }}
181169 path : |
182- sbom-backend.json
183- sbom-frontend.json
184- retention-days : 90
185-
186- # ── Frontend ──────────────────────────────────────────────────────────────
187- frontend :
188- name : Frontend (Next.js / TypeScript)
189- runs-on : ubuntu-latest
190- defaults :
191- run :
192- working-directory : frontend
193- steps :
194- - uses : actions/checkout@v4
195-
196- - uses : actions/setup-node@v4
197- with :
198- node-version : 22
199- cache : npm
200- cache-dependency-path : frontend/package-lock.json
201-
202- - run : npm ci
203- - run : npm run lint
204- - run : npm run check-docs
205- - run : npm run build
206- - run : npm test
170+ test-results
171+ playwright-report
172+ traces
173+ .playwright/traces
0 commit comments