Five review findings of the P2 phase, each fixed at its root: 1. (medium) The P2.6 guard could not see an undeclared third-party import: the closure's imports were filtered through a hard-coded 10-name map, so every module outside it was dropped silently (a module-level `import av` in a copy of the repo still gave "1 passed"). The map is now a *rename* map (cv2 -> opencv-python, PIL -> Pillow, yaml -> pyyaml); every other module is mapped to its own name, so an unknown module shows up as an undeclared dependency. The guard is split by import time: every third-party module imported at import time must be a declared distribution, every lazy (function-level) one must be allowlisted with a reason (dlib, gdown, mc, wandb - all unreachable from the node). 2. (low) The P2.1 (c) progression test was vacuous: it returned before its assertions and probed a second, top-level copy of the vendored tree (`sys.path.insert(modules/deps)`). It now imports the packaged architecture, asserts that FeedForward / AdaLayerNorm come from the vendored _diffusers_compat and that no top-level `basicsr` shadows an installed one. 3. (low) Two swallow-and-stub fallbacks remained in the vendored tree (facelib/detection, facelib/parsing - their stubs called an unimported `urlparse` and would have raised NameError). Both now import the vendored symbol directly; a guard forbids a fallback stub in the vendored tree. 4. (low) `basicsr/utils/file_client.py` still appended to `sys.path` (the optional `sys_path` of MemcachedBackend), which the plan's §3 rule forbids anywhere in the package. The mutation and the parameter are gone and guard (d) now covers the whole package (the vendored tree included). 5. (low) The unreachable body of `KEEPFaceProcessor.process_video` still called the deleted VideoReader / VideoWriter. The 141 dead lines are removed; an AST guard keeps the references out. Found while fixing the findings: the CI job did not install `requests`, which the vendored `basicsr/utils/download_util.py` imports at module level (P2.6 added it to requirements.txt but not to the workflow) - a clean CI runner died with "No module named 'requests'". The install list is now completed and a test derives it from requirements.txt. Gate: pytest -m "unit or mock_integration" -> 109 passed, 1 skipped, 4 xfailed; plan's local gate (+ headless) -> 109 passed, 3 skipped, 4 xfailed; tools/scan_compat.py -> finding_count 0 (exit 0); ruff check . -> All checks passed. A mutation check re-introduces six defects into a copy of the repository: the matching guard fails in 6/6 cases.
90 lines
3.1 KiB
YAML
90 lines
3.1 KiB
YAML
name: tests
|
|
|
|
on:
|
|
push:
|
|
branches: [master, main, feat/v3-modernization]
|
|
pull_request:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# P1.5 - lint gate. ruff is pinned to a major version: an unpinned ruff
|
|
# drifts the pip cache and can turn a green branch red without a code change.
|
|
lint:
|
|
name: Lint (ruff)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Install ruff (pinned major)
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
python -m pip install "ruff==0.8.*"
|
|
|
|
- name: Lint
|
|
run: python -m ruff check .
|
|
|
|
# P1.5 - the test tiers of the modernization plan (section 4):
|
|
# unit | mock_integration | headless
|
|
# The headless tier needs a real ComfyUI checkout; COMFYUI_ROOT is empty
|
|
# here, so those tests skip themselves instead of failing.
|
|
test:
|
|
name: Test (python ${{ matrix.python-version }})
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest]
|
|
python-version: ["3.10", "3.12", "3.13"]
|
|
runs-on: ${{ matrix.os }}
|
|
env:
|
|
COMFYUI_ROOT: ""
|
|
steps:
|
|
- name: Check out code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python ${{ matrix.python-version }}
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ matrix.python-version }}
|
|
|
|
- name: Cache pip (CPU torch wheel)
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/pip
|
|
key: pip-cpu-torch-${{ runner.os }}-${{ matrix.python-version }}-v1
|
|
restore-keys: |
|
|
pip-cpu-torch-${{ runner.os }}-${{ matrix.python-version }}-
|
|
|
|
- name: Install CPU-only torch and the test dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
# CPU wheels are ~200 MB instead of ~2.5 GB of CUDA.
|
|
# torchvision is a runtime dependency of the package
|
|
# (modules/keep_processor.py imports it).
|
|
python -m pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
|
|
# numpy 2.4 has no 3.10 wheel -> pin <2.3 on the 3.10 job.
|
|
# tomli backs tomllib on python 3.10.
|
|
if [ "${{ matrix.python-version }}" = "3.10" ]; then
|
|
python -m pip install "numpy<2.3" tomli
|
|
else
|
|
python -m pip install numpy
|
|
fi
|
|
# PyYAML: the vendored tree imports it eagerly
|
|
# (modules/deps/basicsr/utils/options.py:5 -> basicsr/utils/__init__.py:8),
|
|
# so the unit tier fails with "No module named 'yaml'" without it.
|
|
# requests: the vendored download utility imports it eagerly
|
|
# (modules/deps/basicsr/utils/download_util.py:3 -> modules/utils.py:19),
|
|
# so the unit tier fails with "No module named 'requests'" without it.
|
|
python -m pip install opencv-python-headless einops scipy Pillow tqdm pytest pyyaml requests
|
|
|
|
- name: Run the unit, mock_integration and headless tiers
|
|
run: python -m pytest -q -m "unit or mock_integration or headless"
|