Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 23 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,31 @@ jobs:
- name: checkout repository
uses: actions/checkout@v3

- name: Set up python
uses: actions/setup-python@v3
- name: "Install just"
uses: extractions/setup-just@v3

- name: "Install uv"
uses: astral-sh/setup-uv@v5
with:
version: "0.7.19"

- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: 3.11
python-version-file: ".python-version"

- name: "Install dependencies"
run: uv sync --dev --no-cache-dir --locked

- name: "Run light linters"
run: just lint

- name: install dependencies
run: |
python -m pip install --upgrade pip
pip install uv
uv sync --dev --no-cache-dir
- name: "Run mypy"
run: just mypy

- name: install just
run: |
sudo apt install just
- name: "Run tests"
run: just test

- name: run tests
run: |
just test
- name: "Run CI checks in generated code"
run: just _ci_generation_check

- name: run linters in test catalog
run: |
just ci_lint_full
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Familiarize yourself with the [copier templating engine](https://copier.readthed

### Prerequisites

1. Install python 3.11 or greater. Consider using [pyenv](https://github.com/pyenv/pyenv#installation) if you work with multiple python versions
1. Install python 3.13 or greater. Consider using [pyenv](https://github.com/pyenv/pyenv#installation) if you work with multiple python versions
2. Install [uv](https://github.com/astral-sh/uv#installation)
3. Install project dependencies: `uv sync --dev`

Expand Down
4 changes: 4 additions & 0 deletions copier.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ docker:
type: bool
default: true
help: Enable Docker support

tasks:
# Make entrypoint executable if it exists
- [invoke, "chmod +x docker-entrypoint.sh || true", after-copy]
5 changes: 5 additions & 0 deletions example-answers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
author_email: author@email.test
author_name: test-author
description: Service description.
docker: true
project_name: test-service
122 changes: 96 additions & 26 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,37 +1,107 @@
PROJECT_NAME := "copier-python-project"
TEST_ANSWERS_FILE := ".copier/.copier-answers." + PROJECT_NAME + ".yml"
TEST_CATALOG := "test_catalog"
COPIER_ANSWERS_CATALOG := ".copier"
TEST_ANSWERS_FILE := COPIER_ANSWERS_CATALOG + "/.copier-answers." + PROJECT_NAME + ".yml"
PATHS_TO_LINT := "tests"

copy output="test_catalog":
uv run copier copy . {{ output }} \
--vcs-ref=HEAD
[doc("Command run when 'just' is called without any arguments")]
default: help

recopy output="test_catalog":
uv run copier recopy {{ output }} \
--vcs-ref=HEAD \
--answers-file {{ TEST_ANSWERS_FILE }} \
--skip-answered \
--overwrite
[doc("Prints this help message.")]
help:
just --list

update output="test_catalog":
uv run copier recopy {{ output }} \
[group("generation")]
[doc("Generates repo from template to output directory")]
copy output=TEST_CATALOG data_file="example-answers.yml":
uv run copier copy . {{ output }} \
--vcs-ref=HEAD \
--answers-file {{ TEST_ANSWERS_FILE }} \
--overwrite
--data-file {{ data_file }} \
--overwrite \
--UNSAFE \
--force

[group("generation")]
[doc("Deletes the output directory, excluding the answers file (it is remained for re-copying).")]
clear output=TEST_CATALOG:
find "{{ output }}" -mindepth 1 \
-not -path "{{ output }}/{{ COPIER_ANSWERS_CATALOG }}" \
-not -path "{{ output }}/{{ TEST_ANSWERS_FILE }}" \
-delete

[group("generation")]
[doc("Re-copies the template to the output directory, using the answers file. If clear is true, it deletes the output directory first.")]
recopy output=TEST_CATALOG clear="true" skip-answered="true":
@if {{ clear }}; then \
just clear {{ output }}; \
fi
uv run copier recopy {{ output }} \
--vcs-ref=HEAD \
--answers-file {{ TEST_ANSWERS_FILE }} \
--overwrite \
{{ if skip-answered == "true" { "--skip-answered" } else { "" } }}

[group("generation")]
[doc("Same as `recopy`, but with `skip-answered=false` to allow modifying answers.")]
update output=TEST_CATALOG clear="true":
just recopy output={{ output }} clear={{ clear }} skip-answered=false recopy

[group("generation")]
[doc("Runs linters and tests in the output directory.")]
run_lints_and_tests_in_output output=TEST_CATALOG:
cp {{ output }}/.env.example {{ output }}/.env
cd {{ output }} && uv lock
just --justfile {{ output }}/justfile dc all_ff

all_ff output="test_catalog":
just recopy {{ output }}
just --justfile {{ output }}/justfile all_ff
[group("development")]
[doc("Run all checks and tests (lints, mypy, tests...)")]
all: lint_full test

[group("development")]
[doc("Run all checks and tests, but fail on first that returns error (lints, mypy, tests...)")]
all_ff: lint_full_ff test

[group("development")]
[doc("Runs template tests.")]
test:
uv run pytest tests

ci_lint_full:
uv run copier copy . tmp/test_catalog \
--vcs-ref=HEAD \
--data project_name="test-project" \
--data description="..." \
--data author_name="Test Author" \
--data author_email="test@test.com" \
--data docker=false
[group("lint")]
[doc("Run all lint checks and mypy")]
lint_full: lint mypy
alias full_lint := lint_full

[group("lint")]
[doc("Run all lint checks and mypy, but fail on first that returns error")]
lint_full_ff: lint_ff mypy
alias full_lint_ff := lint_full_ff

[group("lint")]
[doc("Run all lightweight lint checks (no mypy)")]
@lint:
-just ruff

[group("lint")]
[doc("Run ruff lint check (code formatting)")]
ruff:
uv run ruff check {{PATHS_TO_LINT}}
uv run ruff format {{PATHS_TO_LINT}} --check

[group("lint")]
[doc("Run mypy check (type checking)")]
mypy:
uv run mypy {{PATHS_TO_LINT}} --show-error-codes --show-traceback --implicit-reexport

[group("lint")]
[doc("Run all lightweight lint checks, but fail on first that returns error")]
lint_ff: ruff

[group("lint")]
[doc("Automatically fix lint problems (only reported by ruff)")]
lint_fix:
uv run ruff check {{PATHS_TO_LINT}} --fix
uv run ruff format {{PATHS_TO_LINT}}

just --justfile tmp/test_catalog/justfile lint_full_ff
_ci_generation_check output=TEST_CATALOG:
just copy {{ output }}
just run_lints_and_tests_in_output {{ output }}
43 changes: 42 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,59 @@ name = "copier-python-project"
version = "0.1.0"
description = "Template for python project."
authors = [{ name = "Piotr Karaś", email = "pepe500p@gmail.com" }]
requires-python = ">=3.11"
requires-python = ">=3.13"
dependencies = []

[dependency-groups]
dev = [
"copier>=9.7.1,<10",
"mypy>=1.18.2",
"pytest>=8.4.1,<9",
"ruff>=0.14.2",
"types-pyyaml>=6.0.12.20250915",
]

[tool.uv]
package = false

[tool.ruff]
line-length = 120

[tool.ruff.lint]
# See https://docs.astral.sh/ruff/rules/ for more information.
select = [
"PT", # flake8-pytest-style
"B", # flake8-bugbear
"S", # flake8-bandit
"A", # flake8-builtins
"COM", # flake8-commas
"C4", # flake8-comprehensions
"T10", # flake8-debugger
"I", # isort
"T20", # flake8-print
"SIM", # flake8-simplify
"LOG", # flake8-logging
"G", # flake8-logging-format
"N", # pep8-naming
"E", # pycodestyle
"W", # pycodestyle
"F", # pyflakes
]
ignore = ["S101", "A003", "B904", "N818", "COM812"]

[tool.ruff.lint.flake8-pytest-style]
fixture-parentheses = true
mark-parentheses = true

[tool.ruff.lint.isort]
order-by-type = false

[tool.mypy]
disallow_untyped_defs = true
ignore_missing_imports = true
no_implicit_optional = false
disable_error_code = "misc"

[tool.pytest.ini_options]
python_files = ["tests.py", "test_*.py", "*_tests.py"]
testpaths = "tests"
7 changes: 7 additions & 0 deletions skeleton/.env.example.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# --- Env config
FLAVOR=localdev

# --- App config
SERVICE_NAME={{ project_name_kebab_case }}
PYTHONDONTWRITEBYTECODE=1
DEBUG=True
34 changes: 17 additions & 17 deletions skeleton/.github/workflows/ci.yml.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,32 @@ jobs:
steps:
- name: checkout repository
uses: actions/checkout@v3

- name: "Install just"
uses: extractions/setup-just@v3
{%- if docker %}

- name: run linters and tests
run: just dc _ci
{%- else %}

- name: setup python
uses: actions/setup-python@v3
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: 3.13
python-version-file: ".python-version"

- name: "Install dependencies"
run: uv sync --dev --no-cache-dir --frozen

- name: install dependencies
run: |
python -m pip install --upgrade pip
pip install uv
uv sync --dev --no-cache-dir
- name: "Run ruff"
run: just ruff

- name: install just
run: |
sudo apt install just
- name: "Run fawltydeps"
run: just deps

- name: run linters
run: |
just _ci_lint
- name: "Run mypy"
run: just mypy

- name: run tests
run: |
just _ci_test
- name: "Run tests"
run: just test
{%- endif %}
Loading