diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a47119c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,81 @@ +name: CI + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + lint-format: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.10" + + - name: Set up uv + uses: astral-sh/setup-uv@v5 + + - name: Install dependencies + run: uv sync --frozen --all-extras --dev + + - name: Run Ruff lint + run: uv run ruff check . + + - name: Check Ruff formatting + run: uv run ruff format --check . + + unit-tests: + runs-on: ubuntu-latest + + env: + OPENAI_API_KEY: test-key + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.10" + + - name: Set up uv + uses: astral-sh/setup-uv@v5 + + - name: Install dependencies + run: uv sync --frozen --all-extras --dev + + - name: Run unit tests + run: uv run pytest tests --ignore=tests/e2e + + e2e-tests: + runs-on: ubuntu-latest + + env: + OPENAI_API_KEY: test-key + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.10" + + - name: Set up uv + uses: astral-sh/setup-uv@v5 + + - name: Install dependencies + run: uv sync --frozen --all-extras --dev + + - name: Run e2e tests + run: uv run pytest tests/e2e -o addopts='' diff --git a/src/specode/__init__.py b/src/specode/__init__.py index b8c6ad5..4f237bc 100644 --- a/src/specode/__init__.py +++ b/src/specode/__init__.py @@ -3,4 +3,3 @@ __all__ = ["__version__"] __version__ = "0.1.0" - diff --git a/tests/e2e/test_cli_process.py b/tests/e2e/test_cli_process.py index 816ca92..3f430fe 100644 --- a/tests/e2e/test_cli_process.py +++ b/tests/e2e/test_cli_process.py @@ -79,7 +79,9 @@ def test_specode_exits_with_configuration_error_when_openai_api_key_is_missing( tmp_path: Path, ) -> None: result, env = _run_specode(tmp_path, stdin="", extra_env={"OPENAI_API_KEY": ""}) - diagnostics = _format_diagnostics(env, result.stdout, result.stderr, returncode=result.returncode) + diagnostics = _format_diagnostics( + env, result.stdout, result.stderr, returncode=result.returncode + ) assert result.returncode == 1, diagnostics assert "Configuration Error" in result.stdout, diagnostics @@ -92,7 +94,9 @@ def test_specode_handles_help_then_exit_without_calling_a_model(tmp_path: Path) stdin="/help\n/exit\n", extra_env={"OPENAI_API_KEY": "test-key"}, ) - diagnostics = _format_diagnostics(env, result.stdout, result.stderr, returncode=result.returncode) + diagnostics = _format_diagnostics( + env, result.stdout, result.stderr, returncode=result.returncode + ) assert result.returncode == 0, diagnostics assert "Type / for commands" in result.stdout, diagnostics diff --git a/tests/e2e/test_terminal_pty.py b/tests/e2e/test_terminal_pty.py index 4a0cb29..4bf43bf 100644 --- a/tests/e2e/test_terminal_pty.py +++ b/tests/e2e/test_terminal_pty.py @@ -21,9 +21,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2] COMMAND = "uv run specode" PTY_TIMEOUT_SECONDS = 4 -ANSI_ESCAPE_PATTERN = re.compile( - r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\))" -) +ANSI_ESCAPE_PATTERN = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\))") def _isolated_env(tmp_path: Path) -> dict[str, str]: diff --git a/tests/test_config.py b/tests/test_config.py index eee327a..bb5fd3a 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -9,7 +9,9 @@ ) -def test_raises_a_clear_error_when_openai_api_key_is_missing(monkeypatch: pytest.MonkeyPatch) -> None: +def test_raises_a_clear_error_when_openai_api_key_is_missing( + monkeypatch: pytest.MonkeyPatch, +) -> None: monkeypatch.setenv("OPENAI_API_KEY", "") with pytest.raises(ConfigurationError) as exc_info: