Skip to content

Commit a2bd582

Browse files
authored
add CLI checks and fix cross-SDK workflow issues (opensandbox-group#569)
* test(sdks): update quality * feat(cli): ruff check fix * feat(cli): pyright check fix * chore(workflow): cli quality workflow * chore(cli): refine packaging * test(sdks): fix tests
1 parent 91cfc2d commit a2bd582

26 files changed

Lines changed: 1405 additions & 43 deletions

File tree

.github/workflows/sdk-tests.yml

Lines changed: 229 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ on:
1818
pull_request:
1919
branches: [main]
2020
paths:
21+
- "cli/**"
2122
- "sdks/sandbox/**"
2223
- "sdks/code-interpreter/**"
2324
- "specs/**"
2425
push:
2526
branches: [main]
2627
paths:
28+
- "cli/**"
2729
- "sdks/sandbox/**"
2830
- "sdks/code-interpreter/**"
2931
- "specs/**"
@@ -36,6 +38,74 @@ concurrency:
3638
cancel-in-progress: true
3739

3840
jobs:
41+
cli-quality:
42+
name: CLI Quality
43+
runs-on: ubuntu-latest
44+
steps:
45+
- name: Checkout code
46+
uses: actions/checkout@v6
47+
48+
- name: Set up Python
49+
uses: actions/setup-python@v6
50+
with:
51+
python-version: "3.11"
52+
53+
- name: Install uv
54+
uses: astral-sh/setup-uv@v7
55+
with:
56+
version: "latest"
57+
58+
- name: Install dependencies
59+
working-directory: cli
60+
run: |
61+
uv sync
62+
63+
- name: Run ruff
64+
working-directory: cli
65+
run: |
66+
uv run ruff check
67+
68+
- name: Run pyright
69+
working-directory: cli
70+
run: |
71+
uv run pyright
72+
73+
cli-tests:
74+
name: CLI Tests
75+
runs-on: ubuntu-latest
76+
steps:
77+
- name: Checkout code
78+
uses: actions/checkout@v6
79+
80+
- name: Set up Python
81+
uses: actions/setup-python@v6
82+
with:
83+
python-version: "3.11"
84+
85+
- name: Install uv
86+
uses: astral-sh/setup-uv@v7
87+
with:
88+
version: "latest"
89+
90+
- name: Install dependencies
91+
working-directory: cli
92+
run: |
93+
uv sync
94+
95+
- name: Run tests
96+
working-directory: cli
97+
run: |
98+
mkdir -p reports
99+
uv run pytest tests/ -v --junitxml=reports/junit.xml
100+
101+
- name: Upload CLI reports
102+
if: always()
103+
uses: actions/upload-artifact@v4
104+
with:
105+
name: cli-reports
106+
path: |
107+
cli/reports/**
108+
39109
python-sdk-quality:
40110
name: Python SDK Quality (${{ matrix.package_name }})
41111
runs-on: ubuntu-latest
@@ -82,9 +152,19 @@ jobs:
82152
run: |
83153
uv run pyright
84154
85-
python-sdk:
86-
name: Python SDK Tests
155+
python-sdk-tests:
156+
name: Python SDK Tests (${{ matrix.package_name }})
87157
runs-on: ubuntu-latest
158+
strategy:
159+
fail-fast: false
160+
matrix:
161+
include:
162+
- package_name: sandbox
163+
package_dir: sdks/sandbox/python
164+
coverage_target: src/opensandbox
165+
- package_name: code-interpreter
166+
package_dir: sdks/code-interpreter/python
167+
coverage_target: src/code_interpreter
88168
steps:
89169
- name: Checkout code
90170
uses: actions/checkout@v6
@@ -99,20 +179,112 @@ jobs:
99179
with:
100180
version: "latest"
101181

182+
- name: Install dependencies
183+
working-directory: ${{ matrix.package_dir }}
184+
run: |
185+
uv sync
186+
102187
- name: Generate API
188+
if: matrix.package_name == 'sandbox'
103189
working-directory: sdks/sandbox/python
104190
run: |
105-
uv sync
106191
uv run python scripts/generate_api.py
107192
108193
- name: Run tests
109-
working-directory: sdks/sandbox/python
194+
working-directory: ${{ matrix.package_dir }}
195+
run: |
196+
mkdir -p reports
197+
uv run pytest tests/ -v \
198+
--junitxml=reports/junit.xml \
199+
--cov=${{ matrix.coverage_target }} \
200+
--cov-report=term-missing \
201+
--cov-report=xml:reports/coverage.xml
202+
203+
- name: Upload Python reports
204+
if: always()
205+
uses: actions/upload-artifact@v4
206+
with:
207+
name: python-${{ matrix.package_name }}-reports
208+
path: |
209+
${{ matrix.package_dir }}/reports/**
210+
211+
javascript-sdk-quality:
212+
name: JavaScript SDK Quality And Tests (${{ matrix.package_name }})
213+
runs-on: ubuntu-latest
214+
strategy:
215+
fail-fast: false
216+
matrix:
217+
include:
218+
- package_name: sandbox
219+
package_dir: sdks/sandbox/javascript
220+
- package_name: code-interpreter
221+
package_dir: sdks/code-interpreter/javascript
222+
steps:
223+
- name: Checkout code
224+
uses: actions/checkout@v6
225+
226+
- name: Set up pnpm
227+
uses: pnpm/action-setup@v4
228+
with:
229+
version: 9.15.0
230+
run_install: false
231+
232+
- name: Set up Node.js
233+
uses: actions/setup-node@v4
234+
with:
235+
node-version: "20"
236+
cache: "pnpm"
237+
cache-dependency-path: sdks/pnpm-lock.yaml
238+
239+
- name: Install dependencies
240+
working-directory: sdks
241+
run: |
242+
pnpm install --frozen-lockfile
243+
244+
- name: Build JavaScript SDK dependencies
245+
working-directory: sdks
246+
run: |
247+
pnpm run build:js
248+
249+
- name: Run eslint
250+
working-directory: ${{ matrix.package_dir }}
110251
run: |
111-
uv run pytest tests/ -v
252+
pnpm run lint
112253
113-
kotlin-sdk:
114-
name: Kotlin SDK Tests
254+
- name: Run TypeScript typecheck
255+
working-directory: ${{ matrix.package_dir }}
256+
run: |
257+
pnpm run typecheck
258+
259+
- name: Run tests
260+
working-directory: ${{ matrix.package_dir }}
261+
run: |
262+
mkdir -p reports
263+
node --test tests/*.test.mjs > reports/test-output.txt
264+
265+
- name: Upload JavaScript reports
266+
if: always()
267+
uses: actions/upload-artifact@v4
268+
with:
269+
name: javascript-${{ matrix.package_name }}-reports
270+
path: |
271+
${{ matrix.package_dir }}/reports/**
272+
273+
kotlin-sdk-quality:
274+
name: Kotlin SDK Quality And Tests (${{ matrix.package_name }})
115275
runs-on: ubuntu-latest
276+
strategy:
277+
fail-fast: false
278+
matrix:
279+
include:
280+
- package_name: sandbox
281+
package_dir: sdks/sandbox/kotlin
282+
test_task: :sandbox:test
283+
gradle_args: ""
284+
- package_name: code-interpreter
285+
package_dir: sdks/code-interpreter/kotlin
286+
test_task: :code-interpreter:test
287+
gradle_args: "-PuseMavenLocal"
116288
steps:
117289
- name: Checkout code
118290
uses: actions/checkout@v6
@@ -126,14 +298,41 @@ jobs:
126298
- name: Set up Gradle
127299
uses: gradle/actions/setup-gradle@v5
128300

129-
- name: Run tests
301+
- name: Publish sandbox SDK to Maven local
302+
if: matrix.package_name == 'code-interpreter'
130303
working-directory: sdks/sandbox/kotlin
131304
run: |
132-
./gradlew :sandbox:test
305+
./gradlew publishToMavenLocal
133306
134-
csharp-sdk:
135-
name: C# SDK Tests
307+
- name: Run quality checks and tests
308+
working-directory: ${{ matrix.package_dir }}
309+
run: |
310+
./gradlew spotlessCheck ${{ matrix.test_task }} ${{ matrix.gradle_args }}
311+
312+
- name: Upload Kotlin reports
313+
if: always()
314+
uses: actions/upload-artifact@v4
315+
with:
316+
name: kotlin-${{ matrix.package_name }}-reports
317+
path: |
318+
${{ matrix.package_dir }}/**/build/test-results/test/**
319+
${{ matrix.package_dir }}/**/build/reports/tests/test/**
320+
321+
csharp-sdk-quality:
322+
name: C# SDK Quality And Tests (${{ matrix.package_name }})
136323
runs-on: ubuntu-latest
324+
strategy:
325+
fail-fast: false
326+
matrix:
327+
include:
328+
- package_name: sandbox
329+
package_dir: sdks/sandbox/csharp
330+
solution: OpenSandbox.sln
331+
test_project: tests/OpenSandbox.Tests/OpenSandbox.Tests.csproj
332+
- package_name: code-interpreter
333+
package_dir: sdks/code-interpreter/csharp
334+
solution: OpenSandbox.CodeInterpreter.sln
335+
test_project: tests/OpenSandbox.CodeInterpreter.Tests/OpenSandbox.CodeInterpreter.Tests.csproj
137336
steps:
138337
- name: Checkout code
139338
uses: actions/checkout@v6
@@ -143,12 +342,25 @@ jobs:
143342
with:
144343
dotnet-version: "10.0.x"
145344

146-
- name: Run sandbox tests
147-
working-directory: sdks/sandbox/csharp
345+
- name: Build with analyzers
346+
working-directory: ${{ matrix.package_dir }}
148347
run: |
149-
dotnet test tests/OpenSandbox.Tests/OpenSandbox.Tests.csproj --configuration Release
348+
dotnet build ${{ matrix.solution }} --configuration Release /warnaserror
150349
151-
- name: Run code interpreter tests
152-
working-directory: sdks/code-interpreter/csharp
350+
- name: Run tests with reports
351+
working-directory: ${{ matrix.package_dir }}
153352
run: |
154-
dotnet test tests/OpenSandbox.CodeInterpreter.Tests/OpenSandbox.CodeInterpreter.Tests.csproj --configuration Release
353+
dotnet test ${{ matrix.test_project }} \
354+
--configuration Release \
355+
--no-build \
356+
--logger "trx;LogFileName=test-results.trx" \
357+
--results-directory TestResults \
358+
--collect:"XPlat Code Coverage"
359+
360+
- name: Upload C# reports
361+
if: always()
362+
uses: actions/upload-artifact@v4
363+
with:
364+
name: csharp-${{ matrix.package_name }}-reports
365+
path: |
366+
${{ matrix.package_dir }}/TestResults/**

cli/README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pip install opensandbox-cli
1313
### uv
1414

1515
```bash
16-
uv add opensandbox-cli
16+
uv tool install opensandbox-cli
1717
```
1818

1919
### pipx (recommended for global CLI usage)
@@ -46,7 +46,8 @@ opensandbox-server
4646

4747
```bash
4848
cd cli
49-
uv pip install -e .
49+
uv sync
50+
uv run osb --help
5051
```
5152

5253
![Install CLI](assets/install_cli.png)
@@ -205,6 +206,18 @@ The CLI resolves configuration from multiple sources with the following priority
205206
3. **Config file**`~/.opensandbox/config.toml` (or path specified via `--config`)
206207
4. **SDK defaults**
207208

209+
## Development
210+
211+
For local CLI development in this monorepo, prefer `uv sync` from the `cli/` directory. That workflow honors the local `[tool.uv.sources]` overrides for `opensandbox` and `opensandbox-code-interpreter`, so the CLI resolves against the checked-out SDKs instead of published packages.
212+
213+
```bash
214+
cd cli
215+
uv sync
216+
uv run osb --help
217+
```
218+
219+
If you specifically need an editable install into another environment, install the SDK dependencies from their local paths first, then install the CLI.
220+
208221
### Config File Format
209222

210223
```toml

cli/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ classifiers = [
3939
"Programming Language :: Python :: 3.12",
4040
"Programming Language :: Python :: 3.13",
4141
"Topic :: Software Development :: Libraries",
42+
"Typing :: Typed",
4243
]
4344
dependencies = [
4445
"opensandbox>=0.1.4,<0.2.0",

cli/src/opensandbox_cli/client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from typing import Any
2323

2424
import click
25-
2625
from opensandbox.config.connection_sync import ConnectionConfigSync
2726
from opensandbox.models.sandboxes import SandboxFilter
2827
from opensandbox.sync.manager import SandboxManagerSync

cli/src/opensandbox_cli/commands/code.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import sys
2020

2121
import click
22-
2322
from opensandbox.models.execd import OutputMessage
2423
from opensandbox.models.execd_sync import ExecutionHandlersSync
2524

@@ -54,10 +53,11 @@ def code_run(
5453
"""Execute code in a sandbox."""
5554
from code_interpreter.sync.code_interpreter import CodeInterpreterSync
5655

57-
if code is None:
56+
source_code = code
57+
if source_code is None:
5858
if sys.stdin.isatty():
5959
click.echo("Reading code from stdin (Ctrl+D to finish):", err=True)
60-
code = sys.stdin.read()
60+
source_code = sys.stdin.read()
6161

6262
sandbox = obj.connect_sandbox(sandbox_id)
6363
try:
@@ -78,7 +78,7 @@ def on_stderr(msg: OutputMessage) -> None:
7878

7979
handlers = ExecutionHandlersSync(on_stdout=on_stdout, on_stderr=on_stderr)
8080
execution = interpreter.codes.run(
81-
code, language=language, handlers=handlers, **kwargs
81+
source_code, language=language, handlers=handlers, **kwargs
8282
)
8383

8484
if execution.error:

0 commit comments

Comments
 (0)