Address Copilot review on the e2e suite (#984 follow-up) #57
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: E2E | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| branches: [master] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| e2e: | |
| name: 'Playwright (${{ matrix.os }})' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| runs-on: ${{ matrix.os }} | |
| # Bound the job so a stuck Electron launch/close fails fast instead of | |
| # tying up a runner; this suite specifically guards shutdown hangs. | |
| timeout-minutes: 15 | |
| env: | |
| # Only Electron is launched here, never Playwright's bundled browsers, so | |
| # skip their download during yarn install (faster, fewer network flakes). | |
| PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' | |
| # electron's postinstall (extract-zip) intermittently drops files from dist | |
| # on CI runners, so skip it and install the binary deterministically below. | |
| ELECTRON_SKIP_BINARY_DOWNLOAD: '1' | |
| steps: | |
| - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 | |
| - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 | |
| with: | |
| # Match the Node that the target Electron bundles (Electron 42 -> Node | |
| # 24); do not run ahead of it. Node 26 broke Electron's install tooling. | |
| node-version: '24.x' | |
| cache: 'yarn' | |
| - run: yarn install --frozen-lockfile | |
| # Install the Electron binary deterministically instead of relying on the | |
| # flaky extract-zip postinstall. Resolve the cached zip with @electron/get | |
| # (electron's own download dep, same call on every OS) and extract it with | |
| # the system tool: macOS needs ditto to keep the Electron Framework | |
| # symlinks that plain unzip mangles; Linux uses unzip. Then point path.txt | |
| # at the binary and confirm require('electron') resolves. | |
| - name: Install the Electron binary | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| zip=$(node -e "const {downloadArtifact}=require('@electron/get');const {version}=require('electron/package.json');downloadArtifact({version,artifactName:'electron'}).then(p=>process.stdout.write(p)).catch(e=>{console.error(e);process.exit(1)})") | |
| dist=node_modules/electron/dist | |
| rm -rf "$dist" && mkdir -p "$dist" | |
| if [ "$RUNNER_OS" = "macOS" ]; then | |
| ditto -x -k "$zip" "$dist" | |
| printf 'Electron.app/Contents/MacOS/Electron' > node_modules/electron/path.txt | |
| test -f "$dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Electron Framework" | |
| test -x "$dist/Electron.app/Contents/MacOS/Electron" | |
| else | |
| unzip -q -o "$zip" -d "$dist" | |
| printf 'electron' > node_modules/electron/path.txt | |
| test -x "$dist/electron" | |
| fi | |
| node -e "console.log('resolved electron:', require('electron'))" | |
| - run: yarn build | |
| # Electron needs system libraries; xvfb provides a display on the headless | |
| # runner. The app launches up to four windows, so a real display beats | |
| # --headless here. Both are Linux-only: macOS runners have a display and do | |
| # not use this apt-based dependency installer. | |
| - if: matrix.os == 'ubuntu-latest' | |
| run: npx playwright install-deps | |
| # A minimal Python env with jupyterlab so the env-backed tests run (a venv | |
| # + pip is lighter than a full conda env for a smoke). The seeded | |
| # app-data.json points the app at this interpreter. | |
| - name: Provision a Python env for the env-backed e2e | |
| run: | | |
| set -euo pipefail | |
| # Install the same jupyterlab the app bundles, read from the env spec so | |
| # this tracks a version bump instead of drifting. Fail loudly if the | |
| # pin format changes rather than silently installing latest. | |
| ver=$(awk '$1=="-" && $2=="jupyterlab" {print $3}' env_installer/jlab_server.yaml) | |
| [[ "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "unexpected jupyterlab pin '$ver' in jlab_server.yaml (want exact x.y.z)"; exit 1; } | |
| python3 -m venv "$RUNNER_TEMP/jlab-venv" | |
| "$RUNNER_TEMP/jlab-venv/bin/pip" install --quiet "jupyterlab==$ver" | |
| echo "JLAB_TEST_PYTHON_PATH=$RUNNER_TEMP/jlab-venv/bin/python" >> "$GITHUB_ENV" | |
| # xvfb is Linux-only; on macOS the runner has a real display, so run the | |
| # suite directly. Same yarn test:e2e command on both legs. | |
| - name: Run the e2e suite | |
| run: | | |
| if [ "$RUNNER_OS" = "Linux" ]; then | |
| xvfb-run -a yarn test:e2e | |
| else | |
| yarn test:e2e | |
| fi | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: playwright-report-${{ matrix.os }} | |
| path: | | |
| playwright-report/ | |
| test-results/ | |
| retention-days: 14 |