mirror of
https://github.com/elder-plinius/OBLITERATUS.git
synced 2026-08-17 16:37:30 +02:00
ci: add reproducible supply-chain gates
This commit is contained in:
+165
-22
@@ -16,12 +16,15 @@ concurrency:
|
||||
env:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
||||
PIP_NO_INPUT: "1"
|
||||
UV_VERSION: "0.12.4"
|
||||
|
||||
jobs:
|
||||
package:
|
||||
name: Package
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
BUILD_TOOLS: /tmp/obliteratus-ci-tools
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
@@ -34,13 +37,16 @@ jobs:
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
requirements*.txt
|
||||
uv.lock
|
||||
|
||||
- name: Install build tooling
|
||||
run: python -m pip install "build==1.2.2.post1" "twine==7.0.0"
|
||||
run: |
|
||||
python -m pip install "uv==${UV_VERSION}"
|
||||
UV_PROJECT_ENVIRONMENT="$BUILD_TOOLS" uv sync --locked --only-group ci
|
||||
|
||||
- name: Build source and wheel distributions
|
||||
run: python -m build --sdist --wheel
|
||||
run: >-
|
||||
"$BUILD_TOOLS/bin/python" -m build --sdist --wheel
|
||||
|
||||
- name: Verify wheel contents and entry point
|
||||
run: |
|
||||
@@ -78,7 +84,7 @@ jobs:
|
||||
- name: Validate distribution metadata
|
||||
run: |
|
||||
mkdir -p package-evidence
|
||||
python -m twine check dist/* | tee package-evidence/twine-check.txt
|
||||
"$BUILD_TOOLS/bin/python" -m twine check dist/* | tee package-evidence/twine-check.txt
|
||||
sha256sum dist/* | tee package-evidence/SHA256SUMS
|
||||
|
||||
- name: Verify installed wheel contract
|
||||
@@ -168,10 +174,12 @@ jobs:
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: pip
|
||||
cache-dependency-path: pyproject.toml
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
|
||||
- name: Install Ruff
|
||||
run: python -m pip install "ruff==0.8.6"
|
||||
run: python -m pip install "ruff==0.16.2"
|
||||
|
||||
- name: Install actionlint with checksum verification
|
||||
env:
|
||||
@@ -190,15 +198,17 @@ jobs:
|
||||
|
||||
- name: Enforce Ruff F gate
|
||||
run: >-
|
||||
python -m ruff check --select F obliteratus tests
|
||||
python -m ruff check --select F app.py obliteratus tests
|
||||
scripts/check_coverage_thresholds.py
|
||||
scripts/check_supply_chain_policy.py
|
||||
scripts/gemma4_12b_recursive_loop.py
|
||||
|
||||
- name: Report E501 legacy baseline
|
||||
if: always()
|
||||
run: >-
|
||||
python -m ruff check --select E501 --statistics obliteratus tests
|
||||
python -m ruff check --select E501 --statistics app.py obliteratus tests
|
||||
scripts/check_coverage_thresholds.py
|
||||
scripts/check_supply_chain_policy.py
|
||||
scripts/gemma4_12b_recursive_loop.py || true
|
||||
|
||||
test:
|
||||
@@ -219,6 +229,7 @@ jobs:
|
||||
HF_HUB_OFFLINE: "1"
|
||||
TOKENIZERS_PARALLELISM: "false"
|
||||
TRANSFORMERS_OFFLINE: "1"
|
||||
TEST_ENV: /tmp/obliteratus-test-env
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
@@ -231,22 +242,17 @@ jobs:
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
requirements*.txt
|
||||
uv.lock
|
||||
|
||||
- name: Install CPU PyTorch
|
||||
run: python -m pip install --index-url https://download.pytorch.org/whl/cpu "torch>=2.0"
|
||||
|
||||
- name: Install package and test tools
|
||||
- name: Install locked package and test tools
|
||||
run: |
|
||||
python - <<'PY' > /tmp/torch-cpu-constraint.txt
|
||||
import torch
|
||||
print(f"torch=={torch.__version__}")
|
||||
PY
|
||||
python -m pip install -e ".[dev]" -c /tmp/torch-cpu-constraint.txt
|
||||
python -m pip install "uv==${UV_VERSION}"
|
||||
UV_PROJECT_ENVIRONMENT="$TEST_ENV" \
|
||||
uv sync --locked --no-default-groups --extra dev --no-editable
|
||||
|
||||
- name: Smoke import and CLI
|
||||
run: |
|
||||
python - <<'PY'
|
||||
"$TEST_ENV/bin/python" - <<'PY'
|
||||
import obliteratus
|
||||
|
||||
version = getattr(obliteratus, "__version__", None)
|
||||
@@ -255,12 +261,12 @@ jobs:
|
||||
else:
|
||||
print("obliteratus import: ok")
|
||||
PY
|
||||
python -m obliteratus --help
|
||||
"$TEST_ENV/bin/python" -m obliteratus --help
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: |
|
||||
mkdir -p test-results
|
||||
python -m pytest \
|
||||
"$TEST_ENV/bin/python" -m pytest \
|
||||
-m "not slow and not gpu and not mps and not mlx and not network and not download and not remote" \
|
||||
--cov-branch \
|
||||
--cov-fail-under=0 \
|
||||
@@ -270,7 +276,7 @@ jobs:
|
||||
|
||||
- name: Enforce line and branch coverage floors
|
||||
run: >-
|
||||
python scripts/check_coverage_thresholds.py
|
||||
"$TEST_ENV/bin/python" scripts/check_coverage_thresholds.py
|
||||
"test-results/coverage-py${{ matrix.python-version }}.json"
|
||||
--min-line 49
|
||||
--min-branch 36
|
||||
@@ -283,3 +289,140 @@ jobs:
|
||||
path: test-results/
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
supply-chain:
|
||||
name: Supply chain
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
EVIDENCE: /tmp/supply-chain-evidence
|
||||
GITLEAKS_SHA256: "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb"
|
||||
GITLEAKS_VERSION: "8.30.1"
|
||||
RUNTIME_ENV: /tmp/obliteratus-runtime
|
||||
SUPPLY_TOOLS: /tmp/obliteratus-supply-tools
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
|
||||
- name: Install locked supply-chain tooling
|
||||
run: |
|
||||
python -m pip install "uv==${UV_VERSION}"
|
||||
uv lock --check
|
||||
UV_PROJECT_ENVIRONMENT="$RUNTIME_ENV" \
|
||||
uv sync --locked --all-extras --no-default-groups --no-editable
|
||||
UV_PROJECT_ENVIRONMENT="$SUPPLY_TOOLS" \
|
||||
uv sync --locked --only-group ci
|
||||
mkdir -p "$EVIDENCE"
|
||||
cd "$RUNNER_TEMP"
|
||||
"$RUNTIME_ENV/bin/python" -I - <<'PY' | tee "$EVIDENCE/spaces-import.txt"
|
||||
import gradio
|
||||
import app
|
||||
|
||||
assert type(app.demo).__name__ == "Blocks"
|
||||
print(f"installed all-extras app import: {app.__file__}")
|
||||
print(f"gradio: {gradio.__version__}")
|
||||
PY
|
||||
|
||||
- name: Validate exception policy
|
||||
run: >-
|
||||
python scripts/check_supply_chain_policy.py policy
|
||||
--policy ci/supply-chain-policy.json
|
||||
|
||||
- name: Scan checkout for secrets with redacted evidence
|
||||
run: |
|
||||
archive="$RUNNER_TEMP/gitleaks.tar.gz"
|
||||
curl -fsSLo "$archive" \
|
||||
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
|
||||
echo "${GITLEAKS_SHA256} ${archive}" | sha256sum -c -
|
||||
tar -xzf "$archive" -C "$RUNNER_TEMP" gitleaks
|
||||
set +e
|
||||
"$RUNNER_TEMP/gitleaks" dir "$GITHUB_WORKSPACE" \
|
||||
--redact=100 \
|
||||
--report-format json \
|
||||
--report-path "$EVIDENCE/gitleaks.json" \
|
||||
--no-banner \
|
||||
--no-color
|
||||
status=$?
|
||||
set -e
|
||||
echo "$status" > "$EVIDENCE/gitleaks.status"
|
||||
|
||||
- name: Collect vulnerability evidence for supported Python versions
|
||||
run: |
|
||||
for version in 3.10 3.11 3.12; do
|
||||
set +e
|
||||
uv --preview-features audit-command,json-output audit \
|
||||
--locked \
|
||||
--python-version "$version" \
|
||||
--python-platform linux \
|
||||
--output-format json > "$EVIDENCE/uv-audit-py${version}.json"
|
||||
status=$?
|
||||
set -e
|
||||
echo "$status" > "$EVIDENCE/uv-audit-py${version}.status"
|
||||
done
|
||||
|
||||
- name: Build wheel and bind CycloneDX SBOM
|
||||
run: |
|
||||
mkdir -p "$EVIDENCE/dist"
|
||||
"$SUPPLY_TOOLS/bin/python" -m build --wheel --outdir "$EVIDENCE/dist"
|
||||
uv --preview-features sbom-export export \
|
||||
--locked \
|
||||
--format cyclonedx1.5 \
|
||||
--all-extras \
|
||||
--no-dev \
|
||||
--no-editable \
|
||||
--output-file "$EVIDENCE/obliteratus.cdx.unbound.json"
|
||||
mapfile -t wheels < <(find "$EVIDENCE/dist" -maxdepth 1 -type f -name '*.whl' -print)
|
||||
if [ "${#wheels[@]}" -ne 1 ]; then
|
||||
echo "expected exactly one wheel, found ${#wheels[@]}"
|
||||
exit 1
|
||||
fi
|
||||
python scripts/check_supply_chain_policy.py sbom \
|
||||
--input "$EVIDENCE/obliteratus.cdx.unbound.json" \
|
||||
--wheel "${wheels[0]}" \
|
||||
--output "$EVIDENCE/obliteratus.cdx.json"
|
||||
sha256sum "${wheels[0]}" > "$EVIDENCE/distribution.SHA256SUM"
|
||||
|
||||
- name: Collect packaged-dependency license inventory
|
||||
run: >-
|
||||
"$SUPPLY_TOOLS/bin/pip-licenses"
|
||||
--python "$RUNTIME_ENV/bin/python"
|
||||
--format json
|
||||
--output-file "$EVIDENCE/licenses.json"
|
||||
|
||||
- name: Enforce vulnerability, secret, and license policies
|
||||
run: |
|
||||
for version in 3.10 3.11 3.12; do
|
||||
python scripts/check_supply_chain_policy.py audit \
|
||||
--policy ci/supply-chain-policy.json \
|
||||
--evidence "$EVIDENCE/uv-audit-py${version}.json" \
|
||||
--scanner-status "$EVIDENCE/uv-audit-py${version}.status" \
|
||||
--decision "$EVIDENCE/uv-audit-py${version}.decision.json"
|
||||
done
|
||||
python scripts/check_supply_chain_policy.py secrets \
|
||||
--policy ci/supply-chain-policy.json \
|
||||
--evidence "$EVIDENCE/gitleaks.json" \
|
||||
--scanner-status "$EVIDENCE/gitleaks.status" \
|
||||
--decision "$EVIDENCE/gitleaks.decision.json"
|
||||
python scripts/check_supply_chain_policy.py licenses \
|
||||
--policy ci/supply-chain-policy.json \
|
||||
--evidence "$EVIDENCE/licenses.json" \
|
||||
--decision "$EVIDENCE/licenses.decision.json"
|
||||
|
||||
- name: Upload supply-chain evidence
|
||||
if: always()
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: supply-chain-evidence-py3.12
|
||||
path: ${{ runner.temp }}/supply-chain-evidence/
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
Reference in New Issue
Block a user