11name : CI (build & import)
22
33on :
4- workflow_dispatch :
4+ push :
5+ branches : [ "main" ]
6+ pull_request :
7+ branches : [ "main" ]
8+ workflow_dispatch : {}
59
6- # Least-privilege token by default
710permissions :
811 contents : read
912
@@ -21,24 +24,23 @@ jobs:
2124 uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
2225
2326 - name : Set up Python
24- uses : actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6
27+ uses : actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 (full SHA)
2528 with :
2629 python-version : " 3.12"
2730
28- # Use pipx to avoid un-hashed pip installs in workflows
29- - name : Install pipx + build tool (pinned)
31+ # Tools only, via pipx (keeps Scorecard happy)
32+ - name : Install pipx + tools (pinned)
3033 run : |
3134 set -euxo pipefail
3235 sudo apt-get update
3336 sudo apt-get install -y pipx
3437 pipx ensurepath
3538 echo "$HOME/.local/bin" >> "$GITHUB_PATH"
36- # build provides the "pyproject-build" console script
3739 pipx install build==1.2.2
40+ pipx install pytest==8.3.3
3841
3942 - name : Build wheel
40- run : |
41- pyproject-build -o dist
43+ run : pyproject-build -o dist
4244
4345 - name : Inspect wheel has package files
4446 run : |
@@ -52,12 +54,40 @@ jobs:
5254 assert len(names) > 0, "Wheel missing decision_security/*"
5355 PY
5456
55- - name : Import smoke from wheel (no install)
57+ # OPTIONAL: if you later add a hash-locked runtime deps file, CI will install it securely.
58+ # This line uses --require-hashes, so Scorecard will NOT flag it.
59+ - name : Install runtime deps (if lock present)
60+ run : |
61+ if [ -f requirements-runtime.lock ]; then
62+ python -m pip install --require-hashes -r requirements-runtime.lock
63+ else
64+ echo "No requirements-runtime.lock; skipping runtime deps install."
65+ fi
66+
67+ # Install pytest and your wheel into the runner's Python (only if tests exist)
68+ - name : Install test runner + wheel (if tests present)
69+ if : ${{ hashFiles('tests/test_*.py', 'tests/**/test_*.py', 'tests/*_test.py', 'tests/**/*_test.py') != '' }}
5670 run : |
71+ python -m pip install -U pip
72+ python -m pip install pytest==8.3.3
73+ python -m pip install dist/*.whl
74+ # sanity: ensure deps are visible to this Python
5775 python - <<'PY'
58- import glob, sys
59- whl = glob.glob("dist/*.whl")[0]
60- sys.path.insert(0, whl) # allow import from wheel zip
61- from decision_security.synth import sample
62- print("Smoke OK:", sample("poisson", 5, lam=1.0))
76+ import importlib.util
77+ for m in ["numpy","scipy","pandas","matplotlib","decision_security"]:
78+ assert importlib.util.find_spec(m), f"Missing after install: {m}"
79+ print("Runtime deps OK")
6380 PY
81+
82+ # Run pytest only if tests exist; treat "no tests" exit code (5) as success
83+ - name : Run tests (pytest if present)
84+ if : ${{ hashFiles('tests/test_*.py', 'tests/**/test_*.py', 'tests/*_test.py', 'tests/**/*_test.py') != '' }}
85+ run : |
86+ set +e
87+ python -m pytest -q
88+ code=$?
89+ if [ "$code" = "5" ]; then
90+ echo "Pytest: no tests collected. Skipping."
91+ exit 0
92+ fi
93+ exit "$code"
0 commit comments