zizmor's self-repository audit flags every `uses: ./.github/...` reference now that GitHub has a dedicated `$/` form. The `$/` form resolves against the workflow's own commit rather than the runtime checkout, so it cannot load an action cloned into the workspace at runtime, and GitHub treats it as pinned. Rewrites all 22 references (18 local actions, 4 reusable workflow calls). With the `$/` form the runner downloads the whole repository as an action archive at job setup, and that download fails on any broken symlink in the tree. The four broken symlinks were all test fixtures: the directory-fetcher and cafs tests now copy their fixture into a temp dir and create the broken symlink there, and the has-not-outdated-deps fixture drops two dangling node_modules links that `pnpm outdated` never followed. pnpm's GitHub Actions dependency discovery only followed `./` references into local actions and reusable workflows; both stacks now follow `$/` too.
220 lines
8.0 KiB
YAML
220 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
if: github.event_name != 'merge_group'
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
|
|
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Install pnpm
|
|
uses: pnpm/setup@703c52620218391530e48b9e8870d5c0082e1b9b # v2.1.0
|
|
- name: Test release publication scripts
|
|
run: |
|
|
.github/scripts/npm-package-publication-state.test.sh
|
|
.github/scripts/npm-staged-publication.test.sh
|
|
- 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:
|
|
name: TS CI / Test / ${{ matrix.platform_label }}
|
|
needs: [compile-and-lint, build-pnpr-linux]
|
|
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: '24.0.0'
|
|
node_major: '24'
|
|
platform: blacksmith-8vcpu-ubuntu-2404
|
|
platform_label: ubuntu
|
|
test_chunk: '1'
|
|
test_chunk_total: '1'
|
|
garnet: true
|
|
- node: '26.8.1'
|
|
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 }}
|
|
garnet: ${{ matrix.garnet == true }}
|
|
secrets:
|
|
GARNET_API_TOKEN: ${{ secrets.GARNET_API_TOKEN }}
|
|
|
|
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
|
|
- 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
|