diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be06bd4..a837d3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,6 @@ # PR and main-branch CI — lint and test only (no secrets, no PyPI OIDC). -# Keep install/lint/test steps in sync with publish-pypi.yml test job until issue #7 -# (reusable workflow) lands. PR CI also matrices Python versions; publish stays -# single-version as a release gate (see docs/TESTING.md). +# Lint/test steps live in reusable-test.yml (issue #17). PR CI matrices Python +# versions; publish stays single-version as a release gate (see docs/TESTING.md). name: CI @@ -21,46 +20,21 @@ concurrency: jobs: lint-test: name: Python ${{ matrix.python-version }} - runs-on: ubuntu-latest strategy: fail-fast: true matrix: python-version: ["3.10", "3.11", "3.12", "3.13"] - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Install dev dependencies - run: | - python -m pip install --upgrade pip - pip install -e ".[dev]" - - name: Dependency audit (warn-only) - continue-on-error: true - run: | - pip install pip-audit - pip-audit - - name: black - run: black --check aura tests integrations examples - - name: flake8 - run: flake8 aura tests integrations examples - - name: pytest - run: pytest --cov=aura --cov-report=term-missing --ignore=tests/integration + uses: ./.github/workflows/reusable-test.yml + with: + python-version: ${{ matrix.python-version }} + pip-audit: true skillware-live: name: Skillware registry (live) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Install with Skillware extra - run: | - python -m pip install --upgrade pip - pip install -e ".[dev,skillware]" - - name: pytest skillware - run: pytest tests/test_skillware_integration.py -v + uses: ./.github/workflows/reusable-test.yml + with: + python-version: "3.12" + skillware: true # Stable check name for branch protection (matrix cells are "Python 3.xx"). ci-ok: diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index d3036ff..8029afd 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -21,22 +21,11 @@ permissions: contents: read jobs: - # Commands must match .github/workflows/ci.yml (see docs/TESTING.md). - # PR CI matrices 3.10–3.13; this job stays on 3.12 as a single-version release gate. + # Same lint/test as PR CI via reusable-test.yml (Python 3.12 release gate). test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Install and test - run: | - python -m pip install --upgrade pip - pip install -e ".[dev]" - black --check aura tests integrations examples - flake8 aura tests - pytest --cov=aura --cov-report=term-missing + uses: ./.github/workflows/reusable-test.yml + with: + python-version: "3.12" publish: needs: test diff --git a/.github/workflows/reusable-test.yml b/.github/workflows/reusable-test.yml new file mode 100644 index 0000000..4462432 --- /dev/null +++ b/.github/workflows/reusable-test.yml @@ -0,0 +1,65 @@ +# Callable lint + test job — single source for PR CI and PyPI publish (issue #17). +# Callers: ci.yml (matrix + skillware-live), publish-pypi.yml (release gate). + +name: Reusable lint and test + +on: + workflow_call: + inputs: + python-version: + required: true + type: string + pip-audit: + description: Run pip-audit (warn-only; does not fail the job) + required: false + type: boolean + default: false + skillware: + description: Install [skillware] and run registry integration tests only + required: false + type: boolean + default: false + +permissions: + contents: read + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ "${{ inputs.skillware }}" = "true" ]; then + pip install -e ".[dev,skillware]" + else + pip install -e ".[dev]" + fi + + - name: Dependency audit (warn-only) + if: inputs.pip-audit == true + continue-on-error: true + run: | + pip install pip-audit + pip-audit + + - name: black + if: inputs.skillware != true + run: black --check aura tests integrations examples + + - name: flake8 + if: inputs.skillware != true + run: flake8 aura tests integrations examples + + - name: pytest (gate suite) + if: inputs.skillware != true + run: pytest --cov=aura --cov-report=term-missing --ignore=tests/integration + + - name: pytest skillware + if: inputs.skillware == true + run: pytest tests/test_skillware_integration.py -v diff --git a/CHANGELOG.md b/CHANGELOG.md index f41c3fe..cb49cf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **Reusable CI workflow** — `.github/workflows/reusable-test.yml` shared by PR CI and PyPI publish; fixes publish drift (flake8 scope, `--ignore=tests/integration`) ([#17](https://github.com/ARPAHLS/aura/issues/17)). + - **Docs sync (post–#12)** — INDEX, ROADMAP, integration guides, follow-ups backlog, OTel/observer sections aligned with PR #43 closure ([#41](https://github.com/ARPAHLS/aura/issues/41), [#22](https://github.com/ARPAHLS/aura/issues/22)). - **Example 06** — compress step skips when scan `is_safe` is false (sequencer `when`). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d449201..c19613f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -132,7 +132,7 @@ Follow the [Code of Conduct](CODE_OF_CONDUCT.md). We welcome autonomous logical - Shared fixtures: **`tests/conftest.py`** (`aura_home`, `run_aura` for CLI subprocess tests). - Full suite is **64+ tests** across `test_core.py`, `test_core_gaps.py`, `test_v02.py`, `test_v03.py`, `test_cli.py`, `test_examples_smoke.py` — see [TESTING.md](docs/TESTING.md). -- CI runs on PRs via [`.github/workflows/ci.yml`](.github/workflows/ci.yml) (Python **3.10–3.13** matrix; gate job **`lint-test`**: pytest with coverage report, black, flake8). Each matrix cell also runs `pip-audit` as a warn-only dependency check; its findings or audit errors do not fail the gate or block a PR. See [TESTING.md](docs/TESTING.md) for the exact commands. +- CI runs on PRs via [`.github/workflows/ci.yml`](.github/workflows/ci.yml) (Python **3.10–3.13** matrix; gate job **`lint-test`**: pytest with coverage report, black, flake8). Steps are defined once in [`.github/workflows/reusable-test.yml`](.github/workflows/reusable-test.yml). Each matrix cell also runs `pip-audit` as a warn-only dependency check; its findings or audit errors do not fail the gate or block a PR. See [TESTING.md](docs/TESTING.md) for the exact commands. - Wait for green checks before requesting review. ### CHANGELOG @@ -161,7 +161,7 @@ Pure internal refactors with no user-visible effect may omit CHANGELOG; ask on t | New core example | `examples/README.md`, optional link from `docs/getting-started.md` | | Architecture terminology | `docs/architecture.md`, `README.md` diagrams (keep in sync) | | Release / PyPI behavior | `docs/PUBLISHING.md`, `.github/workflows/publish-pypi.yml`, CHANGELOG | -| PR CI workflow | `.github/workflows/ci.yml`, `docs/TESTING.md`, `CONTRIBUTING.md`; keep publish test job in sync | +| PR CI workflow | `.github/workflows/ci.yml`, `.github/workflows/reusable-test.yml`, `docs/TESTING.md`, `CONTRIBUTING.md` | | Issue template fields | `.github/labels.json` if new label needed; run label sync | | Version (maintainer only) | `pyproject.toml`, `aura/__init__.py`, `CITATION.cff`, CHANGELOG release section, Zenodo if archived | diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md index 4f653dd..fb560c6 100644 --- a/docs/PUBLISHING.md +++ b/docs/PUBLISHING.md @@ -7,7 +7,7 @@ Releases are published automatically by [`.github/workflows/publish-pypi.yml`](. Pushing a `v*` tag alone does **not** publish; create and publish the GitHub Release from that tag. -The workflow runs tests (Python 3.12), builds sdist/wheel, then uploads to PyPI. **Pull requests** are gated separately by [`.github/workflows/ci.yml`](.github/workflows/ci.yml) (Python 3.10–3.13 matrix; `lint-test` on every PR to `main`). +The workflow calls **`reusable-test.yml`** (Python 3.12), builds sdist/wheel, then uploads to PyPI. **Pull requests** are gated separately by [`.github/workflows/ci.yml`](.github/workflows/ci.yml) (Python 3.10–3.13 matrix; `lint-test` on every PR to `main`). ## One-time PyPI setup diff --git a/docs/TESTING.md b/docs/TESTING.md index dc3de29..3059829 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -26,7 +26,15 @@ CI expectation: **pytest**, **black**, and **flake8** all pass on `aura/` and `t ## Continuous integration -GitHub Actions workflow **[`.github/workflows/ci.yml`](../.github/workflows/ci.yml)** runs on: +GitHub Actions: + +| Workflow | Role | +|---|---| +| **[`ci.yml`](../.github/workflows/ci.yml)** | PR + push to `main` — Python matrix, Skillware job, gate `lint-test` | +| **[`reusable-test.yml`](../.github/workflows/reusable-test.yml)** | **Single source** for install / black / flake8 / pytest (issue [#17](https://github.com/ARPAHLS/aura/issues/17)) | +| **[`publish-pypi.yml`](../.github/workflows/publish-pypi.yml)** | Release gate — calls `reusable-test.yml` on Python 3.12 before upload | + +**[`ci.yml`](../.github/workflows/ci.yml)** runs on: - every **pull request** targeting `main` - every **push** to `main` (post-merge sanity) @@ -37,15 +45,15 @@ Python matrix on **ubuntu-latest** (`fail-fast: true` — one version failure ca python-version: ["3.10", "3.11", "3.12", "3.13"] ``` -Each cell runs the same steps: +Each matrix cell invokes **`reusable-test.yml`** with the same steps: ```bash pip install -e ".[dev]" pip install pip-audit pip-audit # warn-only; does not block the CI gate -black --check aura tests -flake8 aura tests -pytest --cov=aura --cov-report=term-missing +black --check aura tests integrations examples +flake8 aura tests integrations examples +pytest --cov=aura --cov-report=term-missing --ignore=tests/integration ``` The **Dependency audit (warn-only)** step runs `pip-audit` with @@ -59,7 +67,9 @@ The workflow also emits a gate job named **`lint-test`** that succeeds only when **Fork PRs:** the workflow uses `permissions: contents: read` only — no repository secrets, no PyPI OIDC, no deploy environment. -**Publish workflow:** [`.github/workflows/publish-pypi.yml`](../.github/workflows/publish-pypi.yml) runs the same install/lint/test commands on a single Python 3.12 before release upload. The advisory `pip-audit` step belongs to PR CI and is not a release-blocking check. Full 3.10–3.13 coverage is the PR CI matrix; keep the *commands* in sync until a reusable workflow lands (separate CI follow-up issue). +**Publish workflow:** [`.github/workflows/publish-pypi.yml`](../.github/workflows/publish-pypi.yml) calls **`reusable-test.yml`** on Python 3.12 before release upload (no `pip-audit`; same black/flake8/pytest scope as PR CI). Full 3.10–3.13 coverage is the PR CI matrix. + +**Skillware job:** **`skillware-live`** in `ci.yml` calls **`reusable-test.yml`** with `skillware: true` — `pip install -e ".[dev,skillware]"` and `pytest tests/test_skillware_integration.py`. **Maintainers:** after the first green `lint-test` run on `main`, enable **branch protection** → required status check **`lint-test`**. @@ -107,9 +117,9 @@ Integration tests **fail** (not skip) if Ollama or Skillware is missing — that ## Pre-PR checklist -1. `pytest` -2. `black aura tests` (no diff) -3. `flake8 aura tests` +1. `pytest --ignore=tests/integration` +2. `black aura tests integrations examples` (no diff) +3. `flake8 aura tests integrations examples` 4. CHANGELOG entry under `[Unreleased]` or release section 5. Docs updated if behavior or CLI changed diff --git a/docs/contributing/ai_native_workflow.md b/docs/contributing/ai_native_workflow.md index 6eeb921..1300e00 100644 --- a/docs/contributing/ai_native_workflow.md +++ b/docs/contributing/ai_native_workflow.md @@ -45,7 +45,7 @@ Written for **autonomous and semi-autonomous agents** working on AURA Harness. H - **Session export:** `.jsonl`, `.summary.json` (with `audit_report`), `.otel.jsonl` - **CLI:** `aura agent create/set`, `config show`, `paths`, `run`, `logs`, `export`, `export-otel`, `compare` - **SDK helpers:** `AuditSpine.from_jsonl()` for disk verify; `compare_sessions()` includes `agent_ref` and `hash_chain_valid` diffs -- **CI:** Python 3.10–3.13 matrix on every PR; gate job `lint-test` ([`ci.yml`](../../.github/workflows/ci.yml)) +- **CI:** Python 3.10–3.13 matrix on every PR; gate job `lint-test` ([`ci.yml`](../../.github/workflows/ci.yml) → [`reusable-test.yml`](../../.github/workflows/reusable-test.yml)) ---