name: CI on: pull_request: # The closed event exists only to supersede stale queued/running PR CI. types: [opened, synchronize, reopened, closed] push: branches: - main workflow_dispatch: concurrency: # github.ref changes to the base branch when a PR is merged, so use the # stable PR number to keep its closed event in the original PR CI group. group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read env: CARGO_TERM_COLOR: always # CI jobs use clean, one-shot builds, so incremental compiler state is not reused. CARGO_INCREMENTAL: "0" # actions/checkout registers safe.directory through a temporary HOME that is # not retained by these container jobs. Keep Git trust scoped to this exact # checkout so vergen-gitcl can read the build revision without weakening the # container's policy for any other path. GIT_CONFIG_COUNT: "1" GIT_CONFIG_KEY_0: safe.directory GIT_CONFIG_VALUE_0: ${{ github.workspace }} jobs: format: name: Format if: github.event_name != 'pull_request' || github.event.action != 'closed' runs-on: ubuntu-latest container: rust:1.96.1-bookworm steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install rustfmt run: rustup component add rustfmt - name: Check formatting run: cargo fmt --all --check clippy: name: Clippy if: github.event_name != 'pull_request' || github.event.action != 'closed' runs-on: ubuntu-latest container: rust:1.96.1-bookworm steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install clippy run: rustup component add clippy - name: Check clippy run: cargo clippy --workspace --all-targets --all-features -- -D warnings nextest: name: Nextest if: github.event_name != 'pull_request' || github.event.action != 'closed' runs-on: [self-hosted, moli-ci] container: rust:1.96.1-bookworm steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install cargo-nextest uses: taiki-e/install-action@13608cbb45b01feb47ef444ab1a42dc41ad56f1a # v2.79.11 with: tool: nextest@0.9.132 # Keep one unpartitioned run so full-suite process and resource interactions # remain visible. The ci profile owns fail-fast and retry behavior. - name: Run full workspace tests run: cargo nextest run --workspace --profile ci protocol-smoke: name: CDP and WebDriver smoke if: github.event_name != 'pull_request' || github.event.action != 'closed' runs-on: ubuntu-latest timeout-minutes: 60 container: rust:1.96.1-bookworm steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 with: version: 0.11.14 python-version: "3.12" enable-cache: true cache-dependency-glob: | moli-cdp-smoke/uv.lock moli-webdriver-smoke/uv.lock - name: Install Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 24.15.0 cache: npm cache-dependency-path: moli-cdp-smoke/package-lock.json - name: Install smoke dependencies run: | uv sync --project moli-cdp-smoke --locked uv sync --project moli-webdriver-smoke --locked npm ci --prefix moli-cdp-smoke - name: Build moli id: build_moli run: cargo build --release -p moli - name: Test WebDriver smoke diagnostics run: >- uv run --project moli-webdriver-smoke --no-sync python -m unittest discover --start-directory moli-webdriver-smoke/tests - name: Run default CDP smoke id: cdp_default continue-on-error: true env: MOLI_BIN: ${{ github.workspace }}/target/release/moli run: uv run --project moli-cdp-smoke --no-sync moli-cdp-smoke - name: Run Puppeteer CDP smoke id: cdp_puppeteer if: ${{ !cancelled() && steps.build_moli.outcome == 'success' }} continue-on-error: true env: MOLI_BIN: ${{ github.workspace }}/target/release/moli run: uv run --project moli-cdp-smoke --no-sync moli-cdp-smoke --group puppeteer - name: Run full WebDriver smoke id: webdriver if: ${{ !cancelled() && steps.build_moli.outcome == 'success' }} continue-on-error: true env: MOLI_BIN: ${{ github.workspace }}/target/release/moli run: >- uv run --project moli-webdriver-smoke --no-sync moli-webdriver-smoke --group classic,bidi,selenium,semantics,url-policy,navigation-errors --continue-on-failure - name: Require all protocol smoke suites if: ${{ always() && !cancelled() && steps.build_moli.outcome == 'success' }} env: CDP_DEFAULT_OUTCOME: ${{ steps.cdp_default.outcome }} CDP_PUPPETEER_OUTCOME: ${{ steps.cdp_puppeteer.outcome }} WEBDRIVER_OUTCOME: ${{ steps.webdriver.outcome }} run: | failed=0 if [ "$CDP_DEFAULT_OUTCOME" != success ]; then echo "default CDP smoke: $CDP_DEFAULT_OUTCOME" failed=1 fi if [ "$CDP_PUPPETEER_OUTCOME" != success ]; then echo "Puppeteer CDP smoke: $CDP_PUPPETEER_OUTCOME" failed=1 fi if [ "$WEBDRIVER_OUTCOME" != success ]; then echo "WebDriver smoke: $WEBDRIVER_OUTCOME" failed=1 fi exit "$failed"