Files
OBLITERATUS/.github/workflows/ci.yml
T

286 lines
9.9 KiB
YAML

name: CI
on:
pull_request:
push:
branches:
- main
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
PIP_DISABLE_PIP_VERSION_CHECK: "1"
PIP_NO_INPUT: "1"
jobs:
package:
name: Package
runs-on: ubuntu-latest
timeout-minutes: 15
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
requirements*.txt
- name: Install build tooling
run: python -m pip install "build==1.2.2.post1" "twine==7.0.0"
- name: Build source and wheel distributions
run: python -m build --sdist --wheel
- name: Verify wheel contents and entry point
run: |
python - <<'PY'
from pathlib import Path
from zipfile import ZipFile
wheels = list(Path("dist").glob("*.whl"))
if len(wheels) != 1:
raise SystemExit(f"expected one wheel, found: {wheels}")
with ZipFile(wheels[0]) as archive:
names = set(archive.namelist())
required = {
"app.py",
"obliteratus/__init__.py",
"obliteratus/local_ui.py",
}
missing = sorted(required - names)
if missing:
raise SystemExit(f"wheel is missing required modules: {missing}")
entry_points = [
name for name in names if name.endswith(".dist-info/entry_points.txt")
]
if len(entry_points) != 1:
raise SystemExit(f"expected one entry_points.txt, found: {entry_points}")
contents = archive.read(entry_points[0]).decode("utf-8")
if "obliteratus = obliteratus.cli:main" not in contents:
raise SystemExit("wheel is missing the obliteratus console entry point")
print(f"verified wheel contents: {wheels[0]}")
PY
- name: Validate distribution metadata
run: |
mkdir -p package-evidence
python -m twine check dist/* | tee package-evidence/twine-check.txt
sha256sum dist/* | tee package-evidence/SHA256SUMS
- name: Verify installed wheel contract
run: |
mapfile -t wheels < <(find "$GITHUB_WORKSPACE/dist" -maxdepth 1 -type f -name '*.whl' -print)
if [ "${#wheels[@]}" -ne 1 ]; then
echo "expected exactly one wheel, found ${#wheels[@]}"
exit 1
fi
wheel_env="$RUNNER_TEMP/obliteratus-wheel-env"
wheel_cwd="$RUNNER_TEMP/obliteratus-wheel-cwd"
python -m venv "$wheel_env"
mkdir -p "$wheel_cwd"
"$wheel_env/bin/python" -m pip install --no-cache-dir "rich==15.0.0"
"$wheel_env/bin/python" -m pip install --no-cache-dir --no-deps "${wheels[0]}"
cd "$wheel_cwd"
"$wheel_env/bin/python" -I - <<'PY' | tee "$GITHUB_WORKSPACE/package-evidence/wheel-import.txt"
import importlib.metadata
from pathlib import Path
import obliteratus
origin = Path(obliteratus.__file__).resolve()
assert "site-packages" in origin.parts, origin
assert obliteratus.__version__ == importlib.metadata.version("obliteratus")
print(f"installed wheel import: {origin}")
print(f"version: {obliteratus.__version__}")
PY
"$wheel_env/bin/python" -I -m obliteratus --help > "$GITHUB_WORKSPACE/package-evidence/wheel-module-help.txt"
"$wheel_env/bin/obliteratus" --help > "$GITHUB_WORKSPACE/package-evidence/wheel-console-help.txt"
- name: Verify installed sdist contract
run: |
mapfile -t sdists < <(find "$GITHUB_WORKSPACE/dist" -maxdepth 1 -type f -name '*.tar.gz' -print)
if [ "${#sdists[@]}" -ne 1 ]; then
echo "expected exactly one sdist, found ${#sdists[@]}"
exit 1
fi
sdist_env="$RUNNER_TEMP/obliteratus-sdist-env"
sdist_cwd="$RUNNER_TEMP/obliteratus-sdist-cwd"
python -m venv "$sdist_env"
mkdir -p "$sdist_cwd"
"$sdist_env/bin/python" -m pip install --no-cache-dir "rich==15.0.0"
"$sdist_env/bin/python" -m pip install --no-cache-dir --no-deps "${sdists[0]}"
cd "$sdist_cwd"
"$sdist_env/bin/python" -I - <<'PY' | tee "$GITHUB_WORKSPACE/package-evidence/sdist-import.txt"
import importlib.metadata
from pathlib import Path
import obliteratus
origin = Path(obliteratus.__file__).resolve()
assert "site-packages" in origin.parts, origin
assert obliteratus.__version__ == importlib.metadata.version("obliteratus")
print(f"installed sdist import: {origin}")
print(f"version: {obliteratus.__version__}")
PY
"$sdist_env/bin/python" -I -m obliteratus --help > "$GITHUB_WORKSPACE/package-evidence/sdist-module-help.txt"
"$sdist_env/bin/obliteratus" --help > "$GITHUB_WORKSPACE/package-evidence/sdist-console-help.txt"
- name: Upload distributions and package evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: distributions-py3.12
path: |
dist/
package-evidence/
if-no-files-found: error
retention-days: 14
lint:
name: Ruff
runs-on: ubuntu-latest
timeout-minutes: 15
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
- name: Install Ruff
run: python -m pip install "ruff==0.8.6"
- name: Install actionlint with checksum verification
env:
ACTIONLINT_VERSION: "1.7.12"
ACTIONLINT_SHA256: "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8"
run: |
archive="$RUNNER_TEMP/actionlint.tar.gz"
curl -fsSLo "$archive" \
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
echo "${ACTIONLINT_SHA256} ${archive}" | sha256sum -c -
tar -xzf "$archive" -C "$RUNNER_TEMP" actionlint
- name: Validate GitHub Actions workflows
run: |
"$RUNNER_TEMP/actionlint" -no-color
- name: Enforce Ruff F gate
run: >-
python -m ruff check --select F obliteratus tests
scripts/check_coverage_thresholds.py
scripts/gemma4_12b_recursive_loop.py
- name: Report E501 legacy baseline
if: always()
run: >-
python -m ruff check --select E501 --statistics obliteratus tests
scripts/check_coverage_thresholds.py
scripts/gemma4_12b_recursive_loop.py || true
test:
name: Tests py${{ matrix.python-version }}
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
env:
CUDA_VISIBLE_DEVICES: ""
HF_DATASETS_OFFLINE: "1"
HF_HUB_DISABLE_TELEMETRY: "1"
HF_HUB_OFFLINE: "1"
TOKENIZERS_PARALLELISM: "false"
TRANSFORMERS_OFFLINE: "1"
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: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: |
pyproject.toml
requirements*.txt
- 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
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
- name: Smoke import and CLI
run: |
python - <<'PY'
import obliteratus
version = getattr(obliteratus, "__version__", None)
if version is not None:
print(f"obliteratus version: {version}")
else:
print("obliteratus import: ok")
PY
python -m obliteratus --help
- name: Run tests with coverage
run: |
mkdir -p test-results
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 \
--junitxml="test-results/junit-py${{ matrix.python-version }}.xml" \
--cov-report="xml:test-results/coverage-py${{ matrix.python-version }}.xml" \
--cov-report="json:test-results/coverage-py${{ matrix.python-version }}.json"
- name: Enforce line and branch coverage floors
run: >-
python scripts/check_coverage_thresholds.py
"test-results/coverage-py${{ matrix.python-version }}.json"
--min-line 49
--min-branch 36
- name: Upload test and coverage evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: test-evidence-py${{ matrix.python-version }}
path: test-results/
if-no-files-found: error
retention-days: 14