mirror of
https://github.com/basnijholt/compose-farm.git
synced 2026-02-09 08:42:17 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d07cbdff0 | ||
|
|
0f67c17281 | ||
|
|
bd22a1a55e |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -54,7 +54,7 @@ jobs:
|
||||
run: uv run playwright install chromium --with-deps
|
||||
|
||||
- name: Run browser tests
|
||||
run: uv run pytest -m browser -v --no-cov
|
||||
run: uv run pytest -m browser -n auto -v
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
14
CLAUDE.md
14
CLAUDE.md
@@ -66,8 +66,8 @@ Use `just` for common tasks. Run `just` to list available commands:
|
||||
|---------|-------------|
|
||||
| `just install` | Install dev dependencies |
|
||||
| `just test` | Run all tests |
|
||||
| `just test-unit` | Run unit tests (parallel) |
|
||||
| `just test-browser` | Run browser tests |
|
||||
| `just test-cli` | Run CLI tests (parallel) |
|
||||
| `just test-web` | Run web UI tests (parallel) |
|
||||
| `just lint` | Lint, format, and type check |
|
||||
| `just web` | Start web UI (port 9001) |
|
||||
| `just doc` | Build and serve docs (port 9002) |
|
||||
@@ -78,17 +78,17 @@ Use `just` for common tasks. Run `just` to list available commands:
|
||||
Run tests with `just test` or `uv run pytest`. Browser tests require Chromium (system-installed or via `playwright install chromium`):
|
||||
|
||||
```bash
|
||||
# Unit tests only (skip browser tests, can parallelize)
|
||||
# Unit tests only (parallel)
|
||||
uv run pytest -m "not browser" -n auto
|
||||
|
||||
# Browser tests only (run sequentially, no coverage)
|
||||
uv run pytest -m browser --no-cov
|
||||
# Browser tests only (parallel)
|
||||
uv run pytest -m browser -n auto
|
||||
|
||||
# All tests
|
||||
uv run pytest --no-cov
|
||||
uv run pytest
|
||||
```
|
||||
|
||||
Browser tests are marked with `@pytest.mark.browser`. They use Playwright to test HTMX behavior, JavaScript functionality (sidebar filter, command palette, terminals), and content stability during navigation. Run sequentially (no `-n`) to avoid resource contention.
|
||||
Browser tests are marked with `@pytest.mark.browser`. They use Playwright to test HTMX behavior, JavaScript functionality (sidebar filter, command palette, terminals), and content stability during navigation.
|
||||
|
||||
## Communication Notes
|
||||
|
||||
|
||||
14
justfile
14
justfile
@@ -9,17 +9,17 @@ default:
|
||||
install:
|
||||
uv sync --all-extras --dev
|
||||
|
||||
# Run all tests (no coverage for speed)
|
||||
# Run all tests (parallel)
|
||||
test:
|
||||
uv run pytest --no-cov
|
||||
uv run pytest -n auto
|
||||
|
||||
# Run unit tests only (parallel, with coverage)
|
||||
test-unit:
|
||||
# Run CLI tests only (parallel, with coverage)
|
||||
test-cli:
|
||||
uv run pytest -m "not browser" -n auto
|
||||
|
||||
# Run browser tests only (sequential, no coverage)
|
||||
test-browser:
|
||||
uv run pytest -m browser --no-cov
|
||||
# Run web UI tests only (parallel)
|
||||
test-web:
|
||||
uv run pytest -m browser -n auto
|
||||
|
||||
# Lint, format, and type check
|
||||
lint:
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import getpass
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
@@ -14,7 +15,7 @@ from .paths import config_search_paths, find_config_path
|
||||
COMPOSE_FILENAMES = ("compose.yaml", "compose.yml", "docker-compose.yml", "docker-compose.yaml")
|
||||
|
||||
|
||||
class Host(BaseModel):
|
||||
class Host(BaseModel, extra="forbid"):
|
||||
"""SSH host configuration."""
|
||||
|
||||
address: str
|
||||
@@ -22,7 +23,7 @@ class Host(BaseModel):
|
||||
port: int = 22
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
class Config(BaseModel, extra="forbid"):
|
||||
"""Main configuration."""
|
||||
|
||||
compose_dir: Path = Path("/opt/compose")
|
||||
@@ -113,7 +114,7 @@ class Config(BaseModel):
|
||||
return found
|
||||
|
||||
|
||||
def _parse_hosts(raw_hosts: dict[str, str | dict[str, str | int]]) -> dict[str, Host]:
|
||||
def _parse_hosts(raw_hosts: dict[str, Any]) -> dict[str, Host]:
|
||||
"""Parse hosts from config, handling both simple and full forms."""
|
||||
hosts = {}
|
||||
for name, value in raw_hosts.items():
|
||||
@@ -122,11 +123,7 @@ def _parse_hosts(raw_hosts: dict[str, str | dict[str, str | int]]) -> dict[str,
|
||||
hosts[name] = Host(address=value)
|
||||
else:
|
||||
# Full form: hostname: {address: ..., user: ..., port: ...}
|
||||
hosts[name] = Host(
|
||||
address=str(value.get("address", "")),
|
||||
user=str(value["user"]) if "user" in value else getpass.getuser(),
|
||||
port=int(value["port"]) if "port" in value else 22,
|
||||
)
|
||||
hosts[name] = Host(**value)
|
||||
return hosts
|
||||
|
||||
|
||||
|
||||
@@ -236,8 +236,8 @@ async def _run_shell_session(
|
||||
await websocket.send_text(f"{RED}Host '{host_name}' not found{RESET}{CRLF}")
|
||||
return
|
||||
|
||||
# Start interactive shell in home directory (avoid login shell to prevent job control warnings)
|
||||
shell_cmd = "cd ~ && exec bash -i 2>/dev/null || exec sh -i"
|
||||
# Start interactive shell in home directory
|
||||
shell_cmd = "cd ~ && exec bash -i || exec sh -i"
|
||||
|
||||
if is_local(host):
|
||||
# Local: use argv list with shell -c to interpret the command
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
# Thresholds in seconds, per OS
|
||||
if sys.platform == "win32":
|
||||
CLI_STARTUP_THRESHOLD = 2.0
|
||||
@@ -16,6 +19,10 @@ else: # Linux
|
||||
CLI_STARTUP_THRESHOLD = 0.25
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
"PYTEST_XDIST_WORKER" in os.environ,
|
||||
reason="Skip in parallel mode due to resource contention",
|
||||
)
|
||||
def test_cli_startup_time() -> None:
|
||||
"""Verify CLI startup time stays within acceptable bounds.
|
||||
|
||||
|
||||
@@ -39,6 +39,15 @@ services:
|
||||
image: grafana/grafana
|
||||
""")
|
||||
|
||||
# Create a single-service stack for testing service commands
|
||||
redis_dir = compose_path / "redis"
|
||||
redis_dir.mkdir()
|
||||
(redis_dir / "compose.yaml").write_text("""
|
||||
services:
|
||||
redis:
|
||||
image: redis:alpine
|
||||
""")
|
||||
|
||||
return compose_path
|
||||
|
||||
|
||||
@@ -59,6 +68,7 @@ hosts:
|
||||
stacks:
|
||||
plex: server-1
|
||||
grafana: server-2
|
||||
redis: server-1
|
||||
""")
|
||||
|
||||
# State file must be alongside config file
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user