Skip to content

Commit a80a756

Browse files
committed
Add GitHub Actions CI and apply ruff fixes
The new workflow has three jobs that run on push and pull requests against main: lint runs `ruff format --check` and `ruff check` over src/ and tests/; test runs the full pytest suite on Python 3.11, 3.12, and 3.13 with uv-managed interpreters; docker builds the production image and smoke-tests `teslamate-mcp list-tools` inside it. Concurrency group cancels superseded runs on the same ref. Apply ruff's auto-fixes to db.py and conftest.py so the lint job passes on a fresh checkout: combine nested async-with blocks, sort imports, and drop a stale noqa.
1 parent 8a3f914 commit a80a756

3 files changed

Lines changed: 81 additions & 22 deletions

File tree

.github/workflows/ci.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lint:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Set up uv
19+
uses: astral-sh/setup-uv@v3
20+
with:
21+
enable-cache: true
22+
- name: Install
23+
run: uv sync --frozen
24+
- name: Ruff format check
25+
run: uv run ruff format --check src tests
26+
- name: Ruff lint
27+
run: uv run ruff check src tests
28+
29+
test:
30+
runs-on: ubuntu-latest
31+
strategy:
32+
fail-fast: false
33+
matrix:
34+
python-version: ["3.11", "3.12", "3.13"]
35+
steps:
36+
- uses: actions/checkout@v4
37+
- name: Set up uv
38+
uses: astral-sh/setup-uv@v3
39+
with:
40+
enable-cache: true
41+
- name: Set up Python ${{ matrix.python-version }}
42+
run: uv python install ${{ matrix.python-version }}
43+
- name: Install
44+
run: uv sync --frozen
45+
- name: Run tests
46+
run: uv run pytest -ra
47+
48+
docker:
49+
runs-on: ubuntu-latest
50+
needs: [lint, test]
51+
steps:
52+
- uses: actions/checkout@v4
53+
- name: Set up Docker Buildx
54+
uses: docker/setup-buildx-action@v3
55+
- name: Build image
56+
uses: docker/build-push-action@v6
57+
with:
58+
context: .
59+
push: false
60+
load: true
61+
tags: teslamate-mcp:ci
62+
cache-from: type=gha
63+
cache-to: type=gha,mode=max
64+
- name: Smoke test CLI inside image
65+
run: docker run --rm teslamate-mcp:ci teslamate-mcp list-tools

src/teslamate_mcp/db.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,19 @@ async def fetch_readonly(
5454

5555
async with pool.connection() as conn:
5656
await conn.set_autocommit(False)
57-
async with conn.transaction(force_rollback=True):
58-
async with conn.cursor() as cur:
59-
await cur.execute("SET TRANSACTION READ ONLY")
60-
await cur.execute(
61-
sql.SQL("SET LOCAL statement_timeout = {ms}").format(
62-
ms=sql.Literal(stmt_ms)
63-
)
57+
async with conn.transaction(force_rollback=True), conn.cursor() as cur:
58+
await cur.execute("SET TRANSACTION READ ONLY")
59+
await cur.execute(
60+
sql.SQL("SET LOCAL statement_timeout = {ms}").format(ms=sql.Literal(stmt_ms))
61+
)
62+
await cur.execute(
63+
sql.SQL("SET LOCAL lock_timeout = {ms}").format(ms=sql.Literal(lock_ms))
64+
)
65+
await cur.execute(
66+
sql.SQL("SET LOCAL idle_in_transaction_session_timeout = {ms}").format(
67+
ms=sql.Literal(stmt_ms)
6468
)
65-
await cur.execute(
66-
sql.SQL("SET LOCAL lock_timeout = {ms}").format(
67-
ms=sql.Literal(lock_ms)
68-
)
69-
)
70-
await cur.execute(
71-
sql.SQL("SET LOCAL idle_in_transaction_session_timeout = {ms}").format(
72-
ms=sql.Literal(stmt_ms)
73-
)
74-
)
75-
await cur.execute(query)
76-
rows = await cur.fetchall()
69+
)
70+
await cur.execute(query)
71+
rows = await cur.fetchall()
7772
return rows_to_jsonable(rows)

tests/conftest.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@
2222
except ImportError: # pragma: no cover
2323
_HAS_TESTCONTAINERS = False
2424

25-
from teslamate_mcp.db import build_pool
2625
from teslamate_mcp.config import Settings
27-
26+
from teslamate_mcp.db import build_pool
2827

2928
_SETUP_SQL = """
3029
DROP TABLE IF EXISTS demo_cars;
@@ -52,7 +51,7 @@ def postgres_container():
5251
try:
5352
container = PostgresContainer("postgres:16-alpine")
5453
container.start()
55-
except Exception as exc: # noqa: BLE001 — broad on purpose, any docker issue → skip
54+
except Exception as exc:
5655
pytest.skip(f"Docker is not available: {exc}")
5756
try:
5857
yield container

0 commit comments

Comments
 (0)