CI (OpenClaw E2E) #11
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
| # OpenClaw end-to-end CI. | |
| # | |
| # Triggers, in order of intent: | |
| # 1. PRs that touch OpenClaw-relevant paths (auto, primary signal) | |
| # 2. Pushes to main that touch the same paths (post-merge regression catch) | |
| # 3. Daily schedule at 06:00 UTC (catches environment drift — | |
| # OpenClaw version bumps, MCP SDK | |
| # breaks, npm install regressions) | |
| # 4. Adding the `ci:openclaw` label to a PR (manual re-run on matching PRs) | |
| # 5. Workflow_dispatch from the Actions UI (manual force-run on any ref, | |
| # no PR needed) | |
| # | |
| # The path filter at the trigger level is the primary gate, so non-OpenClaw PRs | |
| # pay no CI cost. The label is only useful as a re-trigger on PRs that already | |
| # matched paths; for force-running against an unrelated branch, use the manual | |
| # dispatch button in the Actions UI. | |
| name: CI (OpenClaw E2E) | |
| on: | |
| pull_request: | |
| branches: [main] | |
| types: [opened, synchronize, reopened, labeled, unlabeled] | |
| paths: | |
| - "app/integrations/openclaw.py" | |
| - "app/tools/OpenClawMCPTool/**" | |
| - "tests/e2e/openclaw/**" | |
| - "tests/utils/alert_factory/**" | |
| - ".github/workflows/e2e-openclaw.yml" | |
| - "docs/openclaw.mdx" | |
| - ".nvmrc" | |
| push: | |
| branches: [main] | |
| paths: | |
| - "app/integrations/openclaw.py" | |
| - "app/tools/OpenClawMCPTool/**" | |
| - "tests/e2e/openclaw/**" | |
| - "tests/utils/alert_factory/**" | |
| - ".github/workflows/e2e-openclaw.yml" | |
| - "docs/openclaw.mdx" | |
| - ".nvmrc" | |
| schedule: | |
| - cron: "0 6 * * *" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| concurrency: | |
| group: ci-openclaw-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Quality gates (lint / format-check / mypy) are run by the main | |
| # ``ci.yml`` workflow for every PR. We don't duplicate them here — | |
| # this workflow's sole job is the OpenClaw e2e suite. If you reach | |
| # this workflow, your PR has already cleared the quality gates. | |
| openclaw-test: | |
| name: openclaw test | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| # No ``env:`` block by design. CI runs the boot + use-case | |
| # scenarios only — the full-RCA sub-tests call an LLM, cost API | |
| # credits, and take ~25s each, so we deliberately don't wire any | |
| # LLM secret in. They auto-skip via | |
| # ``LLM_CREDENTIAL_SKIP_REASON`` when no key is present in env. | |
| # Contributors with ANTHROPIC_API_KEY / OPENAI_API_KEY / | |
| # GEMINI_API_KEY set locally still run them via | |
| # ``make test-openclaw``. Lang Smith env vars stay scoped to the | |
| # local-RCA path for the same reason — no value tracing the | |
| # use-case-only CI runs. | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Set up Node (OpenClaw requires >=22.12; version pinned in .nvmrc) | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version-file: ".nvmrc" | |
| - name: Install OpenClaw CLI | |
| # ``continue-on-error: true`` so an npm-registry hiccup, a package-name | |
| # rename on OpenClaw's side, or a network blip does not kill the whole | |
| # workflow. The "Probe OpenClaw availability" step below catches the | |
| # failure and downgrades the run to "tests skipped" with a clear | |
| # explanation rather than crashing. | |
| continue-on-error: true | |
| id: install_openclaw | |
| run: npm install -g openclaw | |
| - name: Probe OpenClaw availability | |
| # Whether or not ``npm install`` succeeded, check if ``openclaw`` is | |
| # actually runnable. Failure modes we surface explicitly: | |
| # - CLI not installed (npm step failed silently) | |
| # - CLI installed but Node version mismatch (older runner image) | |
| # - CLI installed but the bundled JS errored on first run | |
| # ``openclaw_runnable`` env var feeds the next step's gating. | |
| run: | | |
| set +e | |
| if ! command -v openclaw >/dev/null 2>&1; then | |
| echo "::warning::openclaw CLI is not on PATH (npm install may have failed); the e2e suite will be skipped this run." | |
| echo "openclaw_runnable=false" >> "$GITHUB_ENV" | |
| exit 0 | |
| fi | |
| version_output="$(openclaw --version 2>&1)" | |
| if [ $? -ne 0 ]; then | |
| echo "::warning::openclaw is on PATH but errors when run:" | |
| echo "$version_output" | |
| echo "::warning::Skipping e2e suite this run." | |
| echo "openclaw_runnable=false" >> "$GITHUB_ENV" | |
| exit 0 | |
| fi | |
| echo "✓ OpenClaw verified: $version_output" | |
| echo "openclaw_runnable=true" >> "$GITHUB_ENV" | |
| - name: Note LLM credential policy | |
| # CI deliberately does not wire any LLM key, so the full-RCA | |
| # sub-tests skip every run. This step is informational — it | |
| # makes the policy obvious in the run log instead of leaving a | |
| # silent skip that a reviewer has to dig for. Run RCA locally | |
| # with ``make test-openclaw`` if you have a key configured. | |
| run: | | |
| echo "ℹ︎ CI policy: full-RCA sub-tests are skipped (LLM credentials intentionally not wired)." | |
| echo " Boot + use-case sub-tests still run and gate the merge." | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: | | |
| pyproject.toml | |
| uv.lock | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.13" | |
| - name: Install dependencies | |
| run: uv sync --frozen --extra dev | |
| - name: Run OpenClaw E2E suite | |
| # Skips with a clear message if the OpenClaw probe failed earlier, | |
| # so the workflow finishes green with a documented "couldn't run" | |
| # status rather than a confusing red on the install step. | |
| run: | | |
| if [ "$openclaw_runnable" != "true" ]; then | |
| echo "::warning::Skipping pytest invocation — openclaw CLI unavailable in this environment. See earlier warnings." | |
| exit 0 | |
| fi | |
| uv run python -m pytest -m e2e -v tests/e2e/openclaw/ | |
| - name: Upload gateway logs on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openclaw-gateway-logs | |
| path: /tmp/openclaw-e2e-logs/ | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| - name: Summary | |
| # Always runs, regardless of earlier step outcomes. The probe | |
| # step above downgrades a missing-CLI / wrong-Node environment | |
| # to "tests skipped" rather than failing the workflow, so this | |
| # summary is the one place a reviewer sees why fewer tests ran | |
| # than expected. Real pytest failures still fail the job. | |
| if: always() | |
| run: | | |
| echo "### OpenClaw E2E run summary" | |
| echo " OpenClaw runnable: ${openclaw_runnable:-unknown}" | |
| echo " Full-RCA sub-tests: skipped by CI policy (no LLM key wired)" | |
| echo " Run RCA locally with: make test-openclaw" |