-
Notifications
You must be signed in to change notification settings - Fork 0
254 lines (237 loc) · 10.9 KB
/
Copy pathci.yml
File metadata and controls
254 lines (237 loc) · 10.9 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
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
env:
# PyMuPDF 1.27.2 / SWIG #2881: exact Python 3.13 shutdown warning only.
# Import-time warnings are repaired in pymupdf_compat; remove this when
# upstream generated types carry __module__ metadata.
PYTHONWARNINGS: "ignore:builtin type swigvarlink has no __module__ attribute:DeprecationWarning"
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- run: uv sync --locked --all-packages --group dev
- run: uv run --group dev ruff check .
- run: uv run --group dev ruff format --check .
typecheck:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
- run: uv sync --locked --all-packages --group dev
- run: just typecheck
sast:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- run: uv sync --locked --all-packages --group dev
- name: Run bandit (SAST)
# Skip list mirrors .pre-commit-config.yaml's bandit hook, which
# documents each rule. B608 (dynamic SQL) in particular is skipped
# project-wide because every hit was verified individually in the
# 2026-09 security review: each interpolates only a server-side
# allowlisted column name or a `?`-placeholder count, never raw
# user data; actual values always go through bound parameters.
run: uv run --group dev bandit --recursive --skip B101,B104,B105,B106,B107,B108,B110,B310,B404,B603,B606,B607,B608 packages/
audit:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- run: uv sync --locked --all-packages --group dev
- name: Audit dependencies for known vulnerabilities
run: |
uv --quiet export --all-packages --group dev --no-emit-workspace --format requirements-txt -o /tmp/requirements.txt
uv tool run pip-audit -r /tmp/requirements.txt --strict --no-deps --disable-pip
audit-full:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- run: uv sync --locked --all-packages --group dev --all-extras
- name: Audit full optional dependency surface
run: |
uv --quiet export --all-packages --group dev --all-extras --no-emit-workspace --format requirements-txt -o /tmp/requirements-full.txt
uv tool run pip-audit -r /tmp/requirements-full.txt --strict --no-deps --disable-pip
test:
runs-on: ubuntu-latest
timeout-minutes: 25
strategy:
fail-fast: false # report every Python version independently; don't cancel siblings
matrix:
python-version: ["3.12", "3.13"]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: ${{ matrix.python-version }}
- run: uv sync --locked --all-packages --group dev
- run: uv run --group dev pytest --tb=short --cov=packages --cov-report=term-missing
js:
# The browser-side unit tests (87 at time of writing) previously ran in NO
# gate: no workflow and no just recipe invoked them, so they only executed if
# someone typed `node --test` by hand. A suite nothing runs cannot be evidence
# of anything, which is the same blind spot that hid three regressions in the
# unrun e2e suites.
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24"
- run: node --test packages/studyloop/tests/js/*.test.js
web-profile:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
- run: uv sync --locked --all-packages --group dev --extra web
- run: just test-web
browser-smoke:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
- run: uv sync --locked --all-packages --group dev --extra web
- run: uv run playwright install --with-deps chromium
env:
# Playwright 1.58 still calls Node's deprecated url.parse during its
# installer only. Suppress that exact upstream warning code here;
# application/test Node warnings remain visible.
NODE_OPTIONS: "--disable-warning=DEP0169"
- run: just test-browser-smoke
e2e:
# The other 39 e2e files. Until this job existed only the single smoke file
# above ran in any gate, so ~500 browser tests were evidence of nothing --
# the same blind spot called out for the JS tests in the `js` job. Two real
# defects were hiding in there: a 500 from a file-deletion race in session
# teardown, and a 200ms sleep racing a 187ms CSS fade.
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
# tmux, but deliberately NOT ttyd. This mirrors the environment where the
# 500-pass unscaled result was actually verified, which had tmux and no
# ttyd. ttyd's absence is itself under test --
# test_terminal_proxy_degrades_when_ttyd_is_absent asserts the proxy
# answers 502 rather than hanging -- so installing it would diverge CI
# from the proven configuration and weaken that contract. Do not "fix"
# this by adding ttyd.
- run: sudo apt-get update && sudo apt-get install -y tmux
- run: uv sync --locked --all-packages --group dev --extra web
- run: uv run playwright install --with-deps chromium
env:
# Playwright 1.58 still calls Node's deprecated url.parse during its
# installer only. Suppress that exact upstream warning code here;
# application/test Node warnings remain visible.
NODE_OPTIONS: "--disable-warning=DEP0169"
# A missing dependency makes this suite SKIP rather than fail, so "0
# failed" would survive a run that executed almost nothing. The floor is
# set below the 500 currently passing so ordinary growth or a legitimate
# new skip does not trip it, while a collapse to a hollow green does.
- run: just e2e
env:
STUDYLOOP_MIN_PASSED: "450"
# The e2e tests already screenshot the page and dump its HTML when they
# fail (_diag in the journey files), but nothing collected those, so every
# CI failure had to be diagnosed from a stack trace alone -- a
# wait_for_function timeout says only that a condition never became true,
# never what the page actually showed instead. Uploading them turns the
# next failure into evidence rather than a hypothesis.
#
# if: failure() rather than always(): on a green run there is nothing to
# collect, and an empty artifact per run is noise.
- if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-failure-diagnostics
path: |
test-results/
packages/studyloop/test-results/
retention-days: 7
if-no-files-found: warn
content-profile:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
- run: uv sync --locked --all-packages --group dev --extra content
- run: just test-content
semantic-profile:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
- run: uv sync --locked --all-packages --group dev --extra semantic
- run: just test-semantic
build:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- run: ./scripts/build-release.sh
- run: uv run python scripts/check-release-consistency.py
install-smoke:
runs-on: ubuntu-latest
timeout-minutes: 15
needs: build
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.12"
- name: Build and smoke-test installed wheel
run: |
./scripts/build-release.sh
tmp="$(mktemp -d)"
uv venv "$tmp/venv"
uv pip install --python "$tmp/venv/bin/python" dist/studyloop-*.whl packages/agent-session-tools
STUDYLOOP_EXPECT_BIN_DIR="$tmp/venv/bin" PATH="$tmp/venv/bin:$PATH" ./scripts/smoke-installed-cli.sh