name: Ecosystem E2E # Installs real-world JS stacks (Next.js, Vite, …) with both the pnpm CLI # and pacquet, under both the default isolated layout and the global virtual # store, then builds and serves each app. The binary axis catches pnpm↔pacquet # parity gaps; the layout axis catches breakage introduced by the global # virtual store. Runs on a daily cron rather than per-PR — the installs are # slow and track upstream framework releases, so a red cell is investigated, # not treated as a merge blocker. # # The webcontainer job installs a small project with the pnpm bundle inside a # StackBlitz WebContainer, whose in-browser Node.js differs from Node.js in its # `fs` errors and `node:sqlite`. It depends on StackBlitz's servers, which is # another reason this runs on a cron. permissions: contents: read on: workflow_dispatch: schedule: - cron: '0 6 * * *' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # Compile pacquet, the harness, and the pnpm bundle once, then share them # with every stack job — building them per stack would repeat the same # multi-minute Rust and bundle builds across the whole matrix. build: if: github.repository == 'pnpm/pnpm' # Only run on the main repository, not forks name: Ecosystem E2E / Build runs-on: blacksmith-8vcpu-ubuntu-2404 timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Setup Rust toolchain uses: $/.github/actions/rustup - name: Install pnpm uses: pnpm/setup@a0881977cd8ea73b1ed212236c99ca10dcc80cf4 # v3.1.1 - name: Build pnpm and the harness run: cargo build --release --bin pnpm --bin ecosystem-e2e - name: Build the pnpm CLI bundle run: | pnpm install --frozen-lockfile pnpm --filter 'pnpm' run compile - name: Upload build outputs uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: ecosystem-e2e-build path: | target/release/pnpm target/release/ecosystem-e2e pnpm11/pnpm/dist retention-days: 1 if-no-files-found: error ecosystem-e2e: if: github.repository == 'pnpm/pnpm' # Only run on the main repository, not forks name: Ecosystem E2E / ${{ matrix.stack }} needs: build runs-on: blacksmith-8vcpu-ubuntu-2404 # Bound the blast radius: a hung build or serve subprocess can't pin a # runner indefinitely. timeout-minutes: 60 strategy: fail-fast: false matrix: # One stack per job so a slow or flaky stack can't mask the others # and each gets its own log artifact. stack: [next, vite-react, angular, astro, sveltekit, nuxt, react-router] steps: # The pnpm shim launches the repo's committed `pnpm11/pnpm/bin/pnpm.cjs`, so the # checkout is still needed alongside the downloaded `pnpm11/pnpm/dist` bundle. - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Node # The runner image's system Node is older than the bundle's floor # (`node:sqlite` needs >= 22.13). Installs the `devEngines.runtime` # pin, which the harness passes to every subprocess through PATH. uses: pnpm/setup@a0881977cd8ea73b1ed212236c99ca10dcc80cf4 # v3.1.1 with: install: false - name: Download build outputs uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: ecosystem-e2e-build path: . - name: Restore executable bits # Artifacts don't preserve the executable bit. run: chmod +x target/release/pnpm target/release/ecosystem-e2e - name: Wrap the built pnpm bundle as an executable # The harness takes a single executable for --pnpm; the launcher is a # .cjs that needs `node`. Wrap the repo's bin entry (which loads # dist/pnpm.mjs) so the run tests this repo's pnpm, not a system one. run: | printf '#!/usr/bin/env bash\nexec node "%s/pnpm11/pnpm/bin/pnpm.cjs" "$@"\n' "$PWD" > pnpm-built chmod +x pnpm-built - name: Run ecosystem E2E run: | ./target/release/ecosystem-e2e \ --pnpm "$PWD/pnpm-built" \ --pacquet "$PWD/target/release/pnpm" \ --binary both \ --layout both \ --stack ${{ matrix.stack }} \ --work-dir "$RUNNER_TEMP/ecosystem-e2e-work" - name: Upload cell logs if: always() uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: ecosystem-e2e-logs-${{ matrix.stack }} path: ${{ runner.temp }}/ecosystem-e2e-work/**/*.log retention-days: 7 if-no-files-found: ignore webcontainer: if: github.repository == 'pnpm/pnpm' # Only run on the main repository, not forks name: Ecosystem E2E / webcontainer needs: build runs-on: blacksmith-8vcpu-ubuntu-2404 timeout-minutes: 30 steps: # The harness mounts the committed `pnpm11/pnpm/package.json` and `bin/` # alongside the downloaded `dist/` bundle. - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install pnpm uses: pnpm/setup@a0881977cd8ea73b1ed212236c99ca10dcc80cf4 # v3.1.1 with: install: false - name: Install the harness run: pnpm install --frozen-lockfile --filter @pnpm-private/ecosystem-e2e-webcontainer - name: Install Chromium run: pnpm --filter @pnpm-private/ecosystem-e2e-webcontainer exec playwright-core install --with-deps --only-shell chromium - name: Download build outputs uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: ecosystem-e2e-build path: . - name: Run the WebContainer e2e run: node pnpm/tasks/ecosystem-e2e/webcontainer/run.mjs