Skip to content

Commit 0daa07f

Browse files
committed
Update documentation for Python-only CLI
- Rewrite README.md to focus on Python installation - Rename PYTHON_DEVELOPMENT.md to DEVELOPMENT.md - Update DEVELOPMENT.md to remove Java references - Mark PYTHON_REWRITE_PROGRESS.md as historical archive - Remove PHASE_6_PLAN.md (complete) The CLI is now fully Python-based with: - 479 passing tests - All major commands implemented - Modern Python tooling (ruff, mypy, pytest)
1 parent a1f09ed commit 0daa07f

5 files changed

Lines changed: 344 additions & 679 deletions

File tree

DEVELOPMENT.md

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
# Development Guide
2+
3+
Guide for developing the Seqera Platform CLI.
4+
5+
## Quick Start
6+
7+
### Installation
8+
9+
```bash
10+
# Install in development mode with all dependencies
11+
pip install -e ".[dev]"
12+
```
13+
14+
### Running Tests
15+
16+
```bash
17+
# Run all tests
18+
pytest
19+
20+
# Run specific test file
21+
pytest tests/credentials/test_credentials_cmd.py
22+
23+
# Run with verbose output
24+
pytest -v
25+
26+
# Run with coverage
27+
pytest --cov=seqera --cov-report=html
28+
```
29+
30+
### Running the CLI
31+
32+
```bash
33+
# Run the CLI directly
34+
python -m seqera.main --help
35+
36+
# Or if installed
37+
seqera --help
38+
39+
# Example: List credentials
40+
seqera credentials list
41+
42+
# Example with custom server
43+
seqera --url http://localhost:8080 --access-token your_token credentials list
44+
```
45+
46+
## Project Structure
47+
48+
```text
49+
tower-cli/
50+
├── src/seqera/ # Python source code
51+
│ ├── main.py # CLI entry point
52+
│ ├── api/ # API client
53+
│ │ └── client.py # SeqeraClient class
54+
│ ├── commands/ # CLI commands
55+
│ │ ├── actions/ # Actions commands
56+
│ │ ├── computeenvs/ # Compute environment commands
57+
│ │ ├── credentials/ # Credentials commands
58+
│ │ ├── datalinks/ # Data links commands
59+
│ │ ├── datasets/ # Datasets commands
60+
│ │ ├── labels/ # Labels commands
61+
│ │ ├── members/ # Members commands
62+
│ │ ├── organizations/ # Organizations commands
63+
│ │ ├── participants/ # Participants commands
64+
│ │ ├── pipelines/ # Pipeline commands
65+
│ │ ├── runs/ # Runs commands
66+
│ │ ├── secrets/ # Secrets commands
67+
│ │ ├── studios/ # Data studios commands
68+
│ │ ├── teams/ # Teams commands
69+
│ │ ├── workspaces/ # Workspaces commands
70+
│ │ ├── info.py # Info command
71+
│ │ └── launch.py # Launch command
72+
│ ├── exceptions/ # Custom exceptions
73+
│ ├── responses/ # Response models
74+
│ └── utils/ # Utilities (output formatting, etc.)
75+
└── tests/ # Tests
76+
├── conftest.py # Pytest fixtures
77+
└── ... # Command-specific tests
78+
```
79+
80+
## Code Quality
81+
82+
### Linting
83+
84+
```bash
85+
# Check code style
86+
ruff check src/ tests/
87+
88+
# Fix auto-fixable issues
89+
ruff check --fix src/ tests/
90+
```
91+
92+
### Formatting
93+
94+
```bash
95+
# Format code
96+
ruff format src/ tests/
97+
```
98+
99+
### Type Checking
100+
101+
```bash
102+
# Run mypy
103+
mypy src/seqera
104+
```
105+
106+
### Pre-commit Hooks
107+
108+
Install pre-commit hooks to run checks automatically:
109+
110+
```bash
111+
pre-commit install
112+
```
113+
114+
## Testing
115+
116+
### Test Structure
117+
118+
Tests are organized by command:
119+
120+
```text
121+
tests/
122+
├── conftest.py # Common fixtures
123+
├── test_info_cmd.py # Info command tests
124+
├── test_launch_cmd.py # Launch command tests
125+
├── actions/ # Actions tests
126+
├── credentials/ # Credentials tests
127+
└── ...
128+
```
129+
130+
### Writing Tests
131+
132+
Tests use pytest and pytest-httpserver for mocking API responses:
133+
134+
```python
135+
import pytest
136+
from pytest_httpserver import HTTPServer
137+
from tests.conftest import exec_command
138+
139+
140+
def test_list_credentials(
141+
httpserver: HTTPServer,
142+
cli_runner,
143+
base_args,
144+
) -> None:
145+
"""Test credentials list command."""
146+
# Mock API response
147+
httpserver.expect_request(
148+
"/credentials",
149+
method="GET",
150+
).respond_with_json({
151+
"credentials": [
152+
{"id": "1", "name": "test-cred"}
153+
]
154+
})
155+
156+
# Run command
157+
out = exec_command(
158+
cli_runner,
159+
base_args,
160+
["credentials", "list"],
161+
output_format="json"
162+
)
163+
164+
# Assert
165+
assert out.exit_code == 0
166+
assert "test-cred" in out.stdout
167+
```
168+
169+
### Test Fixtures
170+
171+
Common fixtures in `conftest.py`:
172+
173+
- `cli_runner` - Typer CLI test runner
174+
- `base_args` - Base CLI arguments (--url, --access-token, --insecure)
175+
- `api_url` - Mock server URL
176+
- `auth_token` - Test authentication token
177+
- `user_workspace_name` - Test user workspace name
178+
179+
### Running Specific Tests
180+
181+
```bash
182+
# Run tests for a specific command
183+
pytest tests/credentials/ -v
184+
185+
# Run tests matching a pattern
186+
pytest -k "test_list" -v
187+
188+
# Run with output capture disabled (for debugging)
189+
pytest -s tests/test_info_cmd.py
190+
```
191+
192+
## Adding New Commands
193+
194+
### 1. Create Command Module
195+
196+
```python
197+
# src/seqera/commands/mycommand/__init__.py
198+
import typer
199+
200+
app = typer.Typer(name="mycommand", help="My command description")
201+
202+
203+
@app.command("list")
204+
def list_items(
205+
workspace: str | None = typer.Option(None, "-w", "--workspace"),
206+
) -> None:
207+
"""List items."""
208+
# Implementation
209+
pass
210+
```
211+
212+
### 2. Register Command
213+
214+
```python
215+
# src/seqera/main.py
216+
from seqera.commands import mycommand
217+
218+
app.add_typer(mycommand.app, name="mycommand")
219+
```
220+
221+
### 3. Add Tests
222+
223+
```python
224+
# tests/mycommand/test_mycommand_cmd.py
225+
def test_list(httpserver, cli_runner, base_args):
226+
httpserver.expect_request("/my-endpoint").respond_with_json({...})
227+
out = exec_command(cli_runner, base_args, ["mycommand", "list"])
228+
assert out.exit_code == 0
229+
```
230+
231+
## Dependencies
232+
233+
### Runtime Dependencies
234+
235+
- `typer` - CLI framework
236+
- `httpx` - HTTP client
237+
- `rich` - Terminal formatting
238+
- `pydantic` - Data validation
239+
- `pyyaml` - YAML support
240+
241+
### Development Dependencies
242+
243+
- `pytest` - Testing framework
244+
- `pytest-httpserver` - HTTP mocking
245+
- `ruff` - Linter and formatter
246+
- `mypy` - Type checker
247+
- `pre-commit` - Git hooks
248+
249+
## Release Process
250+
251+
1. Update version in `pyproject.toml`
252+
2. Run tests: `pytest`
253+
3. Run quality checks: `ruff check && mypy src/seqera`
254+
4. Create release commit and tag
255+
5. Push to trigger CI/CD
256+
257+
## Troubleshooting
258+
259+
### Import Errors
260+
261+
If you get import errors, ensure the package is installed in development mode:
262+
263+
```bash
264+
pip install -e .
265+
```
266+
267+
### Test Discovery Issues
268+
269+
Ensure test files and functions follow naming conventions:
270+
- Files: `test_*.py`
271+
- Functions: `test_*`
272+
- Classes: `Test*`
273+
274+
### HTTP Mock Issues
275+
276+
If tests fail with unexpected requests, check the mock server logs for the actual requests being made vs. what was expected.

0 commit comments

Comments
 (0)