forked from ChelseaKR/mrf-honest
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
58 lines (50 loc) · 2.59 KB
/
Copy pathMakefile
File metadata and controls
58 lines (50 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
PYTHON ?= .venv/bin/python
UV ?= uv
.PHONY: verify lint format typecheck test lock audit
verify: lint format typecheck test lock audit
lint:
$(PYTHON) -m ruff check src tests perf
format:
$(PYTHON) -m ruff format --check src tests perf
typecheck:
$(PYTHON) -m mypy
test:
$(PYTHON) -m pytest --cov --cov-report=term-missing -q
# `uv lock --check` is the lockfile-drift gate, and the exact spelling matters.
# Measured on a deliberately drifted project (a dependency added to pyproject.toml, the
# lockfile left alone), uv 0.12.1:
#
# uv lock --check -> exit 1 (sees the drift)
# uv sync --locked -> exit 1 (sees the drift)
# uv sync --frozen -> exit 0 (does not)
#
# `--frozen` installs from the lockfile without consulting pyproject.toml at all, so it
# cannot observe the two disagreeing. A `uv sync --frozen` step is a real reproducibility
# guarantee and is not a drift check, and this repository's CI previously relied on it as
# though it were one. Note also that a bare `uv run` rewrites the lockfile in place when it
# is stale, so a drift gate must never be invoked through `uv run` -- it would repair the
# very condition it is there to report.
lock:
$(UV) lock --check
# CQ-11. The audited surface is the *lockfile*, exported with every extra and the dev group,
# not whatever happens to be installed in someone's .venv -- so the answer is the same on a
# laptop and in CI. `--no-deps` is correct here because uv has already produced a complete
# pinned resolution; pip-audit only has to look each pin up.
#
# There is deliberately no ignore list and no `|| true`. The mute pattern is what turns an
# audit into decoration. `--strict` makes a dependency that could not be audited a failure
# rather than a silence, and the project itself is excluded from the export (it is not on
# PyPI, and under `--strict` an unauditable local package would otherwise fail the run for
# the wrong reason).
#
# `mktemp` is called with a full template rather than `-t <prefix>`: BSD mktemp treats `-t`'s
# argument as a prefix and appends the random part itself, while GNU coreutils treats it as a
# template and rejects one with fewer than three X's. `mktemp -t mrf-honest-audit` therefore
# works on macOS and fails on the Linux runner with "too few X's in template", which is how
# this gate passed locally and failed in CI.
audit:
@req="$$(mktemp "$${TMPDIR:-/tmp}/mrf-honest-audit.XXXXXX")"; \
trap 'rm -f "$$req"' EXIT; \
$(UV) export --frozen --no-emit-project --all-extras --no-hashes \
--format requirements-txt -o "$$req" -q && \
$(PYTHON) -m pip_audit --strict --no-deps -r "$$req" --progress-spinner off