[Fix] Fix runtime bugs #278
Workflow file for this run
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] | |
| pull_request: | |
| branches: [main] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| # Both lanes below are offline: the LLM boundary is served from the committed | |
| # cassette store. That is deliberate — a pull request from a fork cannot access | |
| # secrets, so anything gating a merge must run without them. | |
| LEAPFLOW_TEST_LLM_MODE: replay | |
| jobs: | |
| # ── L1: pull-request lane ────────────────────────────────────────────── | |
| # Static checks, the whole real layer, and the whole mock layer. | |
| # | |
| # Change-scoped selection is deliberately NOT used here, and the reason is | |
| # arithmetic rather than distrust. Measured on this suite: the full mock layer | |
| # is ~18s, while the always-on tier alone (real journeys + regression ledger + | |
| # architecture contracts) is ~14s. Those tiers can never be selected away, so | |
| # they set the floor — selecting the mock layer can save at most ~4s, however | |
| # precise the selection gets. Spending correctness risk on four seconds is a | |
| # bad trade. | |
| # | |
| # Revisit when the full mock layer stops fitting the feedback budget — | |
| # concretely, when `make test-unit` exceeds ~3 minutes on CI hardware. The | |
| # machinery is ready and tested (tools/impact.py, with a coverage-derived map | |
| # in tests/.impact/); `make test-impact` already uses it locally, where a | |
| # single-module change narrows to 2-3 test files. | |
| # | |
| # The live lane *does* select, in .github/workflows/nightly-live.yaml: there a | |
| # journey costs real tokens, so the arithmetic comes out the other way. | |
| pr: | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: uv sync --all-extras | |
| - name: Lint | |
| run: uv run ruff check src/leapflow/ tests/ tools/ | |
| - name: Verify derived fixtures match the cassette store | |
| run: uv run python tools/sync_fixtures.py --check | |
| - name: Real layer — journeys and always-on guards | |
| run: uv run pytest tests/journeys tests/regression tests/test_architecture_contracts.py -q -m "e2e or invariant or unit" -n 4 | |
| - name: Mock layer (full) | |
| run: uv run pytest tests/ -q -m "not e2e" --tb=short -n auto | |
| # ── L2: main lane ────────────────────────────────────────────────────── | |
| # Everything, unscoped, across the supported matrix. | |
| main: | |
| if: github.event_name == 'push' | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 40 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| 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 uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: uv sync --all-extras | |
| - name: Lint | |
| run: uv run ruff check src/leapflow/ tests/ tools/ | |
| - name: Verify derived fixtures match the stored exchanges | |
| run: uv run python tools/sync_fixtures.py --check | |
| - name: Mock layer — full | |
| run: uv run pytest tests/ -q -m "not e2e" --tb=short -n auto | |
| - name: Real layer — full | |
| run: uv run pytest tests/journeys -q -m e2e --tb=short -n 4 | |
| - name: Daemon logs on failure | |
| if: failure() | |
| run: | | |
| echo "Journey daemons log under the scratch root; surface anything left behind." | |
| find /tmp -maxdepth 6 -name 'leapd.log' -newermt '-40 minutes' 2>/dev/null | while read -r log; do | |
| echo "===== $log =====" | |
| tail -n 120 "$log" | |
| done |