Skip to content

deps(uv): wywal workspace install + udokumentuj 11 sdist-only exceptions#177

Merged
mpasternak merged 3 commits into
devfrom
security/uv-binary-only
Apr 27, 2026
Merged

deps(uv): wywal workspace install + udokumentuj 11 sdist-only exceptions#177
mpasternak merged 3 commits into
devfrom
security/uv-binary-only

Conversation

@mpasternak
Copy link
Copy Markdown
Member

@mpasternak mpasternak commented Apr 27, 2026

Podsumowanie

Praktyka #1 z lirantal/pypi-security-best-practices, rev 2 po review.

Pierwotnie PR dodawał pre-commit hook uv-lock-no-build jako enforcement (no-build = true globalnie nie szło). Po review z @mpasternak okazało się że workspace install jest do niczego nie potrzebny — można go usunąć całkowicie. Sprawdzone i potwierdzone:

  • bpp-manage.py script ([project.scripts]) — dead code, 0 wywołań w Makefile/Dockerfile/workflows.
  • testcontainers_bpp pytest plugin ([project.entry-points."pytest11"]) — jedyne load-bearing użycie. Można załadować przez -p w pytest.ini.
  • import bpp_iplweb — 0 wystąpień w src/.

Co się zmienia

  • pyproject.toml: usunięto [project.scripts] i [project.entry-points."pytest11"].
  • pytest.ini: dodano -p testcontainers_bpp.plugin na początku addopts (laduje plugin PRZED conftest.py — krytyczne dla plugin's pytest_load_initial_conftests hook który wstrzykuje DJANGO_BPP_DB_PORT itp. do os.environ przed Django settings load).
  • Makefile: --no-install-project w prepare-developer-machine-{macos,linux} i uv-sync.
  • .github/workflows/{tests,refresh-baseline}.yml: --no-install-project.
  • Dockerfile: już miał --no-install-project (no change).
  • Usunięto pre-commit hook uv-lock-no-build — failował na cssmin przy każdej zmianie pyproject.toml (false positive na pre-existing sdist-only deps).

Dlaczego globalne no-build = true nie poszło

Sprawdzone: 11 pre-existing third-party deps jest sdist-only:

Package Use case Czemu sdist-only
crispy-forms-foundation Foundation theme dla crispy-forms Maintainer nigdy nie publikował wheels (5 wersji od 2014)
cssmin django-compressor backend Stary projekt, last release 2013
django-autocomplete-light Admin widgety (heavy use) Maintainer sdist-only
django-columns Multi-column layout (1-2 użycia) Sole release 2015
django-static-sitemaps sitemap.xml generation Pure-python, sdist
django-tabular-permissions Permissions UI Maintainer sdist-only
langdetect Language detection przy imporcie Pure-python od 2015
pylatexenc LaTeX → text (transitive bibtexparser) Pre-release, sdist
pyoai OAI-PMH (MOAI dep) Już znany upstream issue
python-ldap LDAP auth (extra ldap) C deps na openldap-dev
wsgiutils Old WSGI utility (transitive) Abandonware od 2013

uv nie ma czystego "wheel-only with exceptions" trybu — albo no-build = true globalnie (blokuje te 11), albo nic.

Egzekwowanie wheel-only (po tym PR)

Polegamy na:

  1. PR reviewPULL_REQUEST_TEMPLATE.md (PR docs(security): proces 'Adding a new dependency' + PR template #183) ma checkbox "Jeśli ten PR dodaje nową zależność".
  2. Trivy CVE scan w docker-bake build (Faza 2 build-docker-images.yml).
  3. uv-secure CVE scan w dependency-audit.yml workflow (PR ci(security): workflow skanowania CVE w uv.lock + bump jaraco.context #180).

11 sdist-only exceptions udokumentowane w komentarzu [tool.uv] w pyproject.toml + planowany follow-up dla wymiany na wheel-publishing alternatywy (gdzie istnieją: cssminrcssmin, langdetectlingua-language-detector).

Plan testowy

  • uv sync --frozen --no-install-project --all-extras → ok (330 packages installed).
  • pytest --help zawiera --no-testcontainers → plugin ładuje się via -p.
  • pytest src/pbn_integrator/tests/test_helpers.py::TestPerformanceCharacteristics → 2 passed.
  • uv run pre-commit run --files <changed> → green.
  • Po mergeu — pełny CI (tests.yml) musi przejść.

🤖 Generated with Claude Code

Praktyka #1 z lirantal/pypi-security-best-practices (binary-only installs).

Sdist (source distribution) wykonuje setup.py podczas `uv sync` -
to klasyczny wektor supply-chain attack: zlosliwy maintainer wpycha
arbitralny kod do publishowanego pakietu, ktory wykonuje sie u kazdego
co robi `pip install` / `uv sync`. Wheels (skompilowane binarne)
nie wykonuja kodu przy instalacji.

Globalnego `no-build = true` w [tool.uv] NIE da sie ustawic, bo blokuje
editable install workspace roota (bpp-iplweb sam jest sdist-ish dla uv).
Zamiast tego:

1. Komentarz w [tool.uv] dokumentuje polityke + uzasadnienie braku
   globalnego no-build.
2. Pre-commit hook `uv-lock-no-build` uruchamia
   `uv lock --check --no-build` przy zmianach pyproject.toml lub uv.lock -
   failuje jesli ktoras dep wymaga build z source.

Aktualnie wszystkie 330 zewnetrznych deps maja wheels - hook passes.
Gdy nowa dep nie ma wheel, dev dostaje jasny sygnal: znajdz alternatywe,
lub zglos wheel u maintainera.
Praktyka #1 z lirantal/pypi-security-best-practices, rev 2 po review.

Workspace install (bpp-iplweb editable) nie byl do niczego potrzebny:
- bpp-manage.py script: dead code (Makefile uzywa `python src/manage.py`)
- pytest11 entry point: jedyne load-bearing uzycie - przeniesione do
  pytest.ini addopts jako `-p testcontainers_bpp.plugin`
- import bpp_iplweb: 0 wystapien w src/

Zmiany:
- pyproject.toml: usunieto [project.scripts] + [project.entry-points]
- pytest.ini: dodano `-p testcontainers_bpp.plugin` na poczatku addopts
  (laduje plugin PRZED conftest.py - krytyczne, plugin musi wstrzyknac
  DJANGO_BPP_DB_PORT itp do os.environ przed Django settings load)
- Makefile: --no-install-project w prepare-developer-machine-{macos,linux}
  i uv-sync target
- .github/workflows/tests.yml + refresh-baseline.yml: --no-install-project
- Dockerfile: juz mial --no-install-project (no change)

Globalne `no-build = true` w [tool.uv] zostalo SPRAWDZONE i okazalo sie
nieosiagalne - 11 pre-existing third-party deps jest sdist-only:
crispy-forms-foundation, cssmin, django-autocomplete-light, django-columns,
django-static-sitemaps, django-tabular-permissions, langdetect, pylatexenc,
pyoai, python-ldap, wsgiutils.

uv nie ma czystego "wheel-only with exceptions" trybu (tylko all-or-none
+ per-package no-build, ktore jest blacklist nie whitelist). Usunieto
dlatego pre-commit hook `uv-lock-no-build` ktory failowal na cssmin
przy KAZDEJ zmianie pyproject.toml (false positive).

Polityka wheel-only egzekwowana teraz przez:
1. PR review (PULL_REQUEST_TEMPLATE.md ma checkbox dla nowych dep)
2. Trivy CVE scan w docker-bake
3. uv-secure CVE scan w dependency-audit.yml workflow

Smoke test:
- `uv sync --frozen --no-install-project --all-extras` -> ok
- `pytest --help` zawiera `--no-testcontainers` -> plugin ladowany
- `pytest src/pbn_integrator/tests/test_helpers.py` -> 2 passed
@mpasternak mpasternak changed the title deps(uv): wheel-only policy + pre-commit gate deps(uv): wywal workspace install + udokumentuj 11 sdist-only exceptions Apr 27, 2026
@mpasternak mpasternak merged commit 09a56a0 into dev Apr 27, 2026
10 of 11 checks passed
@mpasternak mpasternak deleted the security/uv-binary-only branch April 28, 2026 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant