feat(dashboard): box table cleanup — drop region, tighten density, full image refs in onboarding #1676
Workflow file for this run
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
| # Run unit tests across all SDKs. | |
| # | |
| # This workflow runs unit tests only (no VM/integration tests). | |
| # GitHub runners do not support nested virtualization, so we cannot run | |
| # tests that require actual VMs. | |
| # | |
| # Test coverage: | |
| # - Rust: cargo-nextest (unit tests only, with llvm-cov coverage) | |
| # - Python: pytest with -m "not integration" | |
| # - Node.js: vitest (all tests are unit tests) | |
| name: Test | |
| on: | |
| merge_group: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'src/boxlite/**' | |
| - 'src/shared/**' | |
| - 'src/cli/**' | |
| - 'src/guest/**' | |
| - 'sdks/**' | |
| - '**/Cargo.toml' | |
| - 'Cargo.lock' | |
| - '.github/workflows/test.yml' | |
| - '.github/workflows/config.yml' | |
| # No path filter on pull_request: the `Test (conclusion)` job is a required | |
| # status check, so this workflow must run on EVERY PR and report it. A | |
| # path-skipped workflow leaves the required check stuck "Pending" → PR blocked. | |
| # Per-suite filtering still happens in the `changes` job (jobs skip when | |
| # unaffected); the conclusion job reports success-or-skipped. | |
| pull_request: | |
| branches: [main] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| CARGO_INCREMENTAL: '0' | |
| jobs: | |
| # Load shared configuration | |
| config: | |
| uses: ./.github/workflows/config.yml | |
| # Detect which files changed to conditionally run tests | |
| changes: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: read | |
| outputs: | |
| rust: ${{ steps.filter.outputs.rust }} | |
| cli: ${{ steps.filter.outputs.boxlite_cli }} | |
| python: ${{ steps.filter.outputs.python }} | |
| node: ${{ steps.filter.outputs.node }} | |
| go: ${{ steps.filter.outputs.go }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dorny/paths-filter@v4 | |
| id: filter | |
| with: | |
| # In a merge queue, diff against the merge-group base/head (no PR base | |
| # exists). Empty on pull_request/push, where paths-filter ignores them. | |
| base: ${{ github.event_name == 'merge_group' && github.event.merge_group.base_sha || '' }} | |
| ref: ${{ github.event_name == 'merge_group' && github.event.merge_group.head_sha || '' }} | |
| filters: | | |
| rust: | |
| - 'src/boxlite/**' | |
| - 'src/shared/**' | |
| - 'src/guest/**' | |
| - '**/Cargo.toml' | |
| - 'Cargo.lock' | |
| cli: | |
| - 'src/cli/**' | |
| python: | |
| - 'sdks/python/**' | |
| node: | |
| - 'sdks/node/**' | |
| go: | |
| - 'sdks/go/**' | |
| # Rust unit tests (boxlite-shared only - boxlite requires native libs not available in CI) | |
| rust: | |
| name: Rust Tests (${{ matrix.platform.target }}) | |
| needs: [config, changes] | |
| if: ${{ needs.changes.outputs.rust == 'true' }} | |
| runs-on: ${{ matrix.platform.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: ${{ fromJson(needs.config.outputs.platforms) }} | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: ${{ needs.config.outputs.rust-toolchain }} | |
| - name: Install system dependencies (Linux) | |
| if: runner.os == 'Linux' | |
| run: sudo apt-get update && sudo apt-get install -y protobuf-compiler | |
| - name: Install system dependencies (macOS) | |
| if: runner.os == 'macOS' | |
| run: brew install protobuf | |
| - name: Install cargo-nextest | |
| uses: taiki-e/install-action@nextest | |
| - name: Install cargo-llvm-cov | |
| uses: taiki-e/install-action@cargo-llvm-cov | |
| - name: Run Rust unit tests with coverage | |
| # Only test boxlite-shared - boxlite requires libkrun/libgvproxy not available in CI | |
| run: cargo llvm-cov nextest -p boxlite-shared --lib --profile ci --lcov --output-path lcov.info | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| file: lcov.info | |
| flags: rust-shared | |
| use_oidc: true | |
| fail_ci_if_error: false | |
| # cli unit tests (integration tests in tests/ are ignored - require VM) | |
| cli: | |
| name: CLI Unit Tests (${{ matrix.platform.target }}) | |
| needs: [config, changes] | |
| if: ${{ needs.changes.outputs.cli == 'true' }} | |
| runs-on: ${{ matrix.platform.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: ${{ fromJson(needs.config.outputs.platforms) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: ${{ needs.config.outputs.rust-toolchain }} | |
| - name: Install system dependencies (Linux) | |
| if: runner.os == 'Linux' | |
| run: sudo apt-get update && sudo apt-get install -y protobuf-compiler | |
| - name: Install system dependencies (macOS) | |
| if: runner.os == 'macOS' | |
| run: brew install protobuf | |
| - name: Install cargo-nextest | |
| uses: taiki-e/install-action@nextest | |
| - name: Setup sccache | |
| uses: mozilla-actions/sccache-action@v0.0.9 | |
| continue-on-error: true | |
| - name: Export GHA cache env vars | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || ''); | |
| core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); | |
| core.exportVariable('ACTIONS_CACHE_SERVICE_V2', process.env.ACTIONS_CACHE_SERVICE_V2 || ''); | |
| - name: Run boxlite-cli unit tests | |
| # Only run tests in src/ (name contains "::tests::"); skip integration tests in tests/ (require VM) | |
| env: | |
| BOXLITE_DEPS_STUB: "1" | |
| run: cargo nextest run -p boxlite-cli --profile ci -E 'test(::tests::)' | |
| # Python SDK unit tests | |
| python: | |
| name: Python Tests (${{ matrix.platform.target }} / Python ${{ matrix.python-version }}) | |
| needs: [config, changes] | |
| if: ${{ needs.changes.outputs.python == 'true' }} | |
| runs-on: ${{ matrix.platform.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: ${{ fromJson(needs.config.outputs.platforms) }} | |
| python-version: ${{ fromJson(needs.config.outputs.python-versions) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install test dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pytest pytest-asyncio | |
| - name: Run Python unit tests | |
| working-directory: sdks/python | |
| run: python -m pytest tests/ -v -m "not integration" | |
| # Node.js SDK unit tests | |
| node: | |
| name: Node.js Tests (${{ matrix.platform.target }} / Node ${{ matrix.node-version }}) | |
| needs: [config, changes] | |
| if: ${{ needs.changes.outputs.node == 'true' }} | |
| runs-on: ${{ matrix.platform.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: ${{ fromJson(needs.config.outputs.platforms) }} | |
| node-version: ${{ fromJson(needs.config.outputs.node-versions) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| - name: Install dependencies | |
| working-directory: sdks/node | |
| run: npm install | |
| - name: Run Node.js unit tests | |
| working-directory: sdks/node | |
| run: npm run test | |
| # Go SDK unit tests | |
| go: | |
| name: Go Tests (${{ matrix.platform.target }}) | |
| needs: [config, changes] | |
| if: ${{ needs.changes.outputs.go == 'true' }} | |
| runs-on: ${{ matrix.platform.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: ${{ fromJson(needs.config.outputs.platforms) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.24' | |
| - name: Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: ${{ needs.config.outputs.rust-toolchain }} | |
| - name: Install build dependencies | |
| run: make setup:build | |
| - name: Setup sccache | |
| uses: mozilla-actions/sccache-action@v0.0.9 | |
| continue-on-error: true | |
| - name: Export GHA cache env vars | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || ''); | |
| core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); | |
| core.exportVariable('ACTIONS_CACHE_SERVICE_V2', process.env.ACTIONS_CACHE_SERVICE_V2 || ''); | |
| - name: Run Go unit tests | |
| run: make test:unit:go | |
| # Single required status check for branch protection / merge queue. | |
| # Passes only if every job above succeeded or was skipped (path-filtered). | |
| # `if: !cancelled()` is required: without it a failed dependency would skip | |
| # this job, and GitHub treats a skipped required check as success. | |
| # NOTE: keep `needs` in sync with the jobs above when adding/removing jobs. | |
| test-conclusion: | |
| name: Test (conclusion) | |
| needs: [config, changes, rust, cli, python, node, go] | |
| if: ${{ !cancelled() }} | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| steps: | |
| - name: All test jobs passed or were skipped | |
| run: | | |
| jq -C <<< '${{ toJSON(needs) }}' | |
| jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJSON(needs) }}' |