Skip to content

Commit 09d862a

Browse files
authored
Merge pull request #24 from mariuspruvot/ci/pipeline-improvements
ci: add mypy, coverage threshold, and claude-runner build
2 parents 754f8bc + cb6d3da commit 09d862a

6 files changed

Lines changed: 275 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ jobs:
1818
- run: uv sync --frozen
1919
- run: uv run ruff check src/ tests/
2020
- run: uv run ruff format --check src/ tests/
21+
- run: uv run mypy src/
2122

2223
test-backend:
2324
runs-on: ubuntu-latest
@@ -42,7 +43,7 @@ jobs:
4243
- uses: actions/checkout@v4
4344
- uses: astral-sh/setup-uv@v4
4445
- run: uv sync --frozen
45-
- run: uv run pytest
46+
- run: uv run pytest --cov=helprs --cov-report=term-missing --cov-fail-under=70
4647
env:
4748
DATABASE_URL: postgresql+asyncpg://helprs:helprs@localhost:5432/helprs_test
4849
SECRET_KEY: ci-test-secret-key
@@ -87,3 +88,4 @@ jobs:
8788
- uses: actions/checkout@v4
8889
- run: docker build -f infra/docker/Dockerfile.api --target production apps/api
8990
- run: docker build -f infra/docker/Dockerfile.web --target production apps/web
91+
- run: docker build -f infra/docker/claude-runner/Dockerfile infra/docker/claude-runner

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
.PHONY: dev lint test build build-runner migrate types
1+
.PHONY: dev lint test build build-runner migrate types typecheck
22

33
dev:
44
docker compose up --build
55

66
lint:
77
cd apps/api && uv run ruff check src/ tests/
88
cd apps/api && uv run ruff format --check src/ tests/
9+
cd apps/api && uv run mypy src/
910
cd apps/web && npx eslint src/
1011

12+
typecheck:
13+
cd apps/api && uv run mypy src/
14+
1115
test:
1216
cd apps/api && uv run pytest
1317
cd apps/web && npx vitest run

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# helPRs
22

3+
[![CI](https://github.com/mariuspruvot/helprs/actions/workflows/ci.yml/badge.svg)](https://github.com/mariuspruvot/helprs/actions/workflows/ci.yml)
4+
35
**Pluggable AI skill runner for pull requests.**
46

57
helPRs spins up ephemeral Docker containers running [Claude Code](https://docs.anthropic.com/en/docs/claude-code) to execute skills against your PRs -- comprehension quizzes, code reviews, security audits -- and streams results back in real time.

apps/api/pyproject.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ dev = [
2727
"ruff>=0.8.0",
2828
"pytest>=8.3.0",
2929
"pytest-asyncio>=0.24.0",
30+
"pytest-cov>=5.0.0",
3031
"httpx>=0.28.0",
32+
"mypy>=1.11.0",
3133
]
3234

3335
[build-system]
@@ -44,6 +46,33 @@ line-length = 120
4446
[tool.ruff.lint]
4547
select = ["E", "F", "I", "N", "UP", "B", "A", "SIM", "TCH"]
4648

49+
[tool.mypy]
50+
python_version = "3.12"
51+
warn_unused_configs = true
52+
ignore_missing_imports = true
53+
plugins = ["pydantic.mypy"]
54+
55+
[tool.pydantic-mypy]
56+
init_forbid_extra = true
57+
init_typed = true
58+
59+
# Per-module overrides for third-party lib typing issues (aiodocker, SQLAlchemy, Starlette)
60+
[[tool.mypy.overrides]]
61+
module = ["helprs.modules.container.*", "helprs.main"]
62+
disable_error_code = ["arg-type", "call-overload", "attr-defined"]
63+
64+
[[tool.mypy.overrides]]
65+
module = ["helprs.core.middleware"]
66+
disable_error_code = ["arg-type"]
67+
68+
[[tool.mypy.overrides]]
69+
module = ["helprs.modules.webhook.repository", "helprs.modules.webhook.verification"]
70+
disable_error_code = ["attr-defined", "arg-type"]
71+
72+
[[tool.mypy.overrides]]
73+
module = ["helprs.modules.installation.service"]
74+
disable_error_code = ["arg-type"]
75+
4776
[tool.pytest.ini_options]
4877
asyncio_mode = "auto"
4978
testpaths = ["tests"]

apps/api/tests/modules/webhook/test_dispatcher.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,25 @@
22

33
from unittest.mock import AsyncMock, patch
44

5+
import pytest
56
import structlog
67

78
from helprs.modules.webhook import dispatcher
89
from helprs.modules.webhook.dispatcher import DispatchResult
910

1011

12+
@pytest.fixture(autouse=True)
13+
def _reset_dispatcher_logger():
14+
"""Clear cached bound logger so structlog.testing.capture_logs() works.
15+
16+
create_app() calls configure_logging() with cache_logger_on_first_use=True.
17+
Once the module-level logger proxy in dispatcher.py resolves and caches its
18+
bound logger, capture_logs() can no longer intercept it. Replacing the proxy
19+
with a fresh one before each test fixes this.
20+
"""
21+
dispatcher.logger = structlog.get_logger()
22+
23+
1124
class TestDispatchWebhook:
1225
async def test_installation_created_routes_to_handler(self, db_session):
1326
mock_handler = AsyncMock()

0 commit comments

Comments
 (0)