Repository navigation
docs: polish bilingual README and use existing WebCodex icon #5
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: | |
| types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled] | |
| # Keep only the newest run for a PR. Main pushes use the commit SHA as the | |
| # group key, so every merged main commit still receives its own full CI run. | |
| concurrency: | |
| group: ci-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: true | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| contract: | |
| # Mandatory first lane for every workflow invocation: pull requests and | |
| # pushes to main. Owner-authored PRs do not need `run-ci` for this cheap gate. | |
| # Keep it limited to deterministic, in-process/static checks so feedback stays fast. | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-ci | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install frontend dependencies | |
| run: npm ci --prefix frontend | |
| - name: Check frontend contracts | |
| run: | | |
| npm --prefix frontend run typecheck | |
| npm --prefix frontend test | |
| npm --prefix frontend run check:dist | |
| - name: Verify workspace boundaries | |
| run: | | |
| bash scripts/workspace_boundary_check.sh --self-test | |
| bash scripts/workspace_boundary_check.sh | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| - name: Ensure test inventory dependency | |
| run: | | |
| if ! command -v rg >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install --no-install-recommends -y ripgrep | |
| fi | |
| - name: Check test inventory contract | |
| run: | | |
| bash scripts/test_inventory.sh --self-test | |
| bash scripts/test_inventory.sh | |
| - name: Check schema and metadata contracts | |
| run: | | |
| cargo test --locked -p webcodex --lib -- \ | |
| openapi_operation_ids_are_minimal \ | |
| openapi_all_local_refs_resolve \ | |
| openapi_tool_call_request_does_not_advertise_hidden_start_bootstrap \ | |
| mcp_tools_list_returns_same_names_as_runtime \ | |
| explicit_resume_advanced_compatibility_schema_and_metadata_are_retained \ | |
| http_project_connector_lists_and_dispatches_only_canonical_capabilities | |
| test-linux-rust: | |
| # Complete Linux Rust coverage is mandatory before merge, including owner PRs. | |
| # Release readiness must not be the first place these package suites execute. | |
| needs: contract | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - shard: server | |
| packages: "-p webcodex" | |
| - shard: runner | |
| packages: "-p webcodex-runner" | |
| - shard: workspace-crates | |
| packages: >- | |
| -p webcodex-admin | |
| -p webcodex-runner-config | |
| -p webcodex-core | |
| -p webcodex-cli | |
| -p webcodex-persistent-shell | |
| -p webcodex-sandbox | |
| -p webcodex-workspace | |
| -p webcodex-process | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-ci | |
| - name: Run ${{ matrix.shard }} Rust tests | |
| run: cargo test --locked ${{ matrix.packages }} | |
| test-linux-tooling: | |
| # Release/tooling checks are cheap relative to native platform builds and are | |
| # mandatory on every PR so release-prep failures are caught before merge. | |
| needs: contract | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-ci | |
| # The retained npm release-smoke tooling below invokes node/npm directly. | |
| # Frontend dependency installation and frontend-specific npm caching remain | |
| # contract-lane responsibilities and are intentionally not repeated here. | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Ensure Python tooling test dependencies | |
| run: | | |
| if ! command -v rg >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install --no-install-recommends -y ripgrep | |
| fi | |
| - name: Check complete workspace production/test targets | |
| run: cargo check --locked --workspace --all-targets | |
| - name: Test deterministic release contract and tooling | |
| run: bash scripts/release_check.sh --static-only | |
| # Exact main CI is the pre-tag source of truth for platform correctness. Keep | |
| # Linux arm64 cfg/target coverage here so release-readiness does not need a | |
| # duplicate release-profile build merely to prove the native architecture. | |
| test-linux-arm64: | |
| needs: contract | |
| if: >- | |
| github.event_name == 'push' || | |
| github.event.pull_request.user.login != github.repository_owner || | |
| contains(github.event.pull_request.labels.*.name, 'run-ci') | |
| runs-on: ubuntu-24.04-arm | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: linux-arm64-ci | |
| - name: Verify native Linux arm64 production targets compile | |
| run: | | |
| test "$(uname -m)" = aarch64 | |
| rust_host="$(rustc -vV | sed -n 's/^host: //p')" | |
| test "$rust_host" = aarch64-unknown-linux-gnu | |
| cargo check --locked -p webcodex -p webcodex-cli -p webcodex-runner | |
| test: | |
| needs: [contract, test-linux-rust, test-linux-tooling] | |
| # Preserve the historical aggregate status check and always evaluate upstream | |
| # results so a failed or unexpectedly skipped Linux lane cannot disappear. | |
| if: always() | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Require successful Linux lanes | |
| env: | |
| CONTRACT_RESULT: ${{ needs.contract.result }} | |
| RUST_RESULT: ${{ needs.test-linux-rust.result }} | |
| TOOLING_RESULT: ${{ needs.test-linux-tooling.result }} | |
| run: | | |
| echo "contract=$CONTRACT_RESULT rust=$RUST_RESULT tooling=$TOOLING_RESULT" | |
| if [ "$CONTRACT_RESULT" != success ] || \ | |
| [ "$RUST_RESULT" != success ] || \ | |
| [ "$TOOLING_RESULT" != success ]; then | |
| echo "required Linux CI lane did not succeed" >&2 | |
| exit 1 | |
| fi | |
| test-macos: | |
| needs: contract | |
| if: >- | |
| github.event_name == 'push' || | |
| github.event.pull_request.user.login != github.repository_owner || | |
| contains(github.event.pull_request.labels.*.name, 'run-ci') | |
| # Native macOS gates for both published architectures plus the Runner's | |
| # detached ownership/restart suites. Keep these ahead of immutable tagging. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: darwin-arm64 | |
| runner: macos-14 | |
| host_arch: arm64 | |
| rust_host: aarch64-apple-darwin | |
| - platform: darwin-x64 | |
| runner: macos-15-intel | |
| host_arch: x86_64 | |
| rust_host: x86_64-apple-darwin | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: macos-ci-${{ matrix.platform }} | |
| - name: Verify native macOS host | |
| env: | |
| EXPECTED_HOST_ARCH: ${{ matrix.host_arch }} | |
| EXPECTED_RUST_HOST: ${{ matrix.rust_host }} | |
| run: | | |
| test "$(uname -m)" = "$EXPECTED_HOST_ARCH" | |
| rust_host="$(rustc -vV | sed -n 's/^host: //p')" | |
| test "$rust_host" = "$EXPECTED_RUST_HOST" | |
| - name: Check macOS release production surfaces | |
| run: cargo check --locked -p webcodex -p webcodex-cli -p webcodex-runner | |
| - name: Run native macOS Runner tests | |
| run: cargo test --locked -p webcodex-runner | |
| # Keep Windows process-heavy suites isolated on separate hosted VMs. The | |
| # webcodex-runner lane remains test-function-serial because its real | |
| # PowerShell/process-tree fixtures can starve each other on hosted Windows. | |
| # Core/library and packaging coverage can run independently in parallel. | |
| test-windows-core: | |
| needs: contract | |
| if: >- | |
| github.event_name == 'push' || | |
| github.event.pull_request.user.login != github.repository_owner || | |
| contains(github.event.pull_request.labels.*.name, 'run-ci') | |
| runs-on: windows-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: windows-core-ci | |
| - name: Configure PowerShell 7 persistent-shell tests | |
| shell: pwsh | |
| run: | | |
| $pwsh = (Get-Command pwsh -ErrorAction Stop).Source | |
| "WEBCODEX_TEST_PWSH=$pwsh" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| - name: Run Windows persistent-shell tests (PowerShell 5.1 + PowerShell 7) | |
| run: cargo test --locked -p webcodex-persistent-shell | |
| - name: Run Windows library and CLI tests | |
| run: cargo test --locked -p webcodex-runner-config -p webcodex-process -p webcodex-cli | |
| test-windows-runner: | |
| needs: contract | |
| if: >- | |
| github.event_name == 'push' || | |
| github.event.pull_request.user.login != github.repository_owner || | |
| contains(github.event.pull_request.labels.*.name, 'run-ci') | |
| runs-on: windows-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: windows-runner-ci | |
| - name: Run Windows Runner tests | |
| # The Runner suite starts many real PowerShell/process-tree fixtures. On | |
| # hosted Windows, parallel test functions can starve process startup long | |
| # enough to trip intentionally tight command timeouts. Serialize only | |
| # the test functions; concurrency exercised inside each test is unchanged. | |
| run: cargo test --locked -p webcodex-runner -- --test-threads=1 | |
| test-windows-package: | |
| needs: contract | |
| if: >- | |
| github.event_name == 'push' || | |
| github.event.pull_request.user.login != github.repository_owner || | |
| contains(github.event.pull_request.labels.*.name, 'run-ci') | |
| runs-on: windows-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: windows-package-ci | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Test npm installer and release manifest natively | |
| run: npm --prefix npm/webcodex test | |
| - name: Windows artifact to npm install smoke | |
| # Builds the three Windows binaries, packages the win32-x64 artifact | |
| # with the native PowerShell script, installs it through the npm | |
| # installer into a temporary prefix, and verifies the wrapper plus | |
| # --version/--help and the failure-preserves-old-binaries path. Never | |
| # touches the npm registry. | |
| shell: pwsh | |
| run: powershell -NoProfile -ExecutionPolicy Bypass -File scripts/npm_install_windows_smoke.ps1 | |
| # The x64 Windows lanes above exercise full process/package behavior. Keep one | |
| # native ARM64 compile gate on exact main so the release workflow is not the | |
| # first place target-specific Windows code is compiled. | |
| test-windows-arm64: | |
| needs: contract | |
| if: >- | |
| github.event_name == 'push' || | |
| github.event.pull_request.user.login != github.repository_owner || | |
| contains(github.event.pull_request.labels.*.name, 'run-ci') | |
| runs-on: windows-11-arm | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: windows-arm64-ci | |
| - name: Verify native Windows ARM64 production targets compile | |
| shell: pwsh | |
| run: | | |
| if ($env:PROCESSOR_ARCHITECTURE -ne 'ARM64') { throw "Expected native Windows ARM64 host" } | |
| $hostLine = rustc -vV | Select-String '^host: ' | |
| if ($hostLine.Line -ne 'host: aarch64-pc-windows-msvc') { throw "Unexpected Rust host: $($hostLine.Line)" } | |
| cargo check --locked -p webcodex -p webcodex-cli -p webcodex-runner | |
| if ($LASTEXITCODE -ne 0) { throw "cargo check failed with exit code $LASTEXITCODE" } | |
| test-windows: | |
| needs: [contract, test-windows-core, test-windows-runner, test-windows-package, test-windows-arm64] | |
| # Preserve the historical required Windows status while moving the expensive | |
| # work into parallel VMs. Eligible heavy runs inspect every lane even after a | |
| # failure so branch protection cannot see a false-success aggregate. | |
| if: >- | |
| always() && | |
| ( | |
| github.event_name == 'push' || | |
| github.event.pull_request.user.login != github.repository_owner || | |
| contains(github.event.pull_request.labels.*.name, 'run-ci') | |
| ) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Require successful Windows lanes | |
| env: | |
| CONTRACT_RESULT: ${{ needs.contract.result }} | |
| CORE_RESULT: ${{ needs.test-windows-core.result }} | |
| RUNNER_RESULT: ${{ needs.test-windows-runner.result }} | |
| PACKAGE_RESULT: ${{ needs.test-windows-package.result }} | |
| ARM64_RESULT: ${{ needs.test-windows-arm64.result }} | |
| run: | | |
| echo "contract=$CONTRACT_RESULT core=$CORE_RESULT runner=$RUNNER_RESULT package=$PACKAGE_RESULT arm64=$ARM64_RESULT" | |
| if [ "$CONTRACT_RESULT" != success ] || \ | |
| [ "$CORE_RESULT" != success ] || \ | |
| [ "$RUNNER_RESULT" != success ] || \ | |
| [ "$PACKAGE_RESULT" != success ] || \ | |
| [ "$ARM64_RESULT" != success ]; then | |
| echo "required Windows CI lane did not succeed" >&2 | |
| exit 1 | |
| fi |