-
Notifications
You must be signed in to change notification settings - Fork 0
143 lines (139 loc) · 4.5 KB
/
Copy pathci.yml
File metadata and controls
143 lines (139 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
name: CI
on:
push:
branches: [main]
pull_request:
workflow_call:
jobs:
backend:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install
run: uv sync --extra dev --extra evals
- name: Lint
run: uv run ruff check src tests
- name: Security scan (bandit)
run: uv run bandit -c pyproject.toml -r src
- name: Typecheck
run: uv run mypy src
- name: Test
env:
# Dummy values so config "is this configured?" checks pass; no real
# network calls are made in the mocked test suite (see auth.py /
# supabase_store.py — invalid tokens fail parsing before any
# request reaches these URLs).
SUPABASE_URL: https://example.com
SUPABASE_SECRET_KEY: dummy-secret-key-for-ci
SUPABASE_JWKS_URL: https://example.com/auth/v1/.well-known/jwks.json
run: >-
uv run python -m pytest tests/ -q
--cov=src
--cov-fail-under=73
--cov-report=term-missing
--cov-report=xml:coverage.xml
- name: Upload backend coverage
if: always()
uses: actions/upload-artifact@v7.0.1
with:
name: backend-coverage
path: coverage.xml
if-no-files-found: warn
- name: AI regression gate
if: always()
run: uv run python -m src.evals.regression_gate --output reports/ai-regression-${{ github.sha }}.json
- name: Upload AI regression score
if: always()
uses: actions/upload-artifact@v7.0.1
with:
name: ai-regression-${{ github.sha }}
path: reports/ai-regression-${{ github.sha }}.json
if-no-files-found: error
ui:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: ui
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
cache-dependency-path: ui/package-lock.json
- name: Install
run: npm ci
- name: Lint
run: npx eslint src --max-warnings=0
- name: Typecheck
run: npx tsc --noEmit -p tsconfig.app.json
- name: Test with coverage
run: npm run test:coverage
- name: Upload UI coverage
if: always()
uses: actions/upload-artifact@v7.0.1
with:
name: ui-coverage
path: ui/coverage/
if-no-files-found: warn
- name: Install Playwright browser
run: npx playwright install --with-deps chromium
- name: Browser smoke test
run: npx playwright test
- name: Upload Playwright failure artifacts
if: failure()
uses: actions/upload-artifact@v7.0.1
with:
name: playwright-failure-artifacts
path: |
ui/playwright-report/
ui/test-results/
if-no-files-found: ignore
retention-days: 14
security:
runs-on: ubuntu-latest
timeout-minutes: 20
needs: [backend, ui]
steps:
- uses: actions/checkout@v5
- name: Build image
run: docker build -t cortex:${{ github.sha }} .
- name: Generate container SBOM
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: cortex:${{ github.sha }}
format: cyclonedx
output: cortex-sbom.cdx.json
scanners: vuln
- name: Upload container SBOM
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cortex-sbom-${{ github.sha }}
path: cortex-sbom.cdx.json
if-no-files-found: error
retention-days: 30
- name: Scan repository dependencies and configuration
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
scan-type: fs
scan-ref: .
scanners: vuln,misconfig,secret
severity: HIGH,CRITICAL
ignore-unfixed: true
exit-code: 1
format: table
- name: Scan container image
if: always()
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: cortex:${{ github.sha }}
scanners: vuln,misconfig,secret
severity: HIGH,CRITICAL
ignore-unfixed: true
exit-code: 1
format: table