-
Notifications
You must be signed in to change notification settings - Fork 0
263 lines (231 loc) · 10.3 KB
/
Copy pathci.yml
File metadata and controls
263 lines (231 loc) · 10.3 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
name: Code Mower CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
package_matrix:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.12", "3.13", "3.14"]
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: ${{ matrix.python-version }}
- name: Install package
run: |
python -m pip install --upgrade pip
python -m pip install ruff
python -m pip install -e '.[coworker]'
python -m pip check
python -c 'from code_mower import coworker_mcp; import keyring'
- name: Ruff lint
run: python -m ruff check .
- name: Privacy scan
run: python scripts/privacy_scan.py
- name: Documentation lifecycle
if: matrix.python-version == '3.12'
run: python -m code_mower.docs_lifecycle --json
- name: Current release documentation
if: matrix.python-version == '3.12'
run: python scripts/render_release.py --check
- name: Unit tests
run: python -m unittest discover -s tests
- name: Compile sources
run: python -m compileall src scripts
- name: Guard package workflow templates
run: python scripts/guard_package_workflows.py
- name: Install actionlint
if: matrix.python-version == '3.12'
run: |
go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.12
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
- name: Actionlint generated workflows
if: matrix.python-version == '3.12'
run: python scripts/actionlint_generated_workflows.py --code-mower-bin code-mower
- name: Release readiness
if: matrix.python-version == '3.12'
run: python -m code_mower.migration release-readiness --json
- name: Verify the base install without optional dependencies
if: matrix.python-version == '3.12'
run: |
python -m venv "$RUNNER_TEMP/code-mower-base"
"$RUNNER_TEMP/code-mower-base/bin/python" -m pip install "$GITHUB_WORKSPACE"
"$RUNNER_TEMP/code-mower-base/bin/python" -c 'import importlib.util; assert all(importlib.util.find_spec(name) is None for name in ("mcp", "keyring", "httpx2", "jwt"))'
- name: Easy-mode smoke with the base install
if: matrix.python-version == '3.12'
run: python scripts/smoke_easy_mode.py --code-mower-bin "$RUNNER_TEMP/code-mower-base/bin/code-mower" --work-dir "$RUNNER_TEMP/code-mower-smoke" --json
- name: Fresh-clone rehearsal
if: matrix.python-version == '3.12'
run: >-
python scripts/fresh_clone_rehearsal.py
--repo-url "$GITHUB_WORKSPACE"
--ref "$GITHUB_SHA"
--work-dir "$RUNNER_TEMP/code-mower-fresh-clone"
--json
- name: Package-install first-user rehearsal
if: matrix.python-version == '3.12'
run: >-
python -m code_mower.migration package-install-rehearsal
--package-spec "$GITHUB_WORKSPACE"
--work-dir "$RUNNER_TEMP/code-mower-package-install"
--python "$(command -v python)"
--timeout 240
--json
release_rehearsal:
name: release wheel rehearsal
runs-on: ubuntu-latest
env:
SOURCE_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
steps:
- name: Check out the exact rehearsal source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ env.SOURCE_SHA }}
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: "3.12"
- name: Build a pre-merge rehearsal pair
# No --release-pr: these bytes are explicitly ineligible for publication.
run: |
python -m pip install build twine PyYAML packaging
python scripts/release_candidate.py build --source "$GITHUB_WORKSPACE" \
--source-sha "$SOURCE_SHA" --dist "$RUNNER_TEMP/rehearsal-dist"
- name: Rehearse the exact installed wheel offline
run: |
python scripts/rehearse_release.py --dist "$RUNNER_TEMP/rehearsal-dist" \
--source-sha "$SOURCE_SHA" --work-dir "$RUNNER_TEMP/rehearsal"
- name: Upload sanitized pre-merge evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: release-rehearsal-evidence
path: |
${{ runner.temp }}/rehearsal-dist/candidate.json
${{ runner.temp }}/rehearsal/rehearsal.json
if-no-files-found: error
graph_containment:
# The local-graph boundary, against the real kernel mechanism rather than a
# stand-in for one. The unit suite skips these when a host offers no
# mechanism, which is right for a laptop and useless as coverage: this job
# installs bubblewrap and sets CODE_MOWER_REQUIRE_CONTAINMENT, which turns
# that skip into a failure.
name: graph containment
runs-on: ubuntu-latest
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: "3.12"
- name: Install bubblewrap
run: |
sudo apt-get update
sudo apt-get install -y bubblewrap
test -x /usr/bin/bwrap
# Ubuntu 24.04 restricts unprivileged user namespaces by default, which
# is what bubblewrap needs to build a mount namespace without being
# setuid. Enabling it is a property of this runner, not of the product:
# a host that refuses keeps refusing builds, which is the fail-closed
# posture. Reported rather than asserted, so the suite below is what
# decides the job.
- name: Allow unprivileged user namespaces
run: |
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
sudo sysctl -w kernel.unprivileged_userns_clone=1 || true
bwrap --unshare-net --dev-bind / / /bin/true \
&& echo "bwrap: namespaces available" \
|| echo "bwrap: refused a namespace on this runner"
- name: Install package
run: python -m pip install -e .
- name: Real containment tests
env:
CODE_MOWER_REQUIRE_CONTAINMENT: "1"
run: python -m unittest discover -s tests -p test_context_graph_lifecycle.py -v
graph_containment_macos:
# The Seatbelt half of the same claim. The bubblewrap job above proves the
# Linux boundary and nothing whatever about this one, and macOS is the
# platform this tool is developed on: leaving the profile to be exercised
# only by whoever happens to run the suite on a laptop is how it stayed
# unexecuted. ``sandbox-exec`` ships with the OS, so there is nothing to
# install -- the job is the evidence that the profile runs at all.
#
# Required, like the bubblewrap job. macOS containment is a behaviour claim
# in ``docs/context-graph-lifecycle.md``, and a claim whose only check is
# allowed to be red is not being checked. A red result still carries the
# probe's own diagnosis of which candidate failed and what the launcher
# said, which is what turned the equivalent bubblewrap failure into a
# one-round fix.
name: graph containment (macOS)
runs-on: macos-latest
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: "3.12"
- name: Confirm the system sandbox is present
run: test -x /usr/bin/sandbox-exec
- name: Install package
run: python -m pip install -e .
- name: Real containment tests
env:
CODE_MOWER_REQUIRE_CONTAINMENT: "1"
run: python -m unittest discover -s tests -p test_context_graph_lifecycle.py -v
board_qualification:
name: Board qualification
runs-on: ubuntu-latest
env:
QUALIFICATION_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: "3.12"
- name: Install package and browser test tool
run: |
python -m pip install -e .
npm install --prefix "$RUNNER_TEMP/board-browser" --no-audit --no-fund playwright@1.63.0
node "$RUNNER_TEMP/board-browser/node_modules/playwright/cli.js" install --with-deps chromium
- name: Local contract scorecard
run: >-
python scripts/qualify_board.py --head-sha "$QUALIFICATION_HEAD_SHA"
--output "$RUNNER_TEMP/board-qualification/scorecard.json"
- name: Desktop and phone Board fixtures
if: always()
run: |
python tests/board_qualification_fixtures.py "$RUNNER_TEMP/board-qualification"
NODE_PATH="$RUNNER_TEMP/board-browser/node_modules" node tests/board_qualification_browser.cjs "$RUNNER_TEMP/board-qualification"
- name: Upload allowlisted qualification metadata
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: board-qualification
path: |
${{ runner.temp }}/board-qualification/scorecard.json
${{ runner.temp }}/board-qualification/browser-scorecard.json
${{ runner.temp }}/board-qualification/board-1440.png
${{ runner.temp }}/board-qualification/board-390.png
package:
name: package
runs-on: ubuntu-latest
needs: [package_matrix, board_qualification, release_rehearsal]
if: always()
steps:
- name: Check matrix result
run: |
test "${{ needs.package_matrix.result }}" = "success"
test "${{ needs.board_qualification.result }}" = "success"
test "${{ needs.release_rehearsal.result }}" = "success"