continue gutting #54
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: | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| # Detect docs-only changes to skip heavy jobs (test, build, packaging checks). | |
| # Lint and format always run. Fail-safe: if detection fails, run everything. | |
| docs-scope: | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| outputs: | |
| docs_only: ${{ steps.check.outputs.docs_only }} | |
| docs_changed: ${{ steps.check.outputs.docs_changed }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| fetch-tags: false | |
| submodules: false | |
| - name: Ensure docs-scope base commit | |
| uses: ./.github/actions/ensure-base-commit | |
| with: | |
| base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }} | |
| fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }} | |
| - name: Detect docs-only changes | |
| id: check | |
| uses: ./.github/actions/detect-docs-changes | |
| # Detect which heavy areas are touched so PRs can skip unrelated expensive jobs. | |
| # Push to main keeps broad coverage, but this job still needs to run so | |
| # downstream jobs that list it in `needs` are not skipped. | |
| changed-scope: | |
| needs: [docs-scope] | |
| if: needs.docs-scope.outputs.docs_only != 'true' | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| outputs: | |
| run_node: ${{ steps.scope.outputs.run_node }} | |
| run_skills_python: ${{ steps.scope.outputs.run_skills_python }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| fetch-tags: false | |
| submodules: false | |
| - name: Ensure changed-scope base commit | |
| uses: ./.github/actions/ensure-base-commit | |
| with: | |
| base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }} | |
| fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }} | |
| - name: Detect changed scopes | |
| id: scope | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ github.event_name }}" = "push" ]; then | |
| BASE="${{ github.event.before }}" | |
| else | |
| BASE="${{ github.event.pull_request.base.sha }}" | |
| fi | |
| node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD | |
| # Build dist once for Node-relevant changes and share it with downstream jobs. | |
| build-artifacts: | |
| needs: [docs-scope, changed-scope] | |
| if: needs.docs-scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.changed-scope.outputs.run_node == 'true') | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: false | |
| - name: Ensure secrets base commit (PR fast path) | |
| if: github.event_name == 'pull_request' | |
| uses: ./.github/actions/ensure-base-commit | |
| with: | |
| base-sha: ${{ github.event.pull_request.base.sha }} | |
| fetch-ref: ${{ github.event.pull_request.base.ref }} | |
| - name: Setup Node environment | |
| uses: ./.github/actions/setup-node-env | |
| with: | |
| install-bun: "false" | |
| use-sticky-disk: "true" | |
| - name: Build dist | |
| run: pnpm build | |
| - name: Upload dist artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist-build | |
| path: dist/ | |
| retention-days: 1 | |
| # Validate npm pack contents after build (only on push to main, not PRs). | |
| release-check: | |
| needs: [docs-scope, build-artifacts] | |
| if: github.event_name == 'push' && needs.docs-scope.outputs.docs_only != 'true' | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: false | |
| - name: Setup Node environment | |
| uses: ./.github/actions/setup-node-env | |
| with: | |
| install-bun: "false" | |
| use-sticky-disk: "true" | |
| - name: Download dist artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist-build | |
| path: dist/ | |
| - name: Check release contents | |
| run: pnpm release:check | |
| checks: | |
| needs: [docs-scope, changed-scope] | |
| if: needs.docs-scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.changed-scope.outputs.run_node == 'true') | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runtime: node | |
| task: test | |
| command: pnpm test | |
| - runtime: node | |
| task: extensions | |
| command: pnpm test:extensions | |
| - runtime: node | |
| task: protocol | |
| command: pnpm protocol:check | |
| - runtime: bun | |
| task: test | |
| command: bunx vitest run --config vitest.unit.config.ts | |
| steps: | |
| - name: Skip bun lane on push | |
| if: github.event_name == 'push' && matrix.runtime == 'bun' | |
| run: echo "Skipping bun test lane on push events." | |
| - name: Checkout | |
| if: github.event_name != 'push' || matrix.runtime != 'bun' | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: false | |
| - name: Setup Node environment | |
| if: matrix.runtime != 'bun' || github.event_name != 'push' | |
| uses: ./.github/actions/setup-node-env | |
| with: | |
| install-bun: "${{ matrix.runtime == 'bun' }}" | |
| use-sticky-disk: "true" | |
| - name: Configure Node test resources | |
| if: (github.event_name != 'push' || matrix.runtime != 'bun') && matrix.task == 'test' && matrix.runtime == 'node' | |
| run: | | |
| # `pnpm test` runs `scripts/test-parallel.mjs`, which spawns multiple Node processes. | |
| # Default heap limits have been too low on Linux CI (V8 OOM near 4GB). | |
| echo "OPENCLAW_TEST_WORKERS=2" >> "$GITHUB_ENV" | |
| echo "OPENCLAW_TEST_MAX_OLD_SPACE_SIZE_MB=6144" >> "$GITHUB_ENV" | |
| - name: Run ${{ matrix.task }} (${{ matrix.runtime }}) | |
| if: matrix.runtime != 'bun' || github.event_name != 'push' | |
| run: ${{ matrix.command }} | |
| # Types, lint, and format check. | |
| check: | |
| name: "check" | |
| needs: [docs-scope, changed-scope] | |
| if: needs.docs-scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.changed-scope.outputs.run_node == 'true') | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: false | |
| - name: Setup Node environment | |
| uses: ./.github/actions/setup-node-env | |
| with: | |
| install-bun: "false" | |
| use-sticky-disk: "true" | |
| - name: Check types and lint and oxfmt | |
| run: pnpm check | |
| - name: Strict TS build smoke | |
| run: pnpm build:strict-smoke | |
| - name: Enforce safe external URL opening policy | |
| run: pnpm lint:ui:no-raw-window-open | |
| # Validate docs (format, lint, broken links) only when docs files changed. | |
| check-docs: | |
| needs: [docs-scope] | |
| if: needs.docs-scope.outputs.docs_changed == 'true' | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: false | |
| - name: Setup Node environment | |
| uses: ./.github/actions/setup-node-env | |
| with: | |
| install-bun: "false" | |
| use-sticky-disk: "true" | |
| - name: Check docs | |
| run: pnpm check:docs | |
| skills-python: | |
| needs: [docs-scope, changed-scope] | |
| if: needs.docs-scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.changed-scope.outputs.run_node == 'true' || needs.changed-scope.outputs.run_skills_python == 'true') | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: false | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install Python tooling | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install pytest ruff pyyaml | |
| - name: Lint Python skill scripts | |
| run: python -m ruff check skills | |
| - name: Test skill Python scripts | |
| run: python -m pytest -q skills | |
| secrets: | |
| runs-on: blacksmith-16vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: false | |
| - name: Ensure secrets base commit | |
| uses: ./.github/actions/ensure-base-commit | |
| with: | |
| base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }} | |
| fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }} | |
| - name: Setup Node environment | |
| uses: ./.github/actions/setup-node-env | |
| with: | |
| install-bun: "false" | |
| use-sticky-disk: "false" | |
| install-deps: "false" | |
| - name: Setup Python | |
| id: setup-python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| cache: "pip" | |
| cache-dependency-path: | | |
| pyproject.toml | |
| .pre-commit-config.yaml | |
| .github/workflows/ci.yml | |
| - name: Restore pre-commit cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pre-commit | |
| key: pre-commit-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }} | |
| - name: Install pre-commit | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install pre-commit | |
| - name: Detect committed private keys | |
| run: pre-commit run --all-files detect-private-key | |
| - name: Audit changed GitHub workflows with zizmor | |
| run: | | |
| set -euo pipefail | |
| if [ "${{ github.event_name }}" = "push" ]; then | |
| BASE="${{ github.event.before }}" | |
| else | |
| BASE="${{ github.event.pull_request.base.sha }}" | |
| fi | |
| mapfile -t workflow_files < <(git diff --name-only "$BASE" HEAD -- '.github/workflows/*.yml' '.github/workflows/*.yaml') | |
| if [ "${#workflow_files[@]}" -eq 0 ]; then | |
| echo "No workflow changes detected; skipping zizmor." | |
| exit 0 | |
| fi | |
| pre-commit run zizmor --files "${workflow_files[@]}" | |
| - name: Audit production dependencies | |
| run: pre-commit run --all-files pnpm-audit-prod |