fix(runtimed): ephemeral notebook review cleanups #4360
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
| name: Build | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| changes: | |
| name: Detect source changes | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| outputs: | |
| source_changed: ${{ steps.filter.outputs.source }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check changed paths | |
| id: filter | |
| uses: dorny/paths-filter@v3 | |
| with: | |
| filters: | | |
| source: | |
| - ".github/workflows/**" | |
| - "apps/**" | |
| - "bin/**" | |
| - "crates/**" | |
| - "e2e/**" | |
| - "!e2e/*.md" | |
| - "python/**" | |
| - "scripts/**" | |
| - "src/**" | |
| - "Cargo.toml" | |
| - "Cargo.lock" | |
| - "rust-toolchain.toml" | |
| - "package.json" | |
| - "package-lock.json" | |
| - "pnpm-lock.yaml" | |
| - "pnpm-workspace.yaml" | |
| - "biome.json" | |
| - "components.json" | |
| - "tailwind.config.js" | |
| - "tsconfig.json" | |
| - "vitest.config.ts" | |
| lint: | |
| name: Lint & Format | |
| needs: [changes] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install rust | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - name: Check Rust formatting | |
| run: cargo fmt --check | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| - name: Enable corepack | |
| run: corepack enable | |
| - name: Install JS dependencies | |
| run: pnpm install | |
| - name: Check Biome (format + lint + imports) | |
| run: npx @biomejs/biome check apps/notebook/src/ e2e/ | |
| - name: Check MCP App renderer plugins are up to date | |
| run: | | |
| pnpm --filter nteract-mcp-app run build:plugins | |
| git diff --exit-code crates/runt-mcp/assets/plugins/ || { | |
| echo "::error::MCP App renderer plugins are stale. Run 'cd apps/mcp-app && pnpm build:plugins' and commit the changes." | |
| exit 1 | |
| } | |
| - name: Lint GitHub Actions workflows | |
| uses: raven-actions/actionlint@v2 | |
| with: | |
| shellcheck: false | |
| windows-clippy: | |
| name: Windows (clippy) | |
| needs: [changes] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Install rust | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: windows-cross | |
| - name: Install mingw-w64 and add Windows GNU target | |
| run: | | |
| sudo apt-get update -qq | |
| sudo apt-get install -y gcc-mingw-w64-x86-64 nasm | |
| rustup target add x86_64-pc-windows-gnu | |
| # Build MCP output widget HTML (needed by runt-mcp's include_str!) | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm --filter nteract-mcp-app install && pnpm --filter nteract-mcp-app run build | |
| - name: Clippy (Windows cross-check) | |
| run: cargo clippy --target x86_64-pc-windows-gnu --workspace --exclude notebook --exclude runtimed-wasm --exclude runtimed-py --all-targets -- -D warnings | |
| wasm-deno: | |
| name: WASM + Deno Tests | |
| needs: [changes] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install rust | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: ubuntu-wasm | |
| - name: Install wasm-pack | |
| run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh | |
| - name: Build runtimed-wasm | |
| run: wasm-pack build crates/runtimed-wasm --target web --out-dir ../../apps/notebook/src/wasm/runtimed-wasm | |
| - name: Check WASM bindings are up to date | |
| run: | | |
| git diff --exit-code -- apps/notebook/src/wasm/runtimed-wasm/ ':!*.wasm' || { | |
| echo "::error::Checked-in WASM bindings are stale. Run: wasm-pack build crates/runtimed-wasm --target web --out-dir ../../apps/notebook/src/wasm/runtimed-wasm" | |
| exit 1 | |
| } | |
| - name: Install Deno | |
| uses: denoland/setup-deno@v2 | |
| with: | |
| deno-version: "2.4" | |
| - name: Run runtimed-wasm Deno tests | |
| run: deno test --allow-read --allow-env --no-check crates/runtimed-wasm/tests/ | |
| build-ui: | |
| name: Build shared UI artifacts | |
| needs: [changes] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| - name: Enable corepack | |
| run: corepack enable | |
| - name: Set pnpm store directory | |
| run: pnpm config set store-dir ~/.pnpm-store | |
| - name: Cache pnpm store | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.pnpm-store | |
| key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| pnpm-store-${{ runner.os }}- | |
| - name: Install JS dependencies | |
| run: pnpm install | |
| - name: Build UIs | |
| run: | | |
| pnpm --dir apps/notebook build | |
| - name: Upload UI build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ui-build-dist | |
| path: | | |
| apps/notebook/dist/ | |
| retention-days: 1 | |
| js-tests: | |
| name: JS Tests & Benchmarks | |
| needs: [changes] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| - name: Enable corepack | |
| run: corepack enable | |
| - name: Set pnpm store directory | |
| run: pnpm config set store-dir ~/.pnpm-store | |
| - name: Cache pnpm store | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.pnpm-store | |
| key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| pnpm-store-${{ runner.os }}- | |
| - name: Install JS dependencies | |
| run: pnpm install | |
| - name: Run JS tests | |
| run: pnpm test:run | |
| - name: Run JS benchmarks | |
| run: pnpm vitest bench --run apps/notebook/src/lib/__tests__/ | |
| build-linux: | |
| name: Linux (release artifacts) | |
| needs: [changes, build-ui] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Download UI build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ui-build-dist | |
| path: apps/notebook/dist | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libxdo-dev | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Install rust | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: ubuntu-release | |
| # Build MCP output widget HTML (needed by runt-mcp's include_str!) | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm --filter nteract-mcp-app install && pnpm --filter nteract-mcp-app run build | |
| - name: Build external binaries | |
| shell: bash | |
| run: | | |
| cargo build --release -p runtimed -p runt-cli -p mcpb-runt | |
| TARGET=$(rustc --print host-tuple) | |
| mkdir -p crates/notebook/binaries | |
| if [[ "$RUNNER_OS" == "Windows" ]]; then | |
| cp target/release/runtimed.exe "crates/notebook/binaries/runtimed-$TARGET.exe" | |
| cp target/release/runt.exe "crates/notebook/binaries/runt-$TARGET.exe" | |
| cp target/release/mcpb-runt.exe "crates/notebook/binaries/mcpb-runt-$TARGET.exe" | |
| else | |
| cp target/release/runtimed "crates/notebook/binaries/runtimed-$TARGET" | |
| cp target/release/runt "crates/notebook/binaries/runt-$TARGET" | |
| cp target/release/mcpb-runt "crates/notebook/binaries/mcpb-runt-$TARGET" | |
| fi | |
| - name: Clippy (notebook crate) | |
| run: cargo clippy -p notebook --all-targets -- -D warnings | |
| - name: Install cargo-binstall | |
| run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash | |
| - name: Install tauri-cli | |
| run: cargo binstall tauri-cli --no-confirm --locked --force | |
| - name: Upload Linux Rust binaries | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-rust-binaries | |
| path: | | |
| target/release/runtimed | |
| target/release/runt | |
| target/release/mcpb-runt | |
| crates/notebook/binaries/runtimed-* | |
| crates/notebook/binaries/runt-* | |
| crates/notebook/binaries/mcpb-runt-* | |
| retention-days: 1 | |
| - name: Build Tauri E2E app | |
| run: cd crates/notebook && cargo tauri build --ci --no-bundle --features e2e-webdriver --config '{"build":{"beforeBuildCommand":""}}' | |
| - name: Stage E2E artifacts | |
| run: | | |
| mkdir -p target/release/binaries | |
| cp crates/notebook/binaries/runtimed-* target/release/binaries/ | |
| cp crates/notebook/binaries/runt-* target/release/binaries/ | |
| cp crates/notebook/binaries/mcpb-runt-* target/release/binaries/ | |
| - name: Upload E2E app | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-app-linux | |
| path: | | |
| target/release/notebook | |
| target/release/binaries/ | |
| retention-days: 1 | |
| - name: Test notebook crate | |
| run: cargo test -p notebook --verbose | |
| clippy-and-tests: | |
| name: Clippy & Tests (Linux) | |
| needs: [changes] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libxdo-dev | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Install rust | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: ubuntu-clippy | |
| # Build MCP output widget HTML (needed by runt-mcp's include_str!) | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm --filter nteract-mcp-app install && pnpm --filter nteract-mcp-app run build | |
| # Excludes: notebook (needs bundled binaries, checked in build-linux), | |
| # runtimed-wasm (needs wasm-pack, tested in wasm-deno), | |
| # runtimed-py (needs Python/maturin, tested in runtimed-py-integration). | |
| - name: Clippy | |
| run: cargo clippy --workspace --exclude notebook --exclude runtimed-wasm --exclude runtimed-py --all-targets -- -D warnings | |
| - name: Run tests | |
| run: cargo test --workspace --exclude notebook --exclude runtimed-wasm --exclude runtimed-py --verbose | |
| build: | |
| name: ${{ matrix.platform.name }} | |
| needs: [changes, build-ui] | |
| if: ${{ always() && (needs.changes.outputs.source_changed != 'true' || needs.build-ui.result == 'success') }} | |
| continue-on-error: ${{ matrix.platform.non_blocking }} | |
| runs-on: ${{ needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) && matrix.platform.runner || 'ubuntu-latest' }} | |
| strategy: | |
| matrix: | |
| platform: | |
| - name: macOS | |
| runner: macos-latest | |
| setup: echo "No extra deps needed on macOS" | |
| run_on_pr: false | |
| non_blocking: false | |
| - name: Windows | |
| runner: windows-latest | |
| setup: echo "No extra deps needed on Windows" | |
| run_on_pr: false | |
| non_blocking: true | |
| steps: | |
| - name: Skip non-source changes | |
| if: needs.changes.outputs.source_changed != 'true' | |
| run: echo "No source changes detected; skipping this platform leg." | |
| - name: Skip this platform on pull requests | |
| if: needs.changes.outputs.source_changed == 'true' && github.event_name == 'pull_request' && !matrix.platform.run_on_pr | |
| run: echo "Skipping this platform for pull_request events." | |
| - uses: actions/checkout@v6 | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| with: | |
| lfs: true | |
| - name: Download UI build artifacts | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ui-build-dist | |
| path: apps/notebook/dist | |
| - name: Install system dependencies | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| run: ${{ matrix.platform.setup }} | |
| - name: Install uv | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Install rust | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - uses: Swatinem/rust-cache@v2 | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| with: | |
| shared-key: ${{ matrix.platform.runner }} | |
| # Build MCP output widget HTML (needed by runt-mcp's include_str!) | |
| - uses: pnpm/action-setup@v4 | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| - uses: actions/setup-node@v4 | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm --filter nteract-mcp-app install && pnpm --filter nteract-mcp-app run build | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| - name: Build external binaries | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| shell: bash | |
| run: | | |
| cargo build --release -p runtimed -p runt-cli -p mcpb-runt | |
| TARGET=$(rustc --print host-tuple) | |
| mkdir -p crates/notebook/binaries | |
| if [[ "$RUNNER_OS" == "Windows" ]]; then | |
| cp target/release/runtimed.exe "crates/notebook/binaries/runtimed-$TARGET.exe" | |
| cp target/release/runt.exe "crates/notebook/binaries/runt-$TARGET.exe" | |
| cp target/release/mcpb-runt.exe "crates/notebook/binaries/mcpb-runt-$TARGET.exe" | |
| else | |
| cp target/release/runtimed "crates/notebook/binaries/runtimed-$TARGET" | |
| cp target/release/runt "crates/notebook/binaries/runt-$TARGET" | |
| cp target/release/mcpb-runt "crates/notebook/binaries/mcpb-runt-$TARGET" | |
| fi | |
| - name: Clippy | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| run: cargo clippy --workspace --all-targets -- -D warnings | |
| - name: Build | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| run: cargo build --release | |
| - name: Run tests | |
| if: needs.changes.outputs.source_changed == 'true' && (github.event_name != 'pull_request' || matrix.platform.run_on_pr) | |
| run: cargo test --workspace --verbose | |
| # Build Tauri app once and share with E2E shards | |
| # E2E smoke test - verifies basic app functionality | |
| e2e: | |
| name: "E2E: ${{ matrix.name }}" | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| needs: [changes, build-linux] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: Smoke | |
| spec: "" | |
| notebook: "" | |
| uv_pool: 3 | |
| conda_pool: 0 | |
| timeout: 12 | |
| - name: UI (Cell Visibility) | |
| spec: "e2e/specs/cell-visibility.spec.js" | |
| notebook: "crates/notebook/fixtures/audit-test/14-cell-visibility.ipynb" | |
| uv_pool: 0 | |
| conda_pool: 0 | |
| timeout: 5 | |
| - name: UV Prewarmed | |
| spec: "e2e/specs/prewarmed-uv.spec.js" | |
| notebook: "crates/notebook/fixtures/audit-test/1-vanilla.ipynb" | |
| uv_pool: 3 | |
| conda_pool: 0 | |
| timeout: 12 | |
| - name: Deno | |
| spec: "e2e/specs/deno.spec.js" | |
| notebook: "crates/notebook/fixtures/audit-test/10-deno.ipynb" | |
| uv_pool: 0 | |
| conda_pool: 0 | |
| timeout: 8 | |
| # UV/Conda Inline and Trust Dialog: disabled — trust dialog | |
| # never appears in CI despite banner click and execute fallbacks. | |
| # The daemon correctly reads untrusted status from the fixture file | |
| # (verify_trust_from_file), but the frontend trust flow doesn't | |
| # complete. Needs CI log access to diagnose. See #1275. | |
| # - name: UV Inline Deps | |
| # spec: "e2e/specs/uv-inline.spec.js" | |
| # notebook: "crates/notebook/fixtures/audit-test/2-uv-inline.ipynb" | |
| # uv_pool: 3 | |
| # conda_pool: 0 | |
| # timeout: 12 | |
| # - name: Conda Inline Deps | |
| # spec: "e2e/specs/conda-inline.spec.js" | |
| # notebook: "crates/notebook/fixtures/audit-test/3-conda-inline.ipynb" | |
| # uv_pool: 0 | |
| # conda_pool: 3 | |
| # timeout: 15 | |
| # - name: Trust Dialog | |
| # spec: "e2e/specs/trust-dialog-dismiss.spec.js" | |
| # notebook: "crates/notebook/fixtures/audit-test/2-uv-inline.ipynb" | |
| # uv_pool: 3 | |
| # conda_pool: 0 | |
| # timeout: 12 | |
| - name: UV Pyproject | |
| spec: "e2e/specs/uv-pyproject.spec.js" | |
| notebook: "crates/notebook/fixtures/audit-test/pyproject-project/5-pyproject.ipynb" | |
| uv_pool: 3 | |
| conda_pool: 0 | |
| timeout: 12 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libgtk-3-dev \ | |
| libwebkit2gtk-4.1-dev \ | |
| libxdo-dev \ | |
| xvfb \ | |
| webkit2gtk-driver | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| - name: Enable corepack | |
| run: corepack enable | |
| - name: Set pnpm store directory | |
| run: pnpm config set store-dir ~/.pnpm-store | |
| - name: Cache pnpm store | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.pnpm-store | |
| key: pnpm-store-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| pnpm-store-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Download E2E artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: e2e-app-linux | |
| path: ./target/release | |
| - name: Make binaries executable | |
| run: | | |
| chmod +x target/release/notebook | |
| chmod +x target/release/binaries/* | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Run E2E test | |
| timeout-minutes: ${{ matrix.timeout }} | |
| run: | | |
| set -o pipefail | |
| mkdir -p e2e-logs | |
| # Pre-seed settings to skip onboarding | |
| mkdir -p ~/.config/nteract-nightly | |
| echo '{"onboarding_completed": true}' > ~/.config/nteract-nightly/settings.json | |
| # Start Xvfb (headless display for WebKitGTK) | |
| Xvfb :99 -screen 0 1920x1080x24 2>/dev/null & | |
| export DISPLAY=:99 | |
| sleep 2 | |
| # Start daemon with pool configuration. | |
| # Unset UV_CACHE_DIR/UV_PYTHON_INSTALL_DIR so the daemon uses its own | |
| # env paths (runtimed-uv-*) instead of the CI uv action's temp cache. | |
| TARGET=$(ls target/release/binaries/ | grep runtimed | head -1) | |
| env -u UV_CACHE_DIR -u UV_PYTHON_INSTALL_DIR \ | |
| RUNTIMED_WORKSPACE_PATH="${GITHUB_WORKSPACE}" \ | |
| ./target/release/binaries/$TARGET --dev run \ | |
| --uv-pool-size ${{ matrix.uv_pool }} --conda-pool-size ${{ matrix.conda_pool }} \ | |
| > e2e-logs/daemon.log 2>&1 & | |
| DAEMON_PID=$! | |
| # Wait for pool warm-up (skip for tests with no pool) | |
| if [ "${{ matrix.uv_pool }}" = "0" ] && [ "${{ matrix.conda_pool }}" = "0" ]; then | |
| echo "No pool to warm, sleeping 5s..." | |
| sleep 5 | |
| else | |
| echo "Waiting for daemon pool to warm (90s on cold CI)..." | |
| sleep 90 | |
| fi | |
| # Start the app (with notebook if specified) | |
| if [ -n "${{ matrix.notebook }}" ]; then | |
| env -u UV_CACHE_DIR -u UV_PYTHON_INSTALL_DIR \ | |
| RUNTIMED_WORKSPACE_PATH="${GITHUB_WORKSPACE}" \ | |
| RUST_LOG=info,notebook=debug \ | |
| ./target/release/notebook "${{ matrix.notebook }}" > e2e-logs/app.log 2>&1 & | |
| else | |
| env -u UV_CACHE_DIR -u UV_PYTHON_INSTALL_DIR \ | |
| RUNTIMED_WORKSPACE_PATH="${GITHUB_WORKSPACE}" \ | |
| RUST_LOG=info,notebook=debug \ | |
| ./target/release/notebook > e2e-logs/app.log 2>&1 & | |
| fi | |
| APP_PID=$! | |
| # Wait for WebDriver server | |
| for i in $(seq 1 60); do | |
| curl -s http://localhost:4445/status >/dev/null 2>&1 && break | |
| kill -0 $APP_PID 2>/dev/null || { echo "App died"; cat e2e-logs/app.log; exit 1; } | |
| sleep 1 | |
| done | |
| echo "WebDriver ready" | |
| # Run tests | |
| if [ -n "${{ matrix.spec }}" ]; then | |
| WEBDRIVER_PORT=4445 E2E_SPEC="${{ matrix.spec }}" \ | |
| pnpm test:e2e 2>&1 | tee e2e-logs/test-output.log | |
| else | |
| WEBDRIVER_PORT=4445 pnpm test:e2e 2>&1 | tee e2e-logs/test-output.log | |
| fi | |
| EXIT=$? | |
| # Cleanup | |
| kill $APP_PID $DAEMON_PID 2>/dev/null || true | |
| exit $EXIT | |
| env: | |
| NO_AT_BRIDGE: 1 | |
| LIBGL_ALWAYS_SOFTWARE: 1 | |
| WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS: 1 | |
| WEBKIT_DISABLE_COMPOSITING_MODE: 1 | |
| - name: Collect daemon logs | |
| if: always() | |
| run: | | |
| mkdir -p e2e-logs | |
| # Find and copy daemon logs from worktree cache | |
| find ~/.cache/runt/worktrees -name "runtimed.log" -exec cp {} e2e-logs/ \; 2>/dev/null || true | |
| find ~/.cache/runt/worktrees -name "daemon.json" -exec cp {} e2e-logs/ \; 2>/dev/null || true | |
| # Also capture any app logs | |
| ls -la ~/.cache/runt/worktrees/*/ 2>/dev/null || true | |
| echo "=== Daemon log ===" && cat e2e-logs/runtimed.log 2>/dev/null || echo "No daemon log found" | |
| - name: Upload failure screenshots | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-screenshots-${{ matrix.name }} | |
| path: e2e-screenshots/failures/ | |
| retention-days: 7 | |
| - name: Upload daemon logs | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: e2e-logs-${{ matrix.name }} | |
| path: e2e-logs/ | |
| retention-days: 7 | |
| # Python daemon integration tests — builds its own runtimed binary | |
| runtimed-py-integration: | |
| name: runtimed-py Integration Tests | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| needs: [changes] | |
| if: needs.changes.outputs.source_changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Install rust | |
| uses: dsherret/rust-toolchain-file@v1 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: ubuntu-py-integration | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Install pixi | |
| uses: prefix-dev/setup-pixi@v0.9.4 | |
| with: | |
| run-install: false | |
| - name: Build runtimed binary | |
| run: cargo build --release -p runtimed | |
| - name: Build runtimed-py | |
| working-directory: python/runtimed | |
| run: uv run maturin develop --manifest-path ../../crates/runtimed-py/Cargo.toml | |
| - name: Run integration tests | |
| timeout-minutes: 30 | |
| working-directory: python/runtimed | |
| run: | | |
| set -o pipefail | |
| mkdir -p integration-logs | |
| # Set environment for CI mode | |
| export RUNTIMED_INTEGRATION_TEST=1 | |
| export RUNTIMED_BINARY="${GITHUB_WORKSPACE}/target/release/runtimed" | |
| export RUNTIMED_LOG_LEVEL=debug | |
| export RUNTIMED_WORKSPACE_PATH="${GITHUB_WORKSPACE}" | |
| # Run tests (daemon is spawned by the test fixture) | |
| uv run pytest tests/test_daemon_integration.py -v --tb=short 2>&1 | tee integration-logs/test-output.log || FAIL=1 | |
| exit ${FAIL:-0} | |
| - name: Upload test logs | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: runtimed-py-integration-logs | |
| path: python/runtimed/integration-logs/ | |
| retention-days: 7 |