Add qa command entrypoints

This commit is contained in:
Abel Luck 2026-03-31 12:52:59 +02:00
parent f3f4badaa2
commit e796e09d14
4 changed files with 111 additions and 5 deletions

View file

@ -87,17 +87,16 @@ The state passed to a render-fn should be thought of as `{persistent db state, e
- Enter the dev environment with `nix develop` if you are not already inside it
- Sync Python dependencies with `uv sync --all-groups`.
- Run the app with `uv run repub`.
- Run `uv run qa` often while working. It runs Tailwind CSS generation, `black`, `flake8`, `pyright`, and the full test suite in that order.
- Run `uv run qa-final` at the end before declaring a task complete and always before staging or committing. It runs `uv run qa`, then `nix fmt`, then `nix flake check`.
- Generate CSS with `tailwindcss -i ./repub/static/app.tailwind.css -o ./repub/static/app.css` and add `--watch` when you need live rebuilds.
- Validate a generated feed with `./scripts/validate-feed path/to/feed.rss`. This wraps the local checkout at `~/src/github.com/w3c/feedvalidator` and pages the validator output through `less` by default.
```sh
uv sync --all-groups
uv run pytest
uv run flake8 repub/ tests/
uv run pyright
uv run qa
./scripts/validate-feed out/feeds/mn-cuba/feed.rss
nix fmt
nix flake check
uv run qa-final
uv run repub
uv run repub crawl -c repub.toml
```

View file

@ -27,6 +27,8 @@ dependencies = [
[project.scripts]
repub = "repub.entrypoint:entrypoint"
qa = "repub.qa:qa_entrypoint"
qa-final = "repub.qa:qa_final_entrypoint"
[dependency-groups]
dev = [

38
repub/qa.py Normal file
View file

@ -0,0 +1,38 @@
from __future__ import annotations
import subprocess
QA_COMMANDS: tuple[tuple[str, ...], ...] = (
(
"tailwindcss",
"-i",
"./repub/static/app.tailwind.css",
"-o",
"./repub/static/app.css",
),
("black", "repub/", "tests/"),
("flake8", "repub/", "tests/"),
("pyright",),
("pytest",),
)
QA_FINAL_COMMANDS: tuple[tuple[str, ...], ...] = QA_COMMANDS + (
("nix", "fmt"),
("nix", "flake", "check"),
)
def _run_commands(commands: tuple[tuple[str, ...], ...]) -> int:
for command in commands:
result = subprocess.run(command, check=False)
if result.returncode != 0:
return result.returncode
return 0
def qa_entrypoint() -> int:
return _run_commands(QA_COMMANDS)
def qa_final_entrypoint() -> int:
return _run_commands(QA_FINAL_COMMANDS)

67
tests/test_qa.py Normal file
View file

@ -0,0 +1,67 @@
import tomllib
from pathlib import Path
from types import SimpleNamespace
from repub.qa import qa_entrypoint, qa_final_entrypoint
def test_pyproject_registers_qa_scripts() -> None:
pyproject_path = Path(__file__).resolve().parents[1] / "pyproject.toml"
config = tomllib.loads(pyproject_path.read_text(encoding="utf-8"))
scripts = config["project"]["scripts"]
assert scripts["qa"] == "repub.qa:qa_entrypoint"
assert scripts["qa-final"] == "repub.qa:qa_final_entrypoint"
def test_qa_entrypoint_runs_expected_commands_in_order(monkeypatch) -> None:
recorded: list[tuple[str, ...]] = []
def fake_run(command: tuple[str, ...], *, check: bool) -> SimpleNamespace:
recorded.append(command)
return SimpleNamespace(returncode=0)
monkeypatch.setattr("repub.qa.subprocess.run", fake_run)
assert qa_entrypoint() == 0
assert recorded == [
(
"tailwindcss",
"-i",
"./repub/static/app.tailwind.css",
"-o",
"./repub/static/app.css",
),
("black", "repub/", "tests/"),
("flake8", "repub/", "tests/"),
("pyright",),
("pytest",),
]
def test_qa_final_entrypoint_runs_expected_commands_in_order(monkeypatch) -> None:
recorded: list[tuple[str, ...]] = []
def fake_run(command: tuple[str, ...], *, check: bool) -> SimpleNamespace:
recorded.append(command)
return SimpleNamespace(returncode=0)
monkeypatch.setattr("repub.qa.subprocess.run", fake_run)
assert qa_final_entrypoint() == 0
assert recorded == [
(
"tailwindcss",
"-i",
"./repub/static/app.tailwind.css",
"-o",
"./repub/static/app.css",
),
("black", "repub/", "tests/"),
("flake8", "repub/", "tests/"),
("pyright",),
("pytest",),
("nix", "fmt"),
("nix", "flake", "check"),
]