@@ -24,23 +24,17 @@ jobs:
2424 uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
2525
2626 - name : Set up Python
27- uses : actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 (full SHA)
27+ uses : actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6
2828 with :
2929 python-version : " 3.12"
3030
31- # Tools only, via pipx (keeps Scorecard happy )
32- - name : Install pipx + tools (pinned )
31+ # Build/test tools from HASHED lock (no raw pip installs )
32+ - name : Install build tools (hashed )
3333 run : |
34- set -euxo pipefail
35- sudo apt-get update
36- sudo apt-get install -y pipx
37- pipx ensurepath
38- echo "$HOME/.local/bin" >> "$GITHUB_PATH"
39- pipx install build==1.2.2
40- pipx install pytest==8.3.3
34+ python -m pip install --require-hashes -r .github/requirements-build.lock
4135
4236 - name : Build wheel
43- run : pyproject- build -o dist
37+ run : python -m build -o dist
4438
4539 - name : Inspect wheel has package files
4640 run : |
@@ -51,47 +45,28 @@ jobs:
5145 with zipfile.ZipFile(whl) as z:
5246 names = [n for n in z.namelist() if n.startswith("decision_security/")]
5347 print("Files in package:", len(names))
54- assert len( names) > 0 , "Wheel missing decision_security/*"
48+ assert names, "Wheel missing decision_security/*"
5549 PY
5650
57- - name : Minimal fuzzer (time-boxed 60s)
51+ # Install runtime deps from HASHED lock, then install the local wheel WITH its hash
52+ - name : Install runtime deps (hashed) + local wheel (hashed)
5853 run : |
59- # install your wheel so imports work (pulls numpy/scipy etc. as deps)
60- python -m pip install -U pip
61- python -m pip install dist/*.whl
62- # run the fuzzer if present (non-blocking or blocking: pick ONE line)
63- if [ -f tools/fuzz_synth.py ]; then
64- python tools/fuzz_synth.py --iterations 600 --timeout-sec 60
65- # If you prefer advisory-only while implementing, use:
66- # python tools/fuzz_synth.py --iterations 600 --timeout-sec 60 || true
67- else
68- echo "No tools/fuzz_synth.py; skipping fuzz."
69- fi
70-
71- - name : Install runtime deps (if lock present)
72- run : |
73- if [ -f requirements-runtime.lock ]; then
74- python -m pip install --require-hashes -r requirements-runtime.lock
75- else
76- echo "No requirements-runtime.lock; skipping runtime deps install."
77- fi
78-
79- # Install pytest and your wheel into the runner's Python (only if tests exist)
80- - name : Install test runner + wheel (if tests present)
81- if : ${{ hashFiles('tests/test_*.py', 'tests/**/test_*.py', 'tests/*_test.py', 'tests/**/*_test.py') != '' }}
82- run : |
83- python -m pip install -U pip
84- python -m pip install pytest==8.3.3
85- python -m pip install dist/*.whl
86- # sanity: ensure deps are visible to this Python
87- python - <<'PY'
88- import importlib.util
89- for m in ["numpy","scipy","pandas","matplotlib","decision_security"]:
90- assert importlib.util.find_spec(m), f"Missing after install: {m}"
91- print("Runtime deps OK")
54+ python -m pip install --require-hashes -r requirements-runtime.lock
55+ WHEEL=$(ls dist/*.whl)
56+ HASH=$(python - <<'PY'
57+ import glob, hashlib
58+ p = glob.glob("dist/*.whl")[0]
59+ print(hashlib.sha256(open(p,"rb").read()).hexdigest())
9260 PY
61+ )
62+ printf "%s --hash=sha256:%s\n" "$WHEEL" "$HASH" > wheel.requirements.txt
63+ python -m pip install --require-hashes --no-deps -r wheel.requirements.txt
64+
65+ # Minimal fuzzer (fails CI on real invariant failures). Add 'continue-on-error: true' if you want advisory-only.
66+ - name : Minimal fuzzer (60s)
67+ run : python tools/fuzz_synth.py --iterations 600 --timeout-sec 60 --seed 123
9368
94- # Run pytest only if tests exist; treat "no tests" exit code (5) as success
69+ # Run pytest only if tests exist; tools already installed from build lock
9570 - name : Run tests (pytest if present)
9671 if : ${{ hashFiles('tests/test_*.py', 'tests/**/test_*.py', 'tests/*_test.py', 'tests/**/*_test.py') != '' }}
9772 run : |
0 commit comments