requirements.txt used >= floors and installed with no hashes, so every CI run and install re-resolved to whatever PyPI served. A poisoned release of any dep (fastapi, aiohttp, lxml, pillow...) would land unverified. - requirements.lock: 42 pkgs pinned to exact versions + SHA256 (1258 hashes), uv (targeted py3.11 to match CI image) - Makefile install + CI: pip install --require-hashes -r requirements.lock - requirements.txt stays the loose source; make pins-lock regenerates Validated: lock installs under --require-hashes, 460 tests pass under resolved versions.
29 lines
674 B
YAML
29 lines
674 B
YAML
stages:
|
|
- test
|
|
|
|
variables:
|
|
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
|
|
|
cache:
|
|
paths:
|
|
- .cache/pip
|
|
- .venv/
|
|
|
|
test:
|
|
stage: test
|
|
tags:
|
|
- build
|
|
image: python:3.11
|
|
before_script:
|
|
- python3 -m venv .venv
|
|
- source .venv/bin/activate
|
|
- pip install --upgrade pip
|
|
# Supply-chain: hash-verified, pinned deps (see requirements.lock / make pins-lock)
|
|
- pip install --require-hashes -r requirements.lock
|
|
- pip install pytest pytest-asyncio httpx
|
|
script:
|
|
- source .venv/bin/activate
|
|
- python3 -m pytest tests/ -v --tb=short
|
|
rules:
|
|
- if: $CI_PIPELINE_SOURCE == "push"
|
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|