From 84fc5e4b144fafb6a6d1b0668f557cf1d0c4a759 Mon Sep 17 00:00:00 2001 From: Artsiom Siamashka Date: Mon, 30 Mar 2026 09:54:38 +0000 Subject: [PATCH] Initial --- .devcontainer/devcontainer.json | 22 ++++++++++ .dockerignore | 48 ++++++++++++++++++++++ .gitignore | 66 ++++++++++++++++++++++++++++++ .pre-commit-config.yaml | 50 ++++++++++++++++++++++ Dockerfile | 18 ++++++++ README.md | 18 ++++++++ pyproject.toml | 28 +++++++++++++ src/comment_automation/__init__.py | 1 + src/comment_automation/main.py | 14 +++++++ tests/test_health.py | 13 ++++++ 10 files changed, 278 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 pyproject.toml create mode 100644 src/comment_automation/__init__.py create mode 100644 src/comment_automation/main.py create mode 100644 tests/test_health.py diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a6015ed --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/python +{ + "name": "Python 3", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/python:3-3.14-trixie" + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "pip3 install --user -r requirements.txt", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..610f752 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,48 @@ +# VCS +.git/ +.gitignore + +# Python cache / bytecode +__pycache__/ +*.py[cod] +*$py.class + +# Build / packaging artifacts +build/ +dist/ +*.egg-info/ +.eggs/ +pip-wheel-metadata/ + +# Test and coverage artifacts +.pytest_cache/ +.tox/ +.nox/ +.coverage +.coverage.* +htmlcov/ + +# Type checker / linter caches +.mypy_cache/ +.pytype/ +.pyre/ +.ruff_cache/ + +# Virtual environments +.venv/ +venv/ +env/ +ENV/ + +# Local env/config files +.env +.env.* + +# IDE and notebook artifacts +.vscode/ +.idea/ +.ipynb_checkpoints/ + +# Logs and temp files +*.log +*.tmp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb2b84b --- /dev/null +++ b/.gitignore @@ -0,0 +1,66 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +dist/ +downloads/ +.eggs/ +*.egg-info/ +*.egg +pip-wheel-metadata/ + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +.pytest_cache/ +coverage.xml +*.cover + +# Type checkers / linters +.mypy_cache/ +.pytype/ +.pyre/ +.ruff_cache/ + +# Virtual environments +.venv/ +venv/ +env/ +ENV/ + +# IDEs and editors +.vscode/ +.idea/ +*.swp + +# Jupyter +.ipynb_checkpoints/ + +# Environment variables +.env +.env.* + +# OS generated files +.DS_Store +Thumbs.db + +# Logs +*.log + +# Local application data +instance/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..cec3606 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,50 @@ +minimum_pre_commit_version: 4.0.0 +fail_fast: false + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - id: check-merge-conflict + + - repo: local + hooks: + - id: black + name: black + entry: uv run black --check --diff + language: system + types_or: [python] + + - id: isort + name: isort + entry: uv run isort --check-only --diff + language: system + types_or: [python] + + - id: ruff + name: ruff + entry: uv run ruff check + language: system + types_or: [python] + + - id: bandit + name: bandit + entry: uv run bandit -q -r src + language: system + pass_filenames: false + + - id: ty + name: ty + entry: uv run ty check + language: system + pass_filenames: false + + - id: pytest + name: pytest-with-coverage + entry: uv run pytest -q + language: system + pass_filenames: false + stages: [pre-push] diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ac2bb08 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM python:3.12-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + UV_LINK_MODE=copy + +WORKDIR /app + +RUN pip install --no-cache-dir uv + +COPY pyproject.toml ./ +RUN uv sync --no-install-project + +COPY src ./src + +EXPOSE 8000 + +CMD ["uv", "run", "uvicorn", "comment_automation.main:app", "--app-dir", "src", "--host", "0.0.0.0", "--port", "8000"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..b252247 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# CommentAutomation + +Python project initialized with uv. + +## Quick start + +1. Install uv. +2. Sync dependencies: + + uv sync --group dev + +3. Run the app: + + uv run uvicorn comment_automation.main:app --app-dir src --host 0.0.0.0 --port 8000 + +4. Run tests: + + uv run pytest diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..7d9812f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[project] +name = "comment-automation" +version = "0.1.0" +description = "Comment automation service" +readme = "README.md" +requires-python = ">=3.11" +dependencies = [ + "fastapi[standard]>=0.116.0", + "pydantic>=2.11.0", + "uplink>=0.9.7", +] + +[dependency-groups] +dev = [ + "pytest>=8.3.0", + "pre-commit>=4.2.0", +] + +[build-system] +requires = ["hatchling>=1.24.2"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["src/comment_automation"] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "-q" diff --git a/src/comment_automation/__init__.py b/src/comment_automation/__init__.py new file mode 100644 index 0000000..51b92c8 --- /dev/null +++ b/src/comment_automation/__init__.py @@ -0,0 +1 @@ +"""CommentAutomation package.""" diff --git a/src/comment_automation/main.py b/src/comment_automation/main.py new file mode 100644 index 0000000..a44011f --- /dev/null +++ b/src/comment_automation/main.py @@ -0,0 +1,14 @@ +from fastapi import FastAPI +from pydantic import BaseModel + + +app = FastAPI(title="CommentAutomation") + + +class HealthResponse(BaseModel): + status: str + + +@app.get("/health", response_model=HealthResponse) +def health() -> HealthResponse: + return HealthResponse(status="ok") diff --git a/tests/test_health.py b/tests/test_health.py new file mode 100644 index 0000000..bed373e --- /dev/null +++ b/tests/test_health.py @@ -0,0 +1,13 @@ +from fastapi.testclient import TestClient + +from comment_automation.main import app + + +client = TestClient(app) + + +def test_health() -> None: + response = client.get("/health") + + assert response.status_code == 200 + assert response.json() == {"status": "ok"}