diff --git a/.github/workflows/import-smoke-on-ubuntu-py3-12.yml b/.github/workflows/import-smoke-on-ubuntu-py3-12.yml deleted file mode 100644 index 35427cc..0000000 --- a/.github/workflows/import-smoke-on-ubuntu-py3-12.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: import-smoke - -# Catches "wheel installs but `import scitex_stats` blows up at runtime" -# — separate from the full pytest suite so a broken entry-point fails -# fast without paying for the matrix. Companion to `tests` — confirms -# the bare package (no extras) is `pip install -e .`-able and -# `import scitex_stats` succeeds. Catches `[project] dependencies` -# drift that the test matrix masks because it installs `[all,dev]`. - -on: - push: - branches: [main, develop] - pull_request: - branches: [main, develop] - schedule: - - cron: "0 7 * * *" # nightly 07:00 UTC - workflow_dispatch: - -jobs: - install-check: - name: import-smoke-on-ubuntu-py3-12 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Install (no extras) - run: | - python -m venv .venv - .venv/bin/pip install --upgrade pip - .venv/bin/pip install -e . - - name: Import smoke - run: .venv/bin/python -c "import scitex_stats; print(scitex_stats.__version__)" diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml new file mode 100644 index 0000000..8acb446 --- /dev/null +++ b/.github/workflows/pr-ci.yml @@ -0,0 +1,134 @@ +name: pr-ci + +# Consolidated PR-only CI gate. Runs the per-PR validation suite as a +# single workflow so the cancel-in-progress concurrency group, path +# filters, and uv cache apply uniformly. Post-merge validation lives +# in release-ci.yml. +# +# L1 concurrency — cancel superseded PR runs. +# L3 path filters — skip docs/skills/examples/markdown-only PRs. +# L4 conditional matrix — full ["3.11", "3.12", "3.13"] on PR (this trigger). +# L5a uv-managed Python (`uv python install` + `uv venv --python`) so the +# matrix leg is not bound to the runner's system Python. +# L5b .venv/bin on PATH (and explicit `.venv/bin/python` for clarity) so +# console scripts resolve without needing `uv run`. + +on: + pull_request: + branches: [main, develop] + paths-ignore: + - 'docs/**' + - '_skills/**' + - 'examples/**' + - '**.md' + - 'CHANGELOG.*' + - '.github/CODEOWNERS' + - '.github/ISSUE_TEMPLATE/**' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + import-smoke: + name: import-smoke-on-ubuntu-py3-12 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Set up Python 3.12 (uv-managed) + run: uv python install 3.12 + - name: Install (no extras) in uv venv + run: | + uv venv --python 3.12 .venv + uv pip install --python .venv/bin/python -e . + - name: Import smoke + run: .venv/bin/python -c "import scitex_stats; print(getattr(scitex_stats, '__version__', 'unversioned'))" + - name: smoke scitex-stats --help + run: .venv/bin/scitex-stats --help + dep-hygiene-smoke: + name: dep-hygiene-smoke + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Set up Python 3.11 (uv-managed) + run: uv python install 3.11 + - name: Bare install (no extras) in uv venv + run: | + uv venv --python 3.11 .venv + uv pip install --python .venv/bin/python . + - name: Import package + run: .venv/bin/python -c "import scitex_stats; print(scitex_stats.__name__)" + + tests: + name: pytest-matrix-on-ubuntu-py${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ${{ github.event_name == 'pull_request' && fromJson('["3.11", "3.12", "3.13"]') || fromJson('["3.12"]') }} + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Set up Python ${{ matrix.python-version }} (uv-managed) + run: uv python install ${{ matrix.python-version }} + - name: Create uv venv on this matrix Python + run: uv venv --python ${{ matrix.python-version }} .venv + - name: Install dependencies + # Fallback chain: prefer [all,dev] so optional-dep code paths + # get exercised. Falls back to [dev] then plain editable so a + # packaging hiccup doesn't strand CI. + run: | + uv pip install --python .venv/bin/python -e ".[all,dev]" \ + || uv pip install --python .venv/bin/python -e ".[dev]" \ + || uv pip install --python .venv/bin/python -e . + - name: Run tests + # PATH prepend so any test that subprocess-calls a console script + # finds it in .venv/bin/. + run: | + export PATH="$PWD/.venv/bin:$PATH" + .venv/bin/pytest tests/ --cov=src/scitex_stats --cov-report=xml --cov-report=term + - name: Upload coverage to Codecov + if: always() && matrix.python-version == '3.12' + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage.xml + fail_ci_if_error: false + + audit: + name: audit + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Set up Python 3.12 (uv-managed) + run: uv python install 3.12 + - name: Install package + audit tooling + run: | + uv venv --python 3.12 .venv + uv pip install --python .venv/bin/python -e ".[dev]" + uv pip install --python .venv/bin/python "scitex-dev[cli-audit]" + - name: Run scitex-dev ecosystem audit-all + run: | + export PATH="$PWD/.venv/bin:$PATH" + scitex-dev ecosystem audit-all scitex-stats --no-version-check diff --git a/.github/workflows/pytest-matrix-on-ubuntu-py3-11-3-12-3-13.yml b/.github/workflows/pytest-matrix-on-ubuntu-py3-11-3-12-3-13.yml deleted file mode 100644 index 99cef14..0000000 --- a/.github/workflows/pytest-matrix-on-ubuntu-py3-11-3-12-3-13.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: tests - -on: - push: - branches: [main, develop] - pull_request: - branches: [main, develop] - schedule: - - cron: "0 7 * * *" # nightly 07:00 UTC - workflow_dispatch: - -jobs: - test: - name: pytest-matrix-on-ubuntu-py${{ matrix.python-version }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.11", "3.12", "3.13"] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - # Fallback chain: prefer [all,dev] so optional-dep code paths - # (yaml, fastmcp, textual) get exercised. Falls back to [dev] then - # plain editable so a packaging hiccup doesn't strand CI. - pip install -e ".[all,dev]" || pip install -e ".[dev]" || pip install -e . - - name: Run tests - run: | - pytest tests/ --cov=src/scitex_stats --cov-report=xml --cov-report=term - - name: Upload coverage to Codecov - if: always() && matrix.python-version == '3.12' - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: ./coverage.xml - fail_ci_if_error: false diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml new file mode 100644 index 0000000..7716c82 --- /dev/null +++ b/.github/workflows/release-ci.yml @@ -0,0 +1,100 @@ +name: release-ci + +# Post-merge validation gate. Runs on push to protected branches +# (main, develop) and as the canonical scheduled run. Always uses the +# FULL pytest matrix — no conditional skipping — so the protected-branch +# history is exercised on every supported Python. +# +# L1 concurrency — coalesce overlapping pushes on the same branch. +# L5a uv-managed Python (`uv python install` + `uv venv --python`) so each +# matrix leg pins its interpreter independently of the runner. +# L5b .venv/bin on PATH so console scripts resolve without `uv run`. + +on: + push: + branches: [main, develop] + schedule: + - cron: "0 7 * * *" # nightly 07:00 UTC + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + tests: + name: pytest-matrix-on-ubuntu-py${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.11", "3.12", "3.13"] + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Set up Python ${{ matrix.python-version }} (uv-managed) + run: uv python install ${{ matrix.python-version }} + - name: Create uv venv on this matrix Python + run: uv venv --python ${{ matrix.python-version }} .venv + - name: Install dependencies + run: | + uv pip install --python .venv/bin/python -e ".[all,dev]" \ + || uv pip install --python .venv/bin/python -e ".[dev]" \ + || uv pip install --python .venv/bin/python -e . + - name: Run tests + run: | + export PATH="$PWD/.venv/bin:$PATH" + .venv/bin/pytest tests/ --cov=src/scitex_stats --cov-report=xml --cov-report=term + - name: Upload coverage to Codecov + if: always() && matrix.python-version == '3.12' + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage.xml + fail_ci_if_error: false + + import-smoke: + name: import-smoke-on-ubuntu-py3-12 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Set up Python 3.12 (uv-managed) + run: uv python install 3.12 + - name: Install (no extras) in uv venv + run: | + uv venv --python 3.12 .venv + uv pip install --python .venv/bin/python -e . + - name: Import smoke + run: .venv/bin/python -c "import scitex_stats; print(getattr(scitex_stats, '__version__', 'unversioned'))" + + audit: + name: audit + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Set up Python 3.12 (uv-managed) + run: uv python install 3.12 + - name: Install package + audit tooling + run: | + uv venv --python 3.12 .venv + uv pip install --python .venv/bin/python -e ".[dev]" + uv pip install --python .venv/bin/python "scitex-dev[cli-audit]" + - name: Run scitex-dev ecosystem audit-all + run: | + export PATH="$PWD/.venv/bin:$PATH" + scitex-dev ecosystem audit-all scitex-stats --no-version-check diff --git a/.github/workflows/scitex-stats-quality-audit-on-ubuntu-latest.yml b/.github/workflows/scitex-stats-quality-audit-on-ubuntu-latest.yml deleted file mode 100644 index 702dd53..0000000 --- a/.github/workflows/scitex-stats-quality-audit-on-ubuntu-latest.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: quality - -# Single-package quality gate — runs `scitex-dev ecosystem audit-all` -# against this package (audit-cli / audit-mcp-tools / audit-skills / -# audit-python-apis / audit-project). Mirrors the canonical audit that -# `tests/develop/test_audit.py` runs inside the test suite, but as a -# standalone gate so an audit regression is visible even when the matrix -# is skipped. -# -# The previous body of this workflow shallow-cloned the entire ecosystem -# and ran `scripts/quality/audit_ecosystem.py` — both of which live only -# in scitex-dev, not in leaf packages. That template was copied here -# verbatim and was always broken (FileNotFoundError on a non-existent -# ecosystem registry file). This version audits just this package. - -on: - schedule: - - cron: "0 8 * * *" # 08:00 UTC, after the 07:00 per-repo Test runs - workflow_dispatch: - push: - branches: [develop] - paths: - - "src/**" - - "tests/**" - - "pyproject.toml" - - ".github/workflows/scitex-stats-quality-audit-on-ubuntu-latest.yml" - pull_request: - branches: [main, develop] - -jobs: - audit: - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - - name: Install package + audit tooling - run: | - python -m pip install --upgrade pip - pip install -e ".[dev]" - pip install "scitex-dev[cli-audit]" - - - name: Run scitex-dev ecosystem audit-all - # warn-only: scitex-stats has a 1917-violation backlog (mostly - # PA-307 §3 test-quality on tests/examples/*), tracked in a - # follow-up issue (linked from this PR). The findings still - # surface in this step's logs so they're discoverable; we just - # don't fail the workflow on them — the goal is to stop the - # nightly cron from emailing the operator about a backlog the - # template swap itself didn't introduce. Drop `continue-on-error` - # once the backlog is under the audit-all threshold. - continue-on-error: true - run: scitex-dev ecosystem audit-all scitex-stats --no-version-check