diff --git a/{{cookiecutter.project_slug}}/.dockerignore b/{{cookiecutter.project_slug}}/.dockerignore new file mode 100644 index 0000000..9d74002 --- /dev/null +++ b/{{cookiecutter.project_slug}}/.dockerignore @@ -0,0 +1,9 @@ +.venv +__pycache__ +*.pyc +.mypy_cache +.ruff_cache +.pytest_cache +build +dist +*.egg-info diff --git a/{{cookiecutter.project_slug}}/Dockerfile b/{{cookiecutter.project_slug}}/Dockerfile new file mode 100644 index 0000000..6b1ad3b --- /dev/null +++ b/{{cookiecutter.project_slug}}/Dockerfile @@ -0,0 +1,9 @@ +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +WORKDIR /app + +COPY pyproject.toml uv.lock* ./ +RUN uv sync --group dev --no-install-project + +COPY . . +RUN uv sync --group dev diff --git a/{{cookiecutter.project_slug}}/README.md b/{{cookiecutter.project_slug}}/README.md index 1170744..def641d 100644 --- a/{{cookiecutter.project_slug}}/README.md +++ b/{{cookiecutter.project_slug}}/README.md @@ -21,4 +21,5 @@ source init.sh uv run invoke lint uv run invoke test uv run invoke format +uv run invoke ci # lint + test in Docker ``` diff --git a/{{cookiecutter.project_slug}}/tasks.py b/{{cookiecutter.project_slug}}/tasks.py index dee4891..be12127 100644 --- a/{{cookiecutter.project_slug}}/tasks.py +++ b/{{cookiecutter.project_slug}}/tasks.py @@ -28,6 +28,20 @@ def test(c): c.run("uv run pytest --cov=src --cov-report=term-missing") +@task +def ci(c): + """Run lint and tests in a clean Docker container.""" + image = "{{ cookiecutter.project_slug }}-ci" + c.run(f"docker build --network=host -t {image} .") + cmd = ( + "uv run ruff check src tests && " + "uv run ruff format --check src tests && " + "uv run mypy src && " + "uv run pytest --cov=src --cov-report=term-missing" + ) + c.run(f"docker run --rm {image} sh -c '{cmd}'") + + @task def clean(c): """Preview files to delete (safe mode)."""