CI #70
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| branches: [main, master] | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 6 * * MON" | |
| - cron: "0 4 * * *" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Test (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.13"] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - name: Set up Python | |
| run: uv python install ${{ matrix.python-version }} | |
| - name: Install dependencies | |
| run: uv sync --all-packages | |
| - name: Ruff lint | |
| run: uv run ruff check packages/ | |
| - name: Ruff format check | |
| run: uv run ruff format --check packages/ | |
| - name: Mypy type check | |
| run: uv run mypy packages/jw-core/src packages/jw-mcp/src | |
| continue-on-error: true # Mypy strict has known false-positives on FastMCP | |
| - name: Pytest | |
| run: uv run pytest packages/ -v --tb=short | |
| - name: Build wheels (smoke) | |
| run: | | |
| for pkg in packages/jw-core packages/jw-mcp packages/jw-cli packages/jw-rag packages/jw-agents; do | |
| (cd "$pkg" && uv build --wheel) || exit 1 | |
| done | |
| security: | |
| name: Security scan | |
| runs-on: ubuntu-latest | |
| needs: test | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| - run: uv run --with bandit bandit -r packages/*/src -ll | |
| continue-on-error: true | |
| test-rag-embeddings: | |
| name: jw-rag embeddings-local (optional) | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| - uses: astral-sh/setup-uv@v6 | |
| - run: uv sync --all-packages | |
| - run: uv pip install -e packages/jw-rag[embeddings-local,rerank-local] | |
| - run: uv run pytest packages/jw-rag/tests -m embeddings_local -v | |
| eval-fast: | |
| # Non-blocking: the 38 L1/L2 golden cases shipped by phases 22-32 are | |
| # aspirational scaffolding — they were never calibrated against the | |
| # real agent signatures. The eval *infrastructure* works, but the | |
| # cases will all error until someone reconciles them with each agent's | |
| # actual input contract. Tracked as a follow-up task; meanwhile this | |
| # job runs and uploads the report but does NOT gate the build. | |
| name: Eval fast (L1 + L2 snapshot) [non-blocking] | |
| needs: test | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - name: Run jw eval layers 1+2 | |
| run: uv run jw eval --layer 1,2 --report md --out eval-fast.md | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: eval-fast-report | |
| path: eval-fast.md | |
| eval-l2-live: | |
| name: Eval L2 live (weekly) | |
| if: github.event_name == 'schedule' && github.event.schedule == '0 6 * * MON' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - run: uv run jw eval --layer 2 --live --report json --out l2-live.json | |
| - run: uv run python packages/jw-eval/scripts/eval_open_drift_issues.py l2-live.json | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| gen-policy: | |
| name: jw-gen policy (offline, property test) | |
| needs: test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - name: jw-gen unit tests (offline) | |
| run: uv run pytest packages/jw-gen/tests -v | |
| - name: Property test — 100 adversarial prompts then 0 allowed | |
| run: uv run pytest packages/jw-gen/tests/test_safety_property.py -v | |
| - name: Smoke — output always carries watermark + disclaimer | |
| run: uv run pytest packages/jw-gen/tests/test_policy.py -v -k "finalize" | |
| - name: CLI smoke — fake image succeeds, fake logo prompt fails | |
| env: | |
| JW_GEN_IMAGE_PROVIDER: fake | |
| JW_GEN_HOME: /tmp/jw-gen-ci | |
| run: | | |
| uv run jw gen image --prompt "ovejas pastoreadas" --out /tmp/ok.png | |
| test -f /tmp/ok.png | |
| test -f /tmp/ok.png.disclaimer.txt | |
| ! uv run jw gen image --prompt "watchtower logo blue" --out /tmp/bad.png | |
| ! test -f /tmp/bad.png | |
| eval-nightly: | |
| name: Eval nightly (L1+L2+L3 Ollama) | |
| if: github.event_name == 'schedule' && github.event.schedule == '0 4 * * *' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - run: JW_EVAL_LLM=none uv run jw eval --layer 1,2,3 --report md --out eval-nightly.md | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: eval-nightly-report | |
| path: eval-nightly.md | |
| chunker-bench-nightly: | |
| name: Chunker NDCG@10 (paragraph vs semantic) | |
| if: github.event_name == 'schedule' && github.event.schedule == '0 4 * * *' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - run: JW_EVAL_LLM=none uv run jw chunker-bench --variants paragraph,semantic --report md --out chunker-bench.md | |
| - if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: chunker-bench-report | |
| path: chunker-bench.md | |
| plugin-sdk: | |
| name: Plugin SDK (e2e fixture install, offline) | |
| needs: test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - run: uv pip install -e packages/jw-core/tests/fixtures/plugin_sample | |
| - run: uv run pytest packages/jw-core/tests/test_plugins_*.py -v | |
| - run: uv run jw plugins list --json | head -30 | |
| cookbook-tests: | |
| name: Cookbook recipes (executable Markdown blocks) | |
| needs: test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - run: uv run pytest --cookbook-dir=docs/cookbook docs/cookbook/ -v | |
| create-jw-agent: | |
| name: create-jw-agent (scaffolder + golden snapshots) | |
| needs: test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: astral-sh/setup-uv@v6 | |
| - run: uv python install 3.13 | |
| - run: uv sync --all-packages | |
| - run: uv run pytest packages/create-jw-agent/tests/ -v | |
| - run: uv run pytest tools/pytest-cookbook/tests/ -v | |
| # Smoke E2E: scaffold + verify the generated project's first commit is CI-green. | |
| - name: E2E scaffold smoke | |
| run: | | |
| mkdir -p /tmp/smoke | |
| uv run create-jw-agent demo-plugin --type=agent --lang=en \ | |
| --output-dir=/tmp/smoke/demo-plugin --quiet | |
| test -f /tmp/smoke/demo-plugin/pyproject.toml | |
| test -f /tmp/smoke/demo-plugin/.github/workflows/ci.yml | |
| test -f /tmp/smoke/demo-plugin/src/demo_plugin/agent.py |