-
Notifications
You must be signed in to change notification settings - Fork 2
315 lines (306 loc) · 14.8 KB
/
Copy pathci.yml
File metadata and controls
315 lines (306 loc) · 14.8 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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
name: CI
on:
push:
branches:
- dev
- feat/keiko-editor
- feat/keiko-agent-native-editor-foundation-and-runtime
- feat/prompt-enhancer-1307
- feat/keiko-establish-governed-end-to-end-git-delivery
- feat/keiko-voice-digital-twin
- feat/keiko-isolated-task-workspaces
- feat/keiko-colleague-like-voice-dialogue-mode
- feat/keiko-repository-centered-desktop-workflow
- "release/**"
pull_request:
branches:
- dev
- feat/keiko-editor
- feat/keiko-agent-native-editor-foundation-and-runtime
- feat/prompt-enhancer-1307
- feat/keiko-establish-governed-end-to-end-git-delivery
- feat/keiko-voice-digital-twin
- feat/keiko-isolated-task-workspaces
- feat/keiko-colleague-like-voice-dialogue-mode
- feat/keiko-repository-centered-desktop-workflow
- "release/**"
workflow_dispatch:
permissions: {}
jobs:
protected-branch-gate:
name: Protected branch gate
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Confirm dev branch gate
run: |
case "${{ github.ref }}:${{ github.base_ref }}" in
refs/heads/dev: | refs/heads/feat/keiko-editor: | refs/heads/feat/keiko-agent-native-editor-foundation-and-runtime: | refs/heads/feat/prompt-enhancer-1307: | refs/heads/feat/keiko-establish-governed-end-to-end-git-delivery: | refs/heads/feat/keiko-voice-digital-twin: | refs/heads/feat/keiko-isolated-task-workspaces: | refs/heads/feat/keiko-colleague-like-voice-dialogue-mode: | refs/heads/feat/keiko-repository-centered-desktop-workflow: | refs/heads/release/*: | *:dev | *:feat/keiko-editor | *:feat/keiko-agent-native-editor-foundation-and-runtime | *:feat/prompt-enhancer-1307 | *:feat/keiko-establish-governed-end-to-end-git-delivery | *:feat/keiko-voice-digital-twin | *:feat/keiko-isolated-task-workspaces | *:feat/keiko-colleague-like-voice-dialogue-mode | *:feat/keiko-repository-centered-desktop-workflow | *:release/*)
echo "Protected or integration branch gate satisfied."
;;
*)
echo "This gate is only valid for protected dev, integration, and release branches."
exit 1
;;
esac
ci:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- run: npm ci
- name: Install sandbox isolation backend (bubblewrap)
run: |
sudo apt-get update
sudo apt-get install -y bubblewrap
# Ubuntu 24.04 restricts unprivileged user namespaces via AppArmor; bubblewrap (and the
# unshare fallback) need them to create the network namespace. Relax it for the runner so
# the enforced-egress proof below actually exercises the isolation boundary (ADR-0043).
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
- name: Enforced sandbox egress proof (ADR-0043 / #1202)
# NOT gated by the feat/keiko-editor branch skip: the assured pre-filter executes untrusted
# model-generated code, so the deny-by-default egress boundary must be proven on every run.
# The egress test fails the job if an outbound connection from inside network:"none" succeeds.
run: npm --workspace @oscharko-dev/keiko-sandbox test
- name: Verify Keiko Editor package
run: |
npm --workspace @oscharko-dev/keiko-editor run build
npm --workspace @oscharko-dev/keiko-editor run typecheck
npm --workspace @oscharko-dev/keiko-editor test
- run: npm run typecheck
- run: npm run check:version-consistency
- run: npm run check:git-client-evidence
- run: npm run lint
- run: npm run arch:check
- run: npm run arch:check:negative
- name: Quality Intelligence supply-chain gate
run: npm run check:qi-supply-chain
- name: Retrieval latency gate (enterprise retrieval M3)
# Runs after `npm run typecheck` (which builds packages), so the compiled keiko-workspace
# dist the gate imports is present. Deterministic fixture + generous p95 ceiling.
run: npm run check:retrieval-latency
- name: Retrieval quality gate (enterprise retrieval M4)
# Same compiled workspace surface as the latency gate; evaluates top-k quality, line-level
# evidence, and generated-artifact leakage over fixed synthetic enterprise fixtures.
run: npm run check:retrieval-quality
- name: Context quality gate (ADR-0052, context-engineering PR1)
# Runs after `npm run typecheck` (which builds packages), so the compiled keiko-contracts,
# keiko-workflows, keiko-workspace, and keiko-security dist the gate imports are present —
# the same build dependency the retrieval gates above rely on. Drives the deterministic lane
# allocator over a fixed offline corpus and enforces context-quality invariants.
run: npm run check:context-quality
- name: Keiko Editor static-export bundle gate
run: |
npm run build:ui
npm run check:editor-bundle-size -- --require-static-export
- name: Package surface and installable smoke
run: |
npm run build
npm run prepare:bin
npm run prune:package-native-optionals
npm run check:package-surface
KEIKO_SMOKE_PACK_IGNORE_SCRIPTS=1 npm run smoke:install
- name: Coverage quality gates
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm run test:coverage:quality
actionlint:
name: actionlint
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Download and verify actionlint
run: |
curl -sSfL "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz" -o actionlint.tar.gz
echo "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 actionlint.tar.gz" | sha256sum --check
tar -xzf actionlint.tar.gz actionlint
chmod +x actionlint
- name: Run actionlint
run: ./actionlint -color .github/workflows/*.yml
verify-pinned-shas:
name: Verify pinned action SHAs
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Assert all action references are pinned to 40-hex SHAs
run: |
set -euo pipefail
violations=$(grep -rnE '^\s*-?\s*uses:' .github/workflows/ \
| grep -vE 'uses:\s*\./' \
| grep -vE 'uses:\s*docker://' \
| grep -vE 'uses:\s*[A-Za-z0-9._/-]+@[0-9a-f]{40}([[:space:]]|$|#)' || true)
if [ -n "$violations" ]; then
echo "Unpinned action references (must pin to a full 40-hex commit SHA):"
echo "$violations"
exit 1
fi
echo "All action references are pinned to full commit SHAs."
build-scan-sbom-smoke:
name: Build, scan, SBOM, smoke
# Keep early feature-branch PRs fast. These release/package gates still run on merges to
# feat/keiko-editor, on dev/release PRs, and on manual workflow_dispatch runs.
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- run: npm ci
- name: Build
run: npm run build
- name: Prepare packaged CLI and UI assets
run: |
npm run prepare:bin
npm run build:ui
- name: Installable-package smoke (Issue #169 AC2)
run: npm run smoke:install
- name: Installable memory smoke (Issue #216)
run: npm run smoke:install:memory
- name: Smoke - offline evaluate exits 0
run: KEIKO_EVIDENCE_DIR="$(mktemp -d)" node dist/cli/index.js evaluate --suite all
- name: Security audit (high and above)
run: npm audit --audit-level=high
- name: Generate CycloneDX SBOM
run: npm sbom --sbom-format cyclonedx --omit dev > sbom.cdx.json
- name: Workspace SBOM and license gate (Issue #169 AC4)
run: npm run check:workspace-supply-chain
- name: Smoke - help exits 0
run: node dist/cli/index.js --help
- name: Smoke - version exits 0
run: node dist/cli/index.js --version
- name: Smoke - unknown command exits 2
run: |
set +e
node dist/cli/index.js definitely-not-a-command
code=$?
if [ "$code" -ne 2 ]; then echo "expected exit 2, got $code"; exit 1; fi
echo "unknown-command exit code correct: $code"
- name: Upload SBOM
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-cyclonedx
path: sbom.cdx.json
retention-days: 90
- name: Upload workspace SBOMs (Issue #169 AC4)
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: workspace-sboms-cyclonedx
path: sbom/
retention-days: 90
cross-platform-smoke:
name: Cross-platform smoke (${{ matrix.os }})
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
# Issue #284 AC4: the packed Keiko artifact must work on macOS, Windows, and Linux via the
# normal start path. Linux is already exercised by `build-scan-sbom-smoke`; this job runs the
# same installable-package smoke (pack -> install -> CLI -> packaged `keiko ui` -> health,
# launch project, QI runs read route, home shell) on Windows and macOS so AC4 portability is
# EXECUTED, not only portable by construction. Intentionally NOT a required/gating check yet —
# the `ci` job remains the merge gate; promote this to a required check once it has proven
# stable across several runs (native optional deps + the Next static export are the parts most
# likely to need per-OS attention). fail-fast:false so one OS result never masks the other.
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- run: npm ci
- name: Build
run: npm run build
# Two separate steps (not one multi-line run): on the Windows runner the default shell is
# PowerShell, which only surfaces the exit code of the LAST line of a multi-line `run`; as
# discrete steps each command's failure fails the job on every OS.
- name: Prepare packaged CLI
run: npm run prepare:bin
- name: Build UI (static export)
run: npm run build:ui
- name: Installable-package smoke (Issue #169 AC2 / #284 AC4 cross-platform)
env:
# Pack the dist already built by the steps above instead of re-running the Linux-oriented
# `prepack` publish gate (arch-check / package-surface / supply-chain shell out to npx/npm
# in ways that are not Windows-portable — a separate concern from artifact portability).
# The gating `build-scan-sbom-smoke` job keeps the full prepack pack on Linux.
KEIKO_SMOKE_PACK_IGNORE_SCRIPTS: "1"
run: npm run smoke:install
ui:
name: ui
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22.x"
cache: "npm"
- name: Install workspaces (single root lockfile after #167)
run: npm ci
- name: Build internal packages so contracts dist resolves for UI tsc
run: npm run build:packages
- name: Security audit UI dependencies (moderate and above)
run: npm audit --audit-level=moderate --workspace @oscharko-dev/keiko-ui
- name: Lint UI
run: npm run lint --workspace @oscharko-dev/keiko-ui
- name: Typecheck UI
run: npm run typecheck --workspace @oscharko-dev/keiko-ui
- name: Build UI (static export)
run: npm run build --workspace @oscharko-dev/keiko-ui
- name: Generate UI CycloneDX SBOM
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm sbom --sbom-format cyclonedx --omit dev --workspace @oscharko-dev/keiko-ui > ui-sbom.cdx.json
- name: Test UI with coverage (jsdom + axe a11y)
run: npm run test:coverage:ui
- name: UI coverage ratchet
run: npm run check:coverage:ui
- name: Install Playwright browser
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npx playwright install --with-deps chromium
- name: Release smoke E2E
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm run test:e2e:smoke
- name: Build package and UI assets
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: |
npm run build
npm run prepare:bin
npm run build:ui
npm run prune:package-native-optionals
- name: Verify package surface
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: npm run check:package-surface
- name: Smoke - keiko ui serves /api/health
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
run: |
set -euo pipefail
node dist/cli/index.js ui --port 4399 &
ui_pid=$!
trap 'kill "$ui_pid" 2>/dev/null || true' EXIT
body=$(curl --retry 10 --retry-connrefused --retry-delay 1 -fsS http://127.0.0.1:4399/api/health)
echo "health: $body"
echo "$body" | grep -q '"status":"ok"'
- name: Upload UI SBOM
if: ${{ github.event_name != 'pull_request' || github.base_ref != 'feat/keiko-editor' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ui-sbom-cyclonedx
path: ui-sbom.cdx.json
retention-days: 90