# 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: - "integrations/openclaw.py" - "tools/OpenClawMCPTool/**" - "tests/e2e/openclaw/**" - "tests/utils/alert_factory/**" - ".github/workflows/e2e-openclaw.yml" - "docs/openclaw.mdx" - ".tool-versions" push: branches: [main] paths: - "integrations/openclaw.py" - "tools/OpenClawMCPTool/**" - "tests/e2e/openclaw/**" - "tests/utils/alert_factory/**" - ".github/workflows/e2e-openclaw.yml" - "docs/openclaw.mdx" - ".tool-versions" 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: if: github.repository == 'Tracer-Cloud/opensre' 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 .tool-versions) uses: actions/setup-node@v4 with: node-version-file: ".tool-versions" - name: Cache npm downloads uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-openclaw-npm-${{ hashFiles('.tool-versions') }} restore-keys: | ${{ runner.os }}-openclaw-npm- - 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 --prefer-offline --no-audit - 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"