Skip to content

Commit 92e22f1

Browse files
authored
Update ci.yml (#6)
* Update ci.yml * Update release.yml * Update ci.yml * Update ci.yml * Update ci.yml * Update ci.yml * Update ci.yml
1 parent 9590074 commit 92e22f1

2 files changed

Lines changed: 72 additions & 46 deletions

File tree

.github/workflows/ci.yml

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
name: CI (build & import)
22

33
on:
4-
workflow_dispatch:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
workflow_dispatch: {}
59

6-
# Least-privilege token by default
710
permissions:
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"

.github/workflows/release.yml

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,67 +5,63 @@ on:
55
tags: [ 'v*.*.*' ]
66
workflow_dispatch: {}
77

8-
# Least-privilege by default
98
permissions:
109
contents: read
1110

1211
jobs:
13-
build:
12+
build-publish:
1413
runs-on: ubuntu-latest
1514
permissions:
16-
contents: read
17-
15+
contents: write # create/upload GitHub Release assets
16+
id-token: write # OIDC for PyPI + Sigstore
1817
steps:
19-
- name: Harden runner
20-
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
21-
2218
- name: Checkout
2319
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
2420

2521
- name: Set up Python
26-
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6
22+
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7 # v6
2723
with:
2824
python-version: "3.12"
2925

30-
# Use pipx (pinned) to avoid raw pip installs in workflows
31-
- name: Install pipx + build (pinned)
26+
# No raw pip: use pipx with pinned tools (keeps 'Pinned-Dependencies' happy)
27+
- name: Install pipx + tools (pinned)
3228
run: |
3329
set -euxo pipefail
3430
sudo apt-get update
3531
sudo apt-get install -y pipx
3632
pipx ensurepath
3733
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
3834
pipx install build==1.2.2
35+
pipx install twine==5.1.1
3936
4037
- name: Build distributions
4138
run: |
4239
pyproject-build -o dist
40+
twine check dist/*
4341
44-
- name: Upload build artifact
45-
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
46-
with:
47-
name: dist
48-
path: dist/*
49-
50-
publish-pypi:
51-
if: startsWith(github.ref, 'refs/tags/')
52-
needs: build
53-
runs-on: ubuntu-latest
54-
permissions:
55-
contents: read
56-
id-token: write # OIDC for PyPI
57-
58-
steps:
59-
- name: Harden runner
60-
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
61-
62-
- name: Download build artifact
63-
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
42+
- name: Create GitHub Release (upload artifacts)
43+
uses: softprops/action-gh-release@62c96d0c4e8a889135c1f3a25910db8dbe0e85f7 # v2.3.4
6444
with:
65-
name: dist
66-
path: dist
45+
files: |
46+
dist/*.tar.gz
47+
dist/*.whl
48+
env:
49+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6750

6851
- name: Publish to PyPI (OIDC)
52+
if: startsWith(github.ref, 'refs/tags/')
6953
uses: pypa/gh-action-pypi-publish@f8d218034565c4b29629e190f46f5d54e3637bf4 # v1.12.2
7054
with:
7155
print-hash: true
56+
57+
sign-release:
58+
needs: build-publish
59+
runs-on: ubuntu-latest
60+
permissions:
61+
contents: write
62+
id-token: write # keyless Sigstore
63+
steps:
64+
- name: Sign & attach with Sigstore
65+
uses: sigstore/gh-action-sigstore-python@f7ad0af51a5648d09a20d00370f0a91c3bdf8f84 # v3.0.1
66+
with:
67+
release-signing-artifacts: true

0 commit comments

Comments
 (0)