diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 924bb99b39f..6312de201cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,7 @@ env: permissions: contents: read + id-token: write jobs: changes: @@ -137,6 +138,7 @@ jobs: - run: jq .scripts package.json > scripts.json + # Include the workflow and root package.json because CI command changes or pnpm script definition changes can change build outputs. - name: 'check cache: qwik' id: cache-qwik uses: actions/cache/restore@v5 @@ -146,7 +148,7 @@ jobs: # Note that this includes the package.json of qwik # qwik-vite source is bundled into packages/qwik/dist/optimizer.mjs by scripts/submodule-optimizer.ts, so its sources must invalidate this cache. # CI-only helpers should not invalidate compiled package output caches. - key: ${{ hashfiles('pnpm-lock.yaml', 'scripts.json', 'scripts/**/*', '!scripts/ci-restore-artifacts.ts', 'packages/qwik/**/*', 'packages/qwik-vite/**/*', 'starters/features/**/*', 'starters/adapters/**/*', 'starters/templates/**/*', '!**/*.unit.*', '!**/*.rs', '!e2e/qwik-e2e/apps/e2e') }} + key: ${{ hashfiles('pnpm-lock.yaml', 'package.json', '.github/workflows/ci.yml', 'scripts.json', 'scripts/**/*', '!scripts/ci-restore-artifacts.ts', 'packages/qwik/**/*', 'packages/qwik-vite/**/*', 'starters/features/**/*', 'starters/adapters/**/*', 'starters/templates/**/*', '!**/*.unit.*', '!**/*.rs', '!e2e/qwik-e2e/apps/e2e') }} - run: 'echo ${{ steps.cache-qwik.outputs.cache-primary-key }} > qwik-key.txt' - name: 'check cache: rust' id: cache-rust @@ -154,7 +156,7 @@ jobs: with: lookup-only: true path: packages/optimizer/ - key: ${{ hashfiles('Makefile', 'rust-toolchain', '**/Cargo.toml', '**/Cargo.lock', '**/*.rs') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'Makefile', 'rust-toolchain', '**/Cargo.toml', '**/Cargo.lock', '**/*.rs') }} - run: 'echo ${{ steps.cache-rust.outputs.cache-primary-key }} > rust-key.txt' - name: 'check cache: others' id: cache-others @@ -167,7 +169,7 @@ jobs: packages/eslint-plugin-qwik/dist packages/create-qwik/dist # note that all inputs need to be listed here, including qwik, for correct cache invalidation - key: ${{ hashfiles('qwik-key.txt', 'rust-key.txt', 'packages/qwik-router/**/*', 'packages/qwik-react/**/*', 'packages/eslint-plugin-qwik/**/*', 'packages/create-qwik/**/*', 'starters/apps/**/*', 'e2e/qwik-e2e/apps/**/*', '!**/*.unit.*') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'qwik-key.txt', 'rust-key.txt', 'packages/qwik-router/**/*', 'packages/qwik-react/**/*', 'packages/eslint-plugin-qwik/**/*', 'packages/create-qwik/**/*', 'starters/apps/**/*', 'e2e/qwik-e2e/apps/**/*', '!**/*.unit.*') }} - run: 'echo ${{ steps.cache-others.outputs.cache-primary-key }} > others-key.txt' - name: 'check cache: docs' id: cache-docs @@ -175,7 +177,7 @@ jobs: with: lookup-only: true path: docs-build-completed.txt - key: ${{ hashfiles('others-key.txt', 'packages/docs/**/*') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'others-key.txt', 'packages/docs/**/*') }} - name: 'check cache: insights' id: cache-insights uses: actions/cache/restore@v5 @@ -184,43 +186,75 @@ jobs: path: | packages/insights/dist packages/insights/.netlify - key: ${{ hashfiles('others-key.txt', 'packages/insights/**/*') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'others-key.txt', 'packages/insights/**/*') }} - name: 'check cache: unit tests' id: cache-unit uses: actions/cache/restore@v5 with: lookup-only: true path: unit-tests-completed.txt - key: ${{ hashfiles('others-key.txt', 'packages/**/*.unit.*', 'packages/**/*.spec.*') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'others-key.txt', 'packages/**/*.unit.*', 'packages/**/*.spec.*') }} - name: 'check cache: benchmarks' id: cache-bench uses: actions/cache/restore@v5 with: lookup-only: true path: bench-tests-completed.txt - key: ${{ hashfiles('others-key.txt', 'packages/**/*.bench.*', 'scripts/validate-bench*') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'others-key.txt', 'packages/**/*.bench.*', 'scripts/validate-bench*') }} - name: 'check cache: e2e tests' id: cache-e2e uses: actions/cache/restore@v5 with: lookup-only: true path: e2e-tests-completed.txt - key: ${{ hashfiles('others-key.txt', 'starters/**/*', 'e2e/qwik-e2e/tests/**/*', 'e2e/qwik-e2e/dev-server.ts', 'e2e/qwik-e2e/playwright.config.ts') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'others-key.txt', 'starters/**/*', 'e2e/qwik-e2e/tests/**/*', 'e2e/qwik-e2e/dev-server.ts', 'e2e/qwik-e2e/playwright.config.ts') }} - name: 'check cache: cli e2e tests' id: cache-cli-e2e uses: actions/cache/restore@v5 with: lookup-only: true path: cli-e2e-tests-completed.txt - key: ${{ hashfiles('others-key.txt', 'e2e/**/*') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'others-key.txt', 'e2e/**/*') }} - name: 'check cache: docs e2e tests' id: cache-docs-e2e uses: actions/cache/restore@v5 with: lookup-only: true path: docs-e2e-tests-completed.txt - key: ${{ hashfiles('others-key.txt', 'e2e/docs-e2e/**/*') }} + key: ${{ hashfiles('package.json', '.github/workflows/ci.yml', 'others-key.txt', 'e2e/docs-e2e/**/*') }} + ########### BUILD NODE MODULES ############ + node-modules: + name: Build node_modules archive (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + needs: + - changes + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup Nix + uses: DeterminateSystems/determinate-nix-action@v3 + with: + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled + + - name: Build node_modules archive + run: bash scripts/ci-build-node-modules.sh ############ BUILD PLATFORM BINDINGS ############ build-bindings: @@ -248,44 +282,89 @@ jobs: - name: Checkout uses: actions/checkout@v6 + - name: Setup Nix + if: runner.os != 'Windows' + uses: DeterminateSystems/determinate-nix-action@v3 + with: + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + if: runner.os != 'Windows' + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled + - name: Install Rust toolchain + if: runner.os == 'Windows' uses: actions-rust-lang/setup-rust-toolchain@v1 with: components: clippy,rustfmt - uses: pnpm/action-setup@v5 + if: runner.os == 'Windows' - name: Setup Node + if: runner.os == 'Windows' uses: actions/setup-node@v6 with: node-version: ${{ env.CI_NODE_VERSION }} cache: 'pnpm' registry-url: https://registry.npmjs.org/ - - run: pnpm install + - name: Install NPM Dependencies + if: runner.os != 'Windows' + run: nix develop .#ci-rust -c pnpm ci.restore-node-modules + + - name: Install NPM Dependencies + if: runner.os == 'Windows' + run: pnpm install - name: Install Wasm build tools - if: matrix.settings.wasm + if: matrix.settings.wasm && runner.os == 'Windows' run: | rustup target add wasm32-unknown-unknown cargo install wasm-pack --locked - name: Lint check - if: matrix.settings.checks + if: matrix.settings.checks && runner.os != 'Windows' + run: nix develop .#ci-rust -c pnpm lint.rust + + - name: Lint check + if: matrix.settings.checks && runner.os == 'Windows' run: pnpm lint.rust - name: Unit tests - if: matrix.settings.checks + if: matrix.settings.checks && runner.os != 'Windows' + run: nix develop .#ci-rust -c pnpm test.rust + + - name: Unit tests + if: matrix.settings.checks && runner.os == 'Windows' run: pnpm test.rust - name: TS bridge - if: matrix.settings.checks + if: matrix.settings.checks && runner.os != 'Windows' + run: nix develop .#ci-rust -c pnpm build --optimizer + + - name: TS bridge + if: matrix.settings.checks && runner.os == 'Windows' run: pnpm build --optimizer - name: Build Platform Binding + if: runner.os != 'Windows' + run: nix develop .#ci-rust -c pnpm build --platform-binding + + - name: Build Platform Binding + if: runner.os == 'Windows' run: pnpm build --platform-binding - name: Build Wasm Binding - if: matrix.settings.wasm + if: matrix.settings.wasm && runner.os != 'Windows' + run: nix develop .#ci-rust -c pnpm build --wasm + + - name: Build Wasm Binding + if: matrix.settings.wasm && runner.os == 'Windows' run: pnpm build --wasm - name: Print Packages Dist Build @@ -394,15 +473,20 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - uses: pnpm/action-setup@v5 + - name: Setup Nix if: needs.changes.outputs.build-qwik == 'true' || needs.changes.outputs.build-others == 'true' - - name: Setup Node + uses: DeterminateSystems/determinate-nix-action@v3 + with: + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache if: needs.changes.outputs.build-qwik == 'true' || needs.changes.outputs.build-others == 'true' - uses: actions/setup-node@v6 + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true with: - node-version: ${{ env.CI_NODE_VERSION }} - cache: 'pnpm' - registry-url: https://registry.npmjs.org/ + use-gha-cache: disabled - name: Restore optimizer artifact if: needs.changes.outputs.build-qwik == 'true' || needs.changes.outputs.build-others == 'true' @@ -416,16 +500,16 @@ jobs: run: | # Ensure that the optimizer binary gets made mkdir -p packages/optimizer/bindings/ - pnpm install --frozen-lockfile + nix develop .#ci-node24 -c pnpm ci.restore-node-modules - name: 'build: qwik and packages' if: needs.changes.outputs.build-qwik == 'true' && needs.changes.outputs.build-others == 'true' - run: pnpm build --qwik --optimizer --insights --tsc --api --qwikrouter --cli --qwikreact --eslint --set-dist-tag="${{ needs.changes.outputs.disttag }}" + run: nix develop .#ci-node24 -c pnpm build --qwik --optimizer --insights --tsc --api --qwikrouter --cli --qwikreact --eslint --set-dist-tag="${{ needs.changes.outputs.disttag }}" - name: 'build: qwik' if: needs.changes.outputs.build-qwik == 'true' && needs.changes.outputs.build-others != 'true' # Also build optimizer for now - run: pnpm build --qwik --optimizer --insights --set-dist-tag="${{ needs.changes.outputs.disttag }}" + run: nix develop .#ci-node24 -c pnpm build --qwik --optimizer --insights --set-dist-tag="${{ needs.changes.outputs.disttag }}" - name: Restore qwik cache if: needs.changes.outputs.build-qwik != 'true' @@ -456,7 +540,7 @@ jobs: - name: 'build: qwik-router & others' if: needs.changes.outputs.build-others == 'true' && needs.changes.outputs.build-qwik != 'true' - run: pnpm build --tsc --api --qwikrouter --cli --qwikreact --eslint --set-dist-tag="${{ needs.changes.outputs.disttag }}" + run: nix develop .#ci-node24 -c pnpm build --tsc --api --qwikrouter --cli --qwikreact --eslint --set-dist-tag="${{ needs.changes.outputs.disttag }}" - name: Save others cache if: needs.changes.outputs.build-others == 'true' uses: actions/cache/save@v5 @@ -545,13 +629,18 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - uses: pnpm/action-setup@v5 - - name: Setup Node - uses: actions/setup-node@v6 + - name: Setup Nix + uses: DeterminateSystems/determinate-nix-action@v3 with: - node-version: ${{ env.CI_NODE_VERSION }} - cache: 'pnpm' - registry-url: https://registry.npmjs.org/ + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled - name: Download Package Artifacts uses: actions/download-artifact@v8 @@ -561,7 +650,7 @@ jobs: - name: Move Distribution Artifacts run: > - pnpm ci.restore-artifacts + nix develop .#ci-node24 -c pnpm ci.restore-artifacts artifact-optimizer artifact-qwik artifact-qwikrouter @@ -569,9 +658,9 @@ jobs: artifact-create-qwik artifact-eslint-plugin-qwik - - run: pnpm install --frozen-lockfile + - run: nix develop .#ci-node24 -c pnpm ci.restore-node-modules - name: Build Qwik Insights - run: pnpm run build.packages.insights + run: nix develop .#ci-node24 -c pnpm run build.packages.insights - name: Save Insights Cache uses: actions/cache/save@v5 @@ -602,13 +691,18 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - uses: pnpm/action-setup@v5 - - name: Setup Node - uses: actions/setup-node@v6 + - name: Setup Nix + uses: DeterminateSystems/determinate-nix-action@v3 with: - node-version: ${{ env.CI_NODE_VERSION }} - cache: 'pnpm' - registry-url: https://registry.npmjs.org/ + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled - name: Download Package Artifacts uses: actions/download-artifact@v8 @@ -618,7 +712,7 @@ jobs: - name: Move Distribution Artifacts run: > - pnpm ci.restore-artifacts + nix develop .#ci-node24 -c pnpm ci.restore-artifacts artifact-optimizer artifact-qwik artifact-qwikrouter @@ -626,9 +720,9 @@ jobs: artifact-create-qwik artifact-eslint-plugin-qwik - - run: pnpm install --frozen-lockfile + - run: nix develop .#ci-node24 -c pnpm ci.restore-node-modules - name: Build Qwik Docs - run: pnpm build --tsc-docs && pnpm run build.packages.docs && echo ok > docs-build-completed.txt + run: nix develop .#ci-node24 -c bash -lc 'pnpm build --tsc-docs && pnpm run build.packages.docs && echo ok > docs-build-completed.txt' - name: Save Docs Artifacts uses: actions/upload-artifact@v7 @@ -661,12 +755,8 @@ jobs: fail-fast: false matrix: settings: - - host: ubuntu-latest - browser: chromium - host: windows-latest browser: chromium - - host: macos-latest - browser: webkit runs-on: ${{ matrix.settings.host }} env: @@ -681,7 +771,9 @@ jobs: uses: actions/checkout@v6 - uses: pnpm/action-setup@v5 + if: runner.os == 'Windows' - name: Setup Node + if: runner.os == 'Windows' uses: actions/setup-node@v6 with: node-version: ${{ env.CI_NODE_VERSION_E2E }} @@ -747,13 +839,18 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - uses: pnpm/action-setup@v5 - - name: Setup Node - uses: actions/setup-node@v6 + - name: Setup Nix + uses: DeterminateSystems/determinate-nix-action@v3 with: - node-version: ${{ env.CI_NODE_VERSION }} - cache: 'pnpm' - registry-url: https://registry.npmjs.org/ + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled - name: Download Package Artifacts uses: actions/download-artifact@v8 @@ -769,7 +866,7 @@ jobs: - name: Move Distribution Artifacts run: > - pnpm ci.restore-artifacts + nix develop .#ci-node24-e2e -c pnpm ci.restore-artifacts artifact-optimizer artifact-qwik artifact-qwikrouter @@ -778,25 +875,10 @@ jobs: artifact-eslint-plugin-qwik artifact-docs - - run: pnpm install --frozen-lockfile - - - name: Restore Playwright browser cache - id: playwright-cache - uses: actions/cache/restore@v5 - with: - key: playwright-${{ runner.os }}-chromium-${{ hashFiles('pnpm-lock.yaml') }} - path: .cache/ms-playwright - - - name: Install Playwright System Dependencies - if: runner.os == 'Linux' - run: pnpm exec playwright install-deps chromium - - - name: Install Playwright Browser - if: steps.playwright-cache.outputs.cache-hit != 'true' - run: pnpm exec playwright install chromium + - run: nix develop .#ci-node24-e2e -c pnpm ci.restore-node-modules - name: Docs E2E Tests - run: pnpm exec playwright test --config=e2e/docs-e2e/playwright.config.ts --project=chromium --shard=${{ matrix.shard.shard }}/${{ matrix.shard.shardTotal }} + run: nix develop .#ci-node24-e2e -c pnpm exec playwright test --config=e2e/docs-e2e/playwright.config.ts --project=chromium --shard=${{ matrix.shard.shard }}/${{ matrix.shard.shardTotal }} - name: Upload Playwright Trace uses: actions/upload-artifact@v7 @@ -860,13 +942,30 @@ jobs: uses: actions/checkout@v6 - uses: pnpm/action-setup@v5 + if: runner.os == 'Windows' - name: Setup Node + if: runner.os == 'Windows' uses: actions/setup-node@v6 with: node-version: ${{ env.CI_NODE_VERSION }} cache: 'pnpm' registry-url: https://registry.npmjs.org/ + - name: Setup Nix + if: runner.os != 'Windows' + uses: DeterminateSystems/determinate-nix-action@v3 + with: + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + if: runner.os != 'Windows' + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled + - name: Download Package Artifacts uses: actions/download-artifact@v8 with: @@ -874,6 +973,18 @@ jobs: merge-multiple: false - name: Move Distribution Artifacts + if: runner.os != 'Windows' + run: > + nix develop .#ci-node24 -c pnpm ci.restore-artifacts + artifact-optimizer + artifact-qwik + artifact-qwikrouter + artifact-qwikreact + artifact-create-qwik + artifact-eslint-plugin-qwik + + - name: Move Distribution Artifacts + if: runner.os == 'Windows' run: > pnpm ci.restore-artifacts artifact-optimizer @@ -883,9 +994,20 @@ jobs: artifact-create-qwik artifact-eslint-plugin-qwik - - run: pnpm install --frozen-lockfile + - name: Install NPM Dependencies + if: runner.os != 'Windows' + run: nix develop .#ci-node24 -c pnpm ci.restore-node-modules + + - name: Install NPM Dependencies + if: runner.os == 'Windows' + run: pnpm install --frozen-lockfile - name: Unit Tests + if: runner.os != 'Windows' + run: nix develop .#ci-node24 -c pnpm run test.unit + + - name: Unit Tests + if: runner.os == 'Windows' run: pnpm run test.unit save-unit-tests-cache: @@ -935,13 +1057,18 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - uses: pnpm/action-setup@v5 - - name: Setup Node - uses: actions/setup-node@v6 + - name: Setup Nix + uses: DeterminateSystems/determinate-nix-action@v3 with: - node-version: ${{ env.CI_NODE_VERSION }} - cache: 'pnpm' - registry-url: https://registry.npmjs.org/ + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled - name: Download Package Artifacts uses: actions/download-artifact@v8 @@ -951,7 +1078,7 @@ jobs: - name: Move Distribution Artifacts run: > - pnpm ci.restore-artifacts + nix develop .#ci-node24 -c pnpm ci.restore-artifacts artifact-optimizer artifact-qwik artifact-qwikrouter @@ -959,13 +1086,13 @@ jobs: artifact-create-qwik artifact-eslint-plugin-qwik - - run: pnpm install --frozen-lockfile + - run: nix develop .#ci-node24 -c pnpm ci.restore-node-modules - name: Timing Benchmarks - run: pnpm run test.bench.timing + run: nix develop .#ci-node24 -c pnpm run test.bench.timing - name: Memory Benchmarks - run: pnpm run test.bench.memory + run: nix develop .#ci-node24 -c pnpm run test.bench.memory save-bench-cache: name: Save Benchmark Cache @@ -1071,13 +1198,30 @@ jobs: uses: actions/checkout@v6 - uses: pnpm/action-setup@v5 + if: runner.os == 'Windows' - name: Setup Node + if: runner.os == 'Windows' uses: actions/setup-node@v6 with: node-version: ${{ env.CI_NODE_VERSION_E2E }} cache: 'pnpm' registry-url: https://registry.npmjs.org/ + - name: Setup Nix + if: runner.os != 'Windows' + uses: DeterminateSystems/determinate-nix-action@v3 + with: + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + if: runner.os != 'Windows' + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled + - name: Download Package Artifacts uses: actions/download-artifact@v8 with: @@ -1085,6 +1229,18 @@ jobs: merge-multiple: false - name: Move Distribution Artifacts + if: runner.os != 'Windows' + run: > + nix develop .#ci-node22-e2e -c pnpm ci.restore-artifacts + artifact-optimizer + artifact-qwik + artifact-qwikrouter + artifact-qwikreact + artifact-create-qwik + artifact-eslint-plugin-qwik + + - name: Move Distribution Artifacts + if: runner.os == 'Windows' run: > pnpm ci.restore-artifacts artifact-optimizer @@ -1094,24 +1250,32 @@ jobs: artifact-create-qwik artifact-eslint-plugin-qwik - - run: pnpm install --frozen-lockfile + - name: Install NPM Dependencies + if: runner.os != 'Windows' + run: nix develop .#ci-node22-e2e -c pnpm ci.restore-node-modules + + - name: Install NPM Dependencies + if: runner.os == 'Windows' + run: pnpm install --frozen-lockfile - name: Restore Playwright browser cache + if: runner.os == 'Windows' id: playwright-cache uses: actions/cache/restore@v5 with: key: playwright-${{ runner.os }}-${{ matrix.settings.browser }}-${{ hashFiles('pnpm-lock.yaml') }} path: .cache/ms-playwright - - name: Install Playwright System Dependencies - if: runner.os == 'Linux' - run: pnpm exec playwright install-deps ${{ matrix.settings.browser }} - - name: Install Playwright Browser - if: steps.playwright-cache.outputs.cache-hit != 'true' + if: runner.os == 'Windows' && steps.playwright-cache.outputs.cache-hit != 'true' run: pnpm exec playwright install ${{ matrix.settings.browser }} - name: Playwright E2E Tests + if: runner.os != 'Windows' + run: nix develop .#ci-node22-e2e -c pnpm exec playwright test e2e/qwik-e2e/tests --browser=${{ matrix.settings.browser }} --config=e2e/qwik-e2e/playwright.config.ts --shard=${{ matrix.settings.shard }}/${{ matrix.settings.shardTotal }} + + - name: Playwright E2E Tests + if: runner.os == 'Windows' run: pnpm exec playwright test e2e/qwik-e2e/tests --browser=${{ matrix.settings.browser }} --config=e2e/qwik-e2e/playwright.config.ts --shard=${{ matrix.settings.shard }}/${{ matrix.settings.shardTotal }} - name: Upload Playwright Trace @@ -1266,13 +1430,30 @@ jobs: uses: actions/checkout@v6 - uses: pnpm/action-setup@v5 + if: runner.os == 'Windows' - name: Setup Node + if: runner.os == 'Windows' uses: actions/setup-node@v6 with: node-version: ${{ env.CI_NODE_VERSION_E2E }} cache: 'pnpm' registry-url: https://registry.npmjs.org/ + - name: Setup Nix + if: runner.os != 'Windows' + uses: DeterminateSystems/determinate-nix-action@v3 + with: + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ + + - name: Setup FlakeHub Cache + if: runner.os != 'Windows' + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled + - name: Download Package Artifacts uses: actions/download-artifact@v8 with: @@ -1280,6 +1461,18 @@ jobs: merge-multiple: false - name: Move Distribution Artifacts + if: runner.os != 'Windows' + run: > + nix develop .#ci-node22-e2e -c pnpm ci.restore-artifacts + artifact-optimizer + artifact-qwik + artifact-qwikrouter + artifact-qwikreact + artifact-create-qwik + artifact-eslint-plugin-qwik + + - name: Move Distribution Artifacts + if: runner.os == 'Windows' run: > pnpm ci.restore-artifacts artifact-optimizer @@ -1289,7 +1482,13 @@ jobs: artifact-create-qwik artifact-eslint-plugin-qwik - - run: pnpm install --frozen-lockfile + - name: Install NPM Dependencies + if: runner.os != 'Windows' + run: nix develop .#ci-node22-e2e -c pnpm ci.restore-node-modules + + - name: Install NPM Dependencies + if: runner.os == 'Windows' + run: pnpm install --frozen-lockfile - name: Setup Bun if: matrix.settings.runtime == 'bun' @@ -1304,28 +1503,40 @@ jobs: deno-version: v2.x - name: Restore Playwright browser cache + if: runner.os == 'Windows' id: playwright-cache uses: actions/cache/restore@v5 with: key: playwright-${{ runner.os }}-${{ matrix.settings.browser }}-${{ hashFiles('pnpm-lock.yaml') }} path: .cache/ms-playwright - - name: Install Playwright System Dependencies - if: runner.os == 'Linux' - run: pnpm exec playwright install-deps ${{ matrix.settings.browser }} - - name: Install Playwright Browser - if: steps.playwright-cache.outputs.cache-hit != 'true' + if: runner.os == 'Windows' && steps.playwright-cache.outputs.cache-hit != 'true' run: pnpm exec playwright install ${{ matrix.settings.browser }} - name: Playwright E2E Integration Tests + if: runner.os != 'Windows' + run: nix develop .#ci-node22-e2e -c pnpm exec playwright test e2e/adapters-e2e/tests --project=${{ matrix.settings.browser }} --config=${{ matrix.settings.integration-config }} --shard=${{ matrix.settings.shard }}/${{ matrix.settings.shardTotal }} + + - name: Playwright E2E Integration Tests + if: runner.os == 'Windows' run: pnpm exec playwright test e2e/adapters-e2e/tests --project=${{ matrix.settings.browser }} --config=${{ matrix.settings.integration-config }} --shard=${{ matrix.settings.shard }}/${{ matrix.settings.shardTotal }} - name: Playwright E2E Qwik React Tests - if: matrix.settings.run-qwik-react + if: matrix.settings.run-qwik-react && runner.os != 'Windows' + run: nix develop .#ci-node22-e2e -c pnpm exec playwright test e2e/qwik-react-e2e/tests --project=${{ matrix.settings.browser }} --config=e2e/qwik-react-e2e/playwright.config.ts --shard=${{ matrix.settings.shard }}/${{ matrix.settings.shardTotal }} + + - name: Playwright E2E Qwik React Tests + if: matrix.settings.run-qwik-react && runner.os == 'Windows' run: pnpm exec playwright test e2e/qwik-react-e2e/tests --project=${{ matrix.settings.browser }} --config=e2e/qwik-react-e2e/playwright.config.ts --shard=${{ matrix.settings.shard }}/${{ matrix.settings.shardTotal }} - name: CLI E2E Tests - if: matrix.settings.run-cli + if: matrix.settings.run-cli && runner.os != 'Windows' + run: nix develop .#ci-node22-e2e -c pnpm --filter qwik-cli-e2e exec vitest run --config=vite.config.ts --shard=${{ matrix.settings.cliShard }}/${{ matrix.settings.cliShardTotal }} + env: + PW_BROWSER: ${{ matrix.settings.browser }} + + - name: CLI E2E Tests + if: matrix.settings.run-cli && runner.os == 'Windows' run: pnpm --filter qwik-cli-e2e exec vitest run --config=vite.config.ts --shard=${{ matrix.settings.cliShard }}/${{ matrix.settings.cliShardTotal }} env: PW_BROWSER: ${{ matrix.settings.browser }} @@ -1386,39 +1597,43 @@ jobs: lint-package: name: Lint Package runs-on: ubuntu-latest + needs: + - changes + - node-modules steps: - name: Checkout uses: actions/checkout@v6 - - uses: pnpm/action-setup@v5 - - name: Setup Node - uses: actions/setup-node@v6 + - name: Setup Nix + uses: DeterminateSystems/determinate-nix-action@v3 with: - node-version: ${{ env.CI_NODE_VERSION }} - cache: 'pnpm' - registry-url: https://registry.npmjs.org/ + extra-conf: | + fallback = true + extra-substituters = https://cache.nixos.org/ - - run: pnpm install --frozen-lockfile + - name: Setup FlakeHub Cache + uses: DeterminateSystems/flakehub-cache-action@v3 + continue-on-error: true + with: + use-gha-cache: disabled - - name: "Verify pnpm dedupe" - if: always() - run: NPM_CONFIG_USERCONFIG=/dev/null pnpm --config.platform=linux --config.arch=x64 dedupe --check + - run: nix develop .#ci-node24 -c pnpm ci.restore-node-modules - name: SyncPack Check if: always() - run: pnpm run lint.syncpack + run: nix develop .#ci-node24 -c pnpm run lint.syncpack - name: Prettier Check if: always() - run: pnpm run lint.prettier + run: nix develop .#ci-node24 -c pnpm run lint.prettier - name: Build ESLint if: always() - run: pnpm build --eslint + run: nix develop .#ci-node24 -c pnpm build --eslint - name: ESLint Check if: always() - run: pnpm run lint.eslint + run: nix develop .#ci-node24 -c pnpm run lint.eslint ############ RELEASE ############ release: @@ -1615,6 +1830,7 @@ jobs: - test-e2e - test-e2e-docs - test-cli-e2e + - node-modules - lint-package - build-docs - build-insights @@ -1628,6 +1844,7 @@ jobs: (needs.test-e2e.result == 'success' || needs.test-e2e.result == 'skipped') && (needs.test-e2e-docs.result == 'success' || needs.test-e2e-docs.result == 'skipped') && (needs.test-cli-e2e.result == 'success' || needs.test-cli-e2e.result == 'skipped') && + needs.node-modules.result == 'success' && (needs.lint-package.result == 'success' || needs.lint-package.result == 'skipped') && (needs.build-docs.result == 'success' || needs.build-docs.result == 'skipped') && (needs.build-insights.result == 'success' || needs.build-insights.result == 'skipped') diff --git a/e2e/docs-e2e/package.json b/e2e/docs-e2e/package.json index 3d3c32c797c..15cc84bf2d4 100644 --- a/e2e/docs-e2e/package.json +++ b/e2e/docs-e2e/package.json @@ -3,7 +3,7 @@ "description": "", "author": "", "devDependencies": { - "@playwright/test": "1.57.0", + "@playwright/test": "1.59.1", "@types/node": "24.10.0" }, "keywords": [], diff --git a/e2e/qwik-cli-e2e/package.json b/e2e/qwik-cli-e2e/package.json index 632a1f7b1cc..2ff97e10a2d 100644 --- a/e2e/qwik-cli-e2e/package.json +++ b/e2e/qwik-cli-e2e/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "dependencies": { "kleur": "^4.1.5", - "playwright": "^1.57.0" + "playwright": "^1.59.1" }, "private": true, "scripts": { diff --git a/flake.lock b/flake.lock index d7e0b490582..9a766e25392 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1767640445, - "narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=", + "lastModified": 1781074563, + "narHash": "sha256-md8WlXOlfnIeHeOScMTTHFyf2d6iaTwPl2apR5EQ3P4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5", + "rev": "9ae611a455b90cf061d8f332b977e387bda8e1ca", "type": "github" }, "original": { @@ -43,11 +43,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1767754000, - "narHash": "sha256-znoNJs2QZFl+wCFLd6FbUJ00c74kvzOjyQYXc45uFvo=", + "lastModified": 1781234414, + "narHash": "sha256-HdA+P4fKRGOomkewnI/Tww5Wz4xK1O7+hDO90YAsPB4=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "0b3a5ad260479f2c9bdadf3ba5b2a4be359cfcdd", + "rev": "1d18bfe3de6244c641ca4e8011186d0981b81d76", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 6034ec8b86f..7b915b8d059 100644 --- a/flake.nix +++ b/flake.nix @@ -17,51 +17,175 @@ outputs = { self, rust-overlay, nixpkgs }: let b = builtins; - devShell = system: _pkgs: + perSystem = system: _pkgs: let overlays = [ (import rust-overlay) ]; pkgs = import nixpkgs { inherit system overlays; }; - in - { - default = pkgs.mkShell { + lib = pkgs.lib; + pnpm = pkgs.pnpm_10.override { nodejs-slim = pkgs.nodejs-slim_24; }; + pnpmDependencySource = lib.cleanSourceWith { + name = "qwik-pnpm-dependency-source"; + src = ./.; + filter = path: type: + let + root = toString ./.; + rel = lib.removePrefix "${root}/" (toString path); + isWorkspaceConfig = builtins.elem rel [ + ".npmrc" + "package.json" + "pnpm-lock.yaml" + "pnpm-workspace.yaml" + ]; + isWorkspacePackageConfig = + builtins.match "(packages|e2e)/[^/]+/(package\\.json|\\.npmrc)" rel != null; + in + type == "directory" + || isWorkspaceConfig + || isWorkspacePackageConfig + || lib.hasPrefix "patches/" rel; + }; + pnpmDependencySourceId = b.substring 0 12 (b.hashString "sha256" (toString pnpmDependencySource)); + # CI prints the replacement hash when a platform hash is missing or stale. + pnpmDepsHash = { + aarch64-darwin = "sha256-kpjBxC8qiyv+ozqXqixTgRc14lijAhKf2PpovSrUUx8="; + x86_64-linux = "sha256-kpjBxC8qiyv+ozqXqixTgRc14lijAhKf2PpovSrUUx8="; + }.${system} or lib.fakeHash; + pnpmDeps = pkgs.fetchPnpmDeps { + pname = "qwik-${pnpmDependencySourceId}"; + version = "0.0.0"; + src = pnpmDependencySource; + inherit pnpm; + fetcherVersion = 4; + hash = pnpmDepsHash; + }; + nodeModules = pkgs.stdenvNoCC.mkDerivation { + pname = "qwik-${pnpmDependencySourceId}-node-modules"; + version = "0.0.0"; + src = pnpmDependencySource; nativeBuildInputs = with pkgs; [ - bashInteractive - gitMinimal - + coreutils + gnutar nodejs_24 - corepack_24 + pnpm + zstd + ]; + dontConfigure = true; + dontBuild = true; + installPhase = '' + runHook preInstall - # Playwright for the end-to-end tests - playwright-driver.browsers + export HOME="$TMPDIR/home" + export npm_config_cache="$TMPDIR/npm-cache" + export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 + export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 + export PUPPETEER_SKIP_DOWNLOAD=1 + export npm_config_manage_package_manager_versions=false - # Qwik optimizer deps - wasm-pack - # Provides rustc and cargo - ((rust-bin.fromRustupToolchainFile - ./rust-toolchain).override { - # For rust-analyzer - extensions = [ "rust-src" ]; - # For building wasm - targets = [ "wasm32-unknown-unknown" ]; - }) - ]; - # https://github.com/microsoft/playwright/issues/5501 - shellHook = '' - export PATH=$PWD/node_modules/.bin:$PATH - export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers} - export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true - pwNixVersion=${pkgs.playwright-driver.version} - pwNpmVersion=$(${pkgs.jq}/bin/jq -r .version node_modules/@playwright/test/package.json 2>/dev/null) - if [ -n "$pwNpmVersion" ] && [ "$pwNpmVersion" != "$pwNixVersion" ]; then - echo "!!! Playwright version mismatch: $pwNpmVersion (nodejs) != $pwNixVersion (nix). Please fix." >&2 - fi + mkdir -p "$HOME" "$TMPDIR/pnpm-store" + tar --zstd -xf ${pnpmDeps}/pnpm-store.tar.zst -C "$TMPDIR/pnpm-store" + chmod -R u+w "$TMPDIR/pnpm-store" + + pnpm config set store-dir "$TMPDIR/pnpm-store" + pnpm config set package-import-method copy + pnpm install --offline --frozen-lockfile --ignore-scripts + + mkdir -p "$out" + find node_modules packages e2e -name node_modules -prune -print \ + | LC_ALL=C sort \ + | tar --zstd --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner \ + -cf "$out/node_modules.tar.zst" --files-from=- + + runHook postInstall ''; }; + rustToolchain = (pkgs.rust-bin.fromRustupToolchainFile + ./rust-toolchain).override { + # For rust-analyzer + extensions = [ "rust-src" ]; + # For building wasm + targets = [ "wasm32-unknown-unknown" ]; + }; + localNodeEnv = '' + export PATH=$PWD/node_modules/.bin:$PATH + unset PLAYWRIGHT_BROWSERS_PATH + unset PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS + ''; + playwrightEnv = localNodeEnv + '' + export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers} + export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true + pwNixVersion=${pkgs.playwright-driver.version} + pwNpmVersion=$(${pkgs.jq}/bin/jq -r .version node_modules/@playwright/test/package.json 2>/dev/null) + if [ -n "$pwNpmVersion" ] && [ "$pwNpmVersion" != "$pwNixVersion" ]; then + echo "!!! Playwright version mismatch: $pwNpmVersion (nodejs) != $pwNixVersion (nix). Please fix." >&2 + fi + ''; + mkNodeShell = { nodejs, corepack, withPlaywright ? false, extraInputs ? [ ] }: + pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + bashInteractive + gitMinimal + gnutar + jq + tree + zstd + + nodejs + corepack + ] ++ pkgs.lib.optionals withPlaywright [ + # Playwright for the end-to-end tests + pkgs.playwright-driver.browsers + ] ++ extraInputs; + shellHook = if withPlaywright then playwrightEnv else localNodeEnv; + }; + in + { + packages = { + pnpm-deps = pnpmDeps; + node-modules = nodeModules; + }; + devShells = { + default = mkNodeShell { + nodejs = pkgs.nodejs_24; + corepack = pkgs.corepack_24; + withPlaywright = true; + extraInputs = with pkgs; [ + # Qwik optimizer deps + wasm-pack + # Provides rustc and cargo + rustToolchain + ]; + }; + ci-node24 = mkNodeShell { + nodejs = pkgs.nodejs_24; + corepack = pkgs.corepack_24; + }; + ci-node24-e2e = mkNodeShell { + nodejs = pkgs.nodejs_24; + corepack = pkgs.corepack_24; + withPlaywright = true; + }; + ci-node22-e2e = mkNodeShell { + nodejs = pkgs.nodejs_22; + corepack = pkgs.corepack_22; + withPlaywright = true; + }; + ci-rust = mkNodeShell { + nodejs = pkgs.nodejs_24; + corepack = pkgs.corepack_24; + extraInputs = with pkgs; [ + # Qwik optimizer deps + wasm-pack + # Provides rustc and cargo + rustToolchain + ]; + }; + }; }; in { - devShells = b.mapAttrs (devShell) nixpkgs.legacyPackages; + packages = b.mapAttrs (system: pkgs: (perSystem system pkgs).packages) nixpkgs.legacyPackages; + devShells = b.mapAttrs (system: pkgs: (perSystem system pkgs).devShells) nixpkgs.legacyPackages; }; } diff --git a/nix-flakehub-ci-todo.md b/nix-flakehub-ci-todo.md new file mode 100644 index 00000000000..01ecd4839ce --- /dev/null +++ b/nix-flakehub-ci-todo.md @@ -0,0 +1,39 @@ +# Nix + FlakeHub CI TODO + +## Current state + +- Unix CI uses `nix develop` for tool prerequisites. +- FlakeHub Cache is optional and must not block CI when unavailable. +- Windows CI stays non-Nix and consumes the same GitHub artifacts as before. +- Build outputs are still cached with the existing GitHub Actions cache/artifact flow. + +## Next steps + +1. Package pnpm dependency materialization. + - Create a Nix derivation keyed by `pnpm-lock.yaml`, package manifests, patches, and pnpm workspace config. + - Store `node_modules/.pnpm` in a Nix store output. + - Generate a manifest of top-level and workspace package links needed to reconstruct `node_modules`. + - Add a cross-platform relink script that can rebuild the workspace `node_modules` layout from that store output. + - Keep `pnpm install --frozen-lockfile` as the fallback path for non-Nix local development and Windows CI. + +2. Package build outputs incrementally. + - Start with `packages/optimizer` and `packages/qwik/dist`. + - Add `packages/qwik-router/lib`, `packages/qwik-react/lib`, `packages/eslint-plugin-qwik/dist`, and `packages/create-qwik/dist`. + - Use filtered Nix sources that mirror the current CI cache-key boundaries so unrelated source changes do not invalidate every package. + - Copy or link Nix outputs back into the existing workspace paths so downstream tests and release jobs do not need to change immediately. + +3. Replace branch-scoped cache skips carefully. + - For each Nix-packaged output, prefer `nix build` substitution checks over `actions/cache` lookup-only keys. + - Keep GitHub artifact upload/download for job fanout and Windows consumers. + - Keep GitHub cache fallbacks until FlakeHub hit rates and failure behavior are known in real PR traffic. + +4. Validate cache safety. + - Only allow trusted upstream workflows to publish to FlakeHub Cache. + - Ensure fork PRs run correctly without cache write access. + - Confirm all Nix derivations are network-free after dependency materialization. + - Keep `cache.nixos.org` and local build fallback enabled for all Nix commands. + +5. Measure before removing old paths. + - Track `pnpm install` time, Nix substitution time, package build time, and artifact transfer time. + - Compare PRs with warm FlakeHub Cache, FlakeHub miss, and FlakeHub unavailable. + - Remove old GitHub cache branches only when replacement paths are measurably stable. diff --git a/package.json b/package.json index 3622142cbe0..38414caee18 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "dependencyTypes": [ "dev" ], - "pinVersion": "1.57.0" + "pinVersion": "1.59.1" } ], "semverGroups": [ @@ -114,7 +114,7 @@ "@napi-rs/triples": "1.2.0", "@node-rs/helper": "1.6.0", "@octokit/action": "6.1.0", - "@playwright/test": "1.57.0", + "@playwright/test": "1.59.1", "@qwik.dev/core": "workspace:*", "@qwik.dev/optimizer": "workspace:*", "@qwik.dev/partytown": "0.13.2", @@ -214,6 +214,7 @@ "build.watch": "node --require ./scripts/runBefore.ts scripts/index.ts --qwik --qwikworker --qwikrouter --watch --dev --platform-binding", "change": "changeset", "ci.restore-artifacts": "node --require ./scripts/runBefore.ts scripts/ci-restore-artifacts.ts", + "ci.restore-node-modules": "bash scripts/ci-restore-node-modules.sh", "cli": "pnpm build.cli && node packages/create-qwik/create-qwik.mjs && node --require ./scripts/runBefore.ts scripts/validate-cli.ts --copy-local-qwik-dist", "cli.qwik": "pnpm build.cli && node packages/qwik/qwik-cli.mjs", "cli.validate": "node --require ./scripts/runBefore.ts scripts/validate-cli.ts", diff --git a/packages/docs/package.json b/packages/docs/package.json index efdaea9bfa8..146af53ac5f 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -41,7 +41,7 @@ "gray-matter": "4.0.3", "leaflet": "1.9.4", "magic-string": "0.30.21", - "playwright": "1.57.0", + "playwright": "1.59.1", "pagefind": "1.4.0", "prettier": "3.7.4", "prism-themes": "1.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb7fd19821b..fcb5931facc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,8 +62,8 @@ importers: specifier: 6.1.0 version: 6.1.0 '@playwright/test': - specifier: 1.57.0 - version: 1.57.0 + specifier: 1.59.1 + version: 1.59.1 '@qwik.dev/core': specifier: workspace:* version: link:packages/qwik @@ -256,8 +256,8 @@ importers: e2e/docs-e2e: devDependencies: '@playwright/test': - specifier: 1.57.0 - version: 1.57.0 + specifier: 1.59.1 + version: 1.59.1 '@types/node': specifier: 24.10.0 version: 24.10.0 @@ -268,8 +268,8 @@ importers: specifier: ^4.1.5 version: 4.1.5 playwright: - specifier: ^1.57.0 - version: 1.57.0 + specifier: ^1.59.1 + version: 1.59.1 e2e/qwik-e2e: {} @@ -576,8 +576,8 @@ importers: specifier: 1.4.0 version: 1.4.0 playwright: - specifier: 1.57.0 - version: 1.57.0 + specifier: 1.59.1 + version: 1.59.1 prettier: specifier: 3.7.4 version: 3.7.4 @@ -3729,8 +3729,8 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.57.0': - resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==} + '@playwright/test@1.59.1': + resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} engines: {node: '>=18'} hasBin: true @@ -9308,13 +9308,13 @@ packages: pkg-types@2.3.1: resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} - playwright-core@1.57.0: - resolution: {integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==} + playwright-core@1.59.1: + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} engines: {node: '>=18'} hasBin: true - playwright@1.57.0: - resolution: {integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==} + playwright@1.59.1: + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} engines: {node: '>=18'} hasBin: true @@ -14421,9 +14421,9 @@ snapshots: '@pkgr/core@0.2.9': {} - '@playwright/test@1.57.0': + '@playwright/test@1.59.1': dependencies: - playwright: 1.57.0 + playwright: 1.59.1 '@pnpm/config.env-replace@1.1.0': {} @@ -20986,11 +20986,11 @@ snapshots: exsolve: 1.0.8 pathe: 2.0.3 - playwright-core@1.57.0: {} + playwright-core@1.59.1: {} - playwright@1.57.0: + playwright@1.59.1: dependencies: - playwright-core: 1.57.0 + playwright-core: 1.59.1 optionalDependencies: fsevents: 2.3.2 diff --git a/scripts/ci-build-node-modules.sh b/scripts/ci-build-node-modules.sh new file mode 100644 index 00000000000..4074f3f4e18 --- /dev/null +++ b/scripts/ci-build-node-modules.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -euo pipefail + +attr="${1:-.#node-modules}" +tmpdir="${TMPDIR:-/tmp}" +log="$(mktemp "${tmpdir%/}/ci-build-node-modules.XXXXXX")" + +cleanup() { + rm -f "$log" +} +trap cleanup EXIT + +if ! system="$(nix eval --raw --impure --expr builtins.currentSystem 2>/dev/null)"; then + system="current system" +fi + +set +e +nix build "$attr" --no-link --print-out-paths 2>&1 | tee "$log" +status="${PIPESTATUS[0]}" +set -e + +if [[ "$status" -eq 0 ]]; then + exit 0 +fi + +got_hash="$(sed -nE 's/^[[:space:]]*got:[[:space:]]*(sha256-[A-Za-z0-9+/=]+).*/\1/p' "$log" | tail -n 1)" + +if [[ -n "$got_hash" ]]; then + echo "::error file=flake.nix,title=Update pnpmDepsHash::The Nix pnpm dependency hash is stale for ${system}. Set pnpmDepsHash.${system} to ${got_hash}, then rerun this job." + echo "::group::How to update pnpmDepsHash" + echo "Update flake.nix:" + echo + echo " ${system} = \"${got_hash}\";" + echo + echo "Then rerun:" + echo + echo " bash scripts/ci-build-node-modules.sh" + echo "::endgroup::" + + if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then + { + echo "## Update pnpmDepsHash" + echo + echo "The Nix pnpm dependency hash is stale for \`${system}\`." + echo + echo "Set this value in \`flake.nix\`:" + echo + echo '```nix' + echo "${system} = \"${got_hash}\";" + echo '```' + echo + echo "Then rerun:" + echo + echo '```sh' + echo "bash scripts/ci-build-node-modules.sh" + echo '```' + } >> "$GITHUB_STEP_SUMMARY" + fi +else + echo "::error title=node_modules archive build failed::nix build ${attr} failed. See the log above for details." +fi + +exit "$status" diff --git a/scripts/ci-restore-node-modules.sh b/scripts/ci-restore-node-modules.sh new file mode 100644 index 00000000000..f756114252f --- /dev/null +++ b/scripts/ci-restore-node-modules.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -euo pipefail + +archive="${1:-}" + +if [[ -z "$archive" ]]; then + node_modules_output="$(nix build .#node-modules --no-link --print-out-paths)" + archive="$node_modules_output/node_modules.tar.zst" +fi + +if [[ ! -f "$archive" ]]; then + echo "Missing node_modules archive: $archive" >&2 + exit 1 +fi + +rm -rf node_modules +find packages e2e -mindepth 2 -maxdepth 2 -type d -name node_modules -prune -exec rm -rf {} + + +tar --zstd -xf "$archive" + +if [[ ! -f node_modules/.pnpm/lock.yaml || ! -x node_modules/.bin/vite ]]; then + echo "Restored node_modules archive did not create the expected pnpm layout" >&2 + exit 1 +fi + +echo "Restored node_modules from $archive"