11name : CI
22
3+ # Fast quality + security gates on every push/PR. Heavy e2e (Redis/Kafka) and
4+ # chaos/mutation/bench run in nightly.yml. Actions use version tags; Dependabot
5+ # (github-actions) + a follow-up SHA-pin pass harden these further.
6+
37on :
48 push :
59 branches : [main, develop]
610 pull_request :
7- branches : [main]
11+ branches : [main, develop ]
812
913concurrency :
1014 group : ${{ github.workflow }}-${{ github.ref }}
1115 cancel-in-progress : true
1216
17+ permissions :
18+ contents : read
19+
1320jobs :
14- # ── Gate 1-3: Lint, Typecheck, Unit Tests ─────────────────────────────
1521 quality :
16- name : Quality Gates (lint / typecheck / coverage)
22+ name : Quality (lint · typecheck · 100% coverage · arch )
1723 runs-on : ubuntu-latest
1824 steps :
1925 - uses : actions/checkout@v4
@@ -22,84 +28,141 @@ jobs:
2228 node-version : " 22"
2329 cache : " npm"
2430 - run : npm ci
25- - name : Gate 1 — Lint (zero errors)
31+ - name : Lint (zero errors)
2632 run : npm run lint
27- - name : Gate 2 — Type Safety (zero errors)
33+ - name : Typecheck (zero errors)
2834 run : npm run typecheck
29- - name : Gate 3 — Unit Tests + Coverage (≥99%)
35+ - name : Architecture (no circular imports)
36+ run : npm run lint:arch
37+ - name : API surface gate (api-extractor — fails on undocumented public-API drift)
38+ run : npm run api:check
39+ - name : Unit tests + coverage (enforced 100% of src/**)
3040 run : npm run test:coverage
31- - name : Gate 6 — Architecture (no circular imports)
32- run : npx madge --circular src/
3341 - name : Upload coverage report
3442 uses : actions/upload-artifact@v4
3543 if : always()
3644 with :
3745 name : coverage
3846 path : coverage/
3947
40- # ── Gate 4a: BullMQ E2E (Redis) ───────────────────────────────────────
41- e2e-bullmq :
42- name : E2E — BullMQ / Redis
48+ board :
49+ name : Board UI (typecheck · build · tests)
4350 runs-on : ubuntu-latest
51+ defaults :
52+ run :
53+ working-directory : board
4454 steps :
4555 - uses : actions/checkout@v4
4656 - uses : actions/setup-node@v4
4757 with :
4858 node-version : " 22"
4959 cache : " npm"
60+ cache-dependency-path : board/package-lock.json
5061 - run : npm ci
51- - name : E2E Tests — BullMQ (Redis)
52- run : npm run test:e2e
53- env :
54- REDIS_URL : redis://localhost:6379
55- AGENT_IDS : test-agent
56- REDIS_PASSWORD : " "
62+ # `build` is `tsc --noEmit && vite build` — typechecks then bundles.
63+ - run : npm run build
64+ - run : npm test
5765
58- # ── Gate 4b: Kafka E2E ────────────────────────────────────────────────
59- e2e-kafka :
60- name : E2E — Kafka
66+ security :
67+ name : Security (audit · secrets · SBOM · OSV)
6168 runs-on : ubuntu-latest
69+ permissions :
70+ contents : read
71+ security-events : write
6272 steps :
6373 - uses : actions/checkout@v4
74+ with :
75+ fetch-depth : 0
6476 - uses : actions/setup-node@v4
6577 with :
6678 node-version : " 22"
6779 cache : " npm"
6880 - run : npm ci
69- - name : E2E Tests — Kafka
70- run : npm run test:e2e:kafka
81+ - name : Dependency audit (fail on HIGH+; moderates triaged in SECURITY.md)
82+ run : npm audit --audit-level=high
83+ - name : Generate CycloneDX 1.6 SBOM
84+ run : npx --yes @cyclonedx/cyclonedx-npm@latest --output-format JSON --spec-version 1.6 --output-file sbom.json
85+ - name : Upload SBOM
86+ uses : actions/upload-artifact@v4
87+ with :
88+ name : sbom-cyclonedx
89+ path : sbom.json
90+ - name : Secret scan (gitleaks)
91+ uses : gitleaks/gitleaks-action@v2
7192 env :
72- KAFKA_BROKERS : localhost:9092
73- AGENT_IDS : test-agent
74- REDIS_PASSWORD : " "
93+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
94+ - name : OSV-Scanner
95+ uses : google/osv-scanner-action/osv-scanner-action@v2.2.2
96+ continue-on-error : true
97+ with :
98+ scan-args : |-
99+ --lockfile=package-lock.json
100+ --format=sarif
101+ --output=osv.sarif
102+ - name : Upload OSV SARIF
103+ if : always()
104+ uses : github/codeql-action/upload-sarif@v3
105+ with :
106+ sarif_file : osv.sarif
107+ category : osv-scanner
75108
76- # ── Gate 5: Security Audit ────────────────────────────────────────────
77- security :
78- name : Security Audit
109+ codeql :
110+ name : CodeQL (JS/TS static analysis)
79111 runs-on : ubuntu-latest
112+ permissions :
113+ contents : read
114+ security-events : write
80115 steps :
81116 - uses : actions/checkout@v4
82- - uses : actions/setup-node@v4
117+ - uses : github/codeql-action/init@v3
83118 with :
84- node-version : " 22"
85- cache : " npm"
86- - run : npm ci
87- - name : Gate 5 — Dependency Audit
88- run : |
89- npm audit --audit-level=moderate || echo "::warning::Audit issues found - see output above (known: kaibanjs transitive CVEs)"
119+ languages : javascript-typescript
120+ - uses : github/codeql-action/analyze@v3
90121
91- # ── Gate 4c: Docker Build ─────────────────────────────────────────────
92122 docker :
93- name : Docker Build
123+ name : Docker build + image scan (Trivy)
94124 runs-on : ubuntu-latest
95125 needs : [quality]
126+ permissions :
127+ contents : read
128+ security-events : write
96129 steps :
97130 - uses : actions/checkout@v4
98- - name : Set up Docker Buildx
99- uses : docker/setup-buildx-action@v3
100- - name : Build Docker image
101- uses : docker/build-push-action@v5
131+ - uses : docker/setup-buildx-action@v3
132+ - uses : docker/build-push-action@v6
102133 with :
103134 context : .
104135 push : false
136+ load : true # load into the local daemon so Trivy can scan the built image
105137 tags : kaiban-distributed:ci-${{ github.sha }}
138+ # Blocking gate: fail the build on a FIXABLE CRITICAL/HIGH OS or library CVE
139+ # in the runtime image (unfixed base-image CVEs are reported but don't block).
140+ - name : Scan image (Trivy — gate on fixable CRITICAL/HIGH)
141+ uses : aquasecurity/trivy-action@v0.36.0
142+ with :
143+ image-ref : kaiban-distributed:ci-${{ github.sha }}
144+ format : table
145+ severity : CRITICAL,HIGH
146+ ignore-unfixed : true
147+ exit-code : " 1"
148+ env :
149+ TRIVY_DB_REPOSITORY : ghcr.io/aquasecurity/trivy-db
150+ # Always publish the full SARIF to the Security tab, even when the gate fails.
151+ - name : Scan image (Trivy — SARIF report)
152+ if : always()
153+ uses : aquasecurity/trivy-action@v0.36.0
154+ with :
155+ image-ref : kaiban-distributed:ci-${{ github.sha }}
156+ format : sarif
157+ output : trivy.sarif
158+ severity : CRITICAL,HIGH
159+ ignore-unfixed : true
160+ exit-code : " 0"
161+ env :
162+ TRIVY_DB_REPOSITORY : ghcr.io/aquasecurity/trivy-db
163+ - name : Upload Trivy SARIF to code scanning
164+ if : always()
165+ uses : github/codeql-action/upload-sarif@v3
166+ with :
167+ sarif_file : trivy.sarif
168+ category : trivy-image
0 commit comments