mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-20 20:52:33 -04:00
* ci: run TS and Rust test jobs on Blacksmith runners Move the unit and e2e test jobs that were still on GitHub-hosted runners onto Blacksmith 8vcpu runners, matching the Blacksmith runners the lint/detect/ancillary jobs already use. - TS CI (ci.yml): test-smoke and the test/test-windows matrices now pass blacksmith-8vcpu-ubuntu-2404 / blacksmith-8vcpu-windows-2022 into the reusable test.yml. - Rust CI (pacquet-ci.yml): the test matrix ubuntu/windows legs move to the same Blacksmith labels. The macOS leg stays on macos-latest because Blacksmith offers no macOS runners. The Bencher upload workflow validates testbed names against strict ubuntu/windows/macos regexes, and both test workflows derived that slug by stripping "-latest" from the runner label, which no longer works for Blacksmith labels. test.yml now maps *ubuntu*/*windows* labels to the bare slug, and the Rust test job derives the slug (and its artifact name) from matrix.os_label instead. * test(cli): make stale-pin-dedupe robust on coarse-mtime filesystems The three stale_pin_dedupe tests each run two back-to-back installs, rewriting package.json between them, and assert the second install re-resolves the bumped version. pnpm and pacquet both gate their incremental-install fast path on a manifest's mtime being newer than the previous install (optimistic_repeat_install). The two installs run a few hundred milliseconds apart, so on a filesystem whose mtime granularity is coarser than that gap the rewritten manifest lands in the same mtime tick as the first install, the edit is not seen as newer, re-resolution is skipped, and the lockfile keeps the stale version. This surfaced on CI runners whose filesystem has second-granularity mtimes: the tests pass on ext4-backed runners and local dev but fail deterministically there. It is not a pacquet-vs-pnpm divergence — the mtime fast path behaves the same in both stacks, and forcing the second manifest's mtime equal to the lockfile's reproduces the failure locally regardless of which baseline (wall clock or lockfile mtime) the gate uses. Model the intended scenario explicitly: push the rewritten manifest's mtime well past the lockfile's so the second install reads it as a genuine later edit, matching what a user editing the manifest at a later time would produce. The assertions still exercise the real stale-pin-refresh behavior. * ci: use Blacksmith windows-2025 label for the test jobs Blacksmith's Windows runners run Windows Server 2025; the valid labels are blacksmith-<N>vcpu-windows-2025. The windows-2022 label matches no runner, so the Windows test legs would queue forever. Point them at the windows-2025 label instead. * ci: run the Build pnpr jobs on Blacksmith The two build-pnpr legs compile the pnpr binaries the TS test jobs consume; they gate those tests but were still on GitHub-hosted runners. Move them onto the same Blacksmith 8vcpu labels as the test jobs (ubuntu-2404 / windows-2025). build-pnpr.yml keys its disk-cleanup gate, cache, and artifact name off `runner.os`, which is unaffected by the label change.
222 lines
8.0 KiB
YAML
222 lines
8.0 KiB
YAML
name: TS CI
|
|
|
|
on:
|
|
# Run push CI only on the default branch. A branch that lives in this repo
|
|
# fires both a `push` and a `pull_request` event for the same commit, and
|
|
# both runs report the `TS CI / Success` context to that commit. Branch
|
|
# protection then sees two results for the required check, so a cancellation
|
|
# or flake on the push side (e.g. two pushes racing on the test.yml
|
|
# concurrency group) blocks the PR even when the pull_request run passed.
|
|
# Restricting push to `main` means PRs carry `TS CI / Success` only via
|
|
# their `pull_request` run (and the merge queue via `merge_group`); `main`
|
|
# is validated pre-merge by `merge_group` and re-checked post-merge here.
|
|
push:
|
|
branches:
|
|
- main
|
|
pull_request:
|
|
merge_group:
|
|
|
|
permissions:
|
|
contents: read # to fetch code (actions/checkout)
|
|
|
|
jobs:
|
|
changes:
|
|
name: TS CI / Detect Changes
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
outputs:
|
|
ts: ${{ steps.force.outputs.ts || steps.filter.outputs.ts }}
|
|
steps:
|
|
# In the merge queue the full suite must run: `TS CI / Compile & Lint`
|
|
# is itself a required check, and a skipped job never reports its
|
|
# context, which would leave the queue waiting forever. Forcing
|
|
# detection true also tests the merged result, which is the point of
|
|
# the queue.
|
|
- name: Force TS CI for merge queue
|
|
if: github.event_name == 'merge_group'
|
|
id: force
|
|
run: echo "ts=true" >> "$GITHUB_OUTPUT"
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
if: github.event_name != 'merge_group'
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
|
if: github.event_name != 'merge_group'
|
|
id: filter
|
|
with:
|
|
# The TypeScript pnpm stack lives under pnpm11/, plus the
|
|
# workspace-root tooling that drives its build/lint/test.
|
|
filters: |
|
|
ts:
|
|
- 'pnpm11/**'
|
|
- '.meta-updater/**'
|
|
- '__patches__/**'
|
|
- 'package.json'
|
|
- 'pnpm-workspace.yaml'
|
|
- 'pnpm-lock.yaml'
|
|
- '.pnpmfile.cjs'
|
|
- 'eslint.config.mjs'
|
|
- 'tsconfig.lint.json'
|
|
- 'cspell.json'
|
|
- '.github/workflows/ci.yml'
|
|
- '.github/workflows/test.yml'
|
|
- '.github/workflows/build-pnpr.yml'
|
|
- '.github/scripts/**'
|
|
|
|
compile-and-lint:
|
|
needs: changes
|
|
# Run only when TypeScript-relevant files changed. Every PR (same-repo or
|
|
# fork) is covered by its pull_request run, and push only fires on main, so
|
|
# there are no duplicate build jobs to guard against here.
|
|
if: ${{ !cancelled() && needs.changes.outputs.ts == 'true' }}
|
|
|
|
name: TS CI / Compile & Lint
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
|
|
steps:
|
|
- name: Checkout Commit
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- name: Install pnpm
|
|
uses: pnpm/setup@77cf06832101b3ac8c65caaf76a21643936d07a4
|
|
- name: Compile TypeScript
|
|
run: pn compile-only
|
|
- name: Lint
|
|
run: pn lint
|
|
- name: Package compiled artifacts
|
|
shell: bash
|
|
run: |
|
|
mapfile -d '' -t lib_dirs < <(find . -type d -name lib -not -path '*/node_modules/*' -print0)
|
|
mapfile -d '' -t tsbuildinfo_files < <(find . -name 'tsconfig.tsbuildinfo' -not -path '*/node_modules/*' -print0)
|
|
tar -czf compiled.tar.gz --exclude='node_modules' "${lib_dirs[@]}" "${tsbuildinfo_files[@]}" pnpm11/pnpm/dist
|
|
- name: Upload compiled artifacts
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: compiled-packages
|
|
path: compiled.tar.gz
|
|
retention-days: 1
|
|
|
|
# Build the pnpr binaries once per OS via a per-OS reusable workflow (not a
|
|
# single matrix job) so each platform's test jobs gate only on their own
|
|
# build. `needs` can only target a whole job, never an individual matrix
|
|
# leg, so a matrix build would make the ubuntu tests wait for the slower
|
|
# windows build and vice versa.
|
|
build-pnpr-linux:
|
|
needs: changes
|
|
if: ${{ !cancelled() && needs.changes.outputs.ts == 'true' }}
|
|
name: TS CI / Build pnpr
|
|
uses: ./.github/workflows/build-pnpr.yml
|
|
with:
|
|
os: blacksmith-8vcpu-ubuntu-2404
|
|
|
|
build-pnpr-windows:
|
|
needs: changes
|
|
if: ${{ !cancelled() && needs.changes.outputs.ts == 'true' }}
|
|
name: TS CI / Build pnpr
|
|
uses: ./.github/workflows/build-pnpr.yml
|
|
with:
|
|
os: blacksmith-8vcpu-windows-2025
|
|
|
|
test-smoke:
|
|
name: TS CI / Test / ubuntu
|
|
needs: [compile-and-lint, build-pnpr-linux]
|
|
uses: ./.github/workflows/test.yml
|
|
with:
|
|
node: '24.0.0'
|
|
node_major: '24'
|
|
platform: blacksmith-8vcpu-ubuntu-2404
|
|
garnet: true
|
|
secrets:
|
|
GARNET_API_TOKEN: ${{ secrets.GARNET_API_TOKEN }}
|
|
|
|
test:
|
|
name: TS CI / Test / ${{ matrix.platform_label }}
|
|
needs: test-smoke
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- node: '22.13.0'
|
|
node_major: '22'
|
|
platform: blacksmith-8vcpu-ubuntu-2404
|
|
platform_label: ubuntu
|
|
test_chunk: '1'
|
|
test_chunk_total: '1'
|
|
- node: '26.5.0'
|
|
node_major: '26'
|
|
platform: blacksmith-8vcpu-ubuntu-2404
|
|
platform_label: ubuntu
|
|
test_chunk: '1'
|
|
test_chunk_total: '1'
|
|
uses: ./.github/workflows/test.yml
|
|
with:
|
|
node: ${{ matrix.node }}
|
|
node_major: ${{ matrix.node_major }}
|
|
platform: ${{ matrix.platform }}
|
|
test_chunk: ${{ matrix.test_chunk }}
|
|
test_chunk_total: ${{ matrix.test_chunk_total }}
|
|
|
|
# Windows is the slowest platform. Gate it only on compile-and-lint so its
|
|
# shards run in parallel with the ubuntu smoke job, instead of waiting for
|
|
# the smoke job like the other Node.js versions do.
|
|
test-windows:
|
|
name: TS CI / Test / ${{ matrix.platform_label }}
|
|
needs: [compile-and-lint, build-pnpr-windows]
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- node: '22.13.0'
|
|
node_major: '22'
|
|
platform: blacksmith-8vcpu-windows-2025
|
|
platform_label: windows 1/3
|
|
test_chunk: '1'
|
|
test_chunk_total: '3'
|
|
- node: '22.13.0'
|
|
node_major: '22'
|
|
platform: blacksmith-8vcpu-windows-2025
|
|
platform_label: windows 2/3
|
|
test_chunk: '2'
|
|
test_chunk_total: '3'
|
|
- node: '22.13.0'
|
|
node_major: '22'
|
|
platform: blacksmith-8vcpu-windows-2025
|
|
platform_label: windows 3/3
|
|
test_chunk: '3'
|
|
test_chunk_total: '3'
|
|
uses: ./.github/workflows/test.yml
|
|
with:
|
|
node: ${{ matrix.node }}
|
|
node_major: ${{ matrix.node_major }}
|
|
platform: ${{ matrix.platform }}
|
|
test_chunk: ${{ matrix.test_chunk }}
|
|
test_chunk_total: ${{ matrix.test_chunk_total }}
|
|
|
|
# Single aggregate gate — the only TS CI context branch protection needs
|
|
# to require. Listing the individual jobs as required checks does not
|
|
# work: they skip on non-TypeScript PRs, and a matrix job skipped at the
|
|
# job level never expands its `${{ matrix.* }}` name, so the per-platform
|
|
# contexts it would report never appear and the PR blocks forever waiting
|
|
# for them. This job always runs (it reports under a static name in every
|
|
# state) and fails only if a dependency actually failed or was cancelled —
|
|
# skipped dependencies count as a pass.
|
|
success:
|
|
name: TS CI / Success
|
|
if: ${{ always() }}
|
|
needs:
|
|
- changes
|
|
- compile-and-lint
|
|
- build-pnpr-linux
|
|
- build-pnpr-windows
|
|
- test-smoke
|
|
- test
|
|
- test-windows
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404
|
|
steps:
|
|
- name: Fail if any dependency failed or was cancelled
|
|
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
|
|
run: exit 1
|