Skip to content
Closed

3.x #1383

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 63 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,65 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
# GitHub Actions: weekly, grouped. SHA-pinning means most updates are just
# noise unless a real CVE lands; weekly cadence is plenty.
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
actions:
patterns:
- '*'

# Main npm tree (build, test, lint tooling). Weekly + grouped minor/patch so
# routine bumps land in one reviewable PR; majors stay separate.
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
groups:
dev-dependencies:
patterns:
- '*'
update-types:
- minor
- patch

# Consumer-shape verification harnesses under typescript/. These exist to
# catch packaging regressions, not to ship code — group them all together
# so we don't get six separate PRs every time @types/node bumps.
- package-ecosystem: npm
directory: /typescript
schedule:
interval: weekly
groups:
typescript-harness:
patterns:
- '*'

- package-ecosystem: npm
directory: /typescript/esm
schedule:
interval: weekly
groups:
typescript-harness:
patterns:
- '*'

- package-ecosystem: npm
directory: /typescript/esm-with-no-types
schedule:
interval: weekly
groups:
typescript-harness:
patterns:
- '*'

- package-ecosystem: npm
directory: /typescript/esm-with-specific-types
schedule:
interval: weekly
groups:
typescript-harness:
patterns:
- '*'
71 changes: 71 additions & 0 deletions .github/workflows/build-and-test-skip.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Build & Test

# Companion workflow for build-and-test.yml.
#
# Background: GitHub's required-status-check system leaves PRs stuck in
# "Waiting for status to be reported" when the workflow that would provide
# the check is skipped via paths-ignore. GitHub's own documented workaround
# is to define a twin workflow with the SAME workflow name and SAME job
# names, gated on the INVERSE path filter, that does nothing but succeed.
#
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
#
# RULES FOR EDITING THIS FILE:
#
# 1. The top-level `name:` must match build-and-test.yml exactly. GitHub
# identifies required checks by (workflow name, job name) tuple.
#
# 2. The `install` job's matrix and name must produce the SAME check
# names as build-and-test.yml: "install (20.x)", "install (22.x)",
# "install (24.x)", "install (25.x)".
#
# 3. The `paths` list below must be the INVERSE of the `paths-ignore`
# list in build-and-test.yml. If you exclude a path there, include it
# here (and vice versa). Mismatched lists = the real tests are
# skipped AND this passthrough doesn't fire = PR hangs.
#
# 4. Every job is a no-op that exits 0. Do NOT add real work here - this
# file exists purely to satisfy the required-check machinery.

on:
pull_request:
paths:
- '**/*.md'
- 'demos/**'
- 'website/**'
- 'LICENSE'
- '.gitattributes'
- '.editorconfig'
- '.prettierignore'
- '.prettierrc'
- '.nvmrc'
- '.gitignore'
- '.husky/**'
- '.pre-commit-config.yaml'
- 'osv-scanner.toml'
- '.github/ISSUE_TEMPLATE.md'
- '.github/PULL_REQUEST_TEMPLATE.md'
- '.github/FUNDING.yml'
- '.github/dependabot.yml'
- '.github/workflows/codeql-analysis.yml'
- '.github/workflows/dependency-review.yml'
- '.github/workflows/fuzz.yml'
- '.github/workflows/scorecard.yml'
- '.github/workflows/sign-release.yml'
- '.github/workflows/slsa-provenance.yml'

permissions:
contents: read

jobs:
install:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x, 22.x, 24.x, 25.x, 26.x]
steps:
- name: No-op (docs-only change, real tests skipped)
run: |
echo "Skipping build & test - change only touched documentation or"
echo "metadata files (see paths-ignore in build-and-test.yml)."
echo "Reporting success so the required status check doesn't hang."
187 changes: 169 additions & 18 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,198 @@
name: Build and Test
name: Build & Test

# The event triggers are configured as following:
# - on `main` -> trigger the workflow on every push
# - on any pull request -> trigger the workflow
# This is to avoid running the workflow twice on pull requests.
on:
push:
branches:
- main
- 3.x
- 2.x
# Skip on docs-only / metadata-only pushes. Keep this list in SYNC with
# build-and-test-skip.yml - that companion workflow reports success for
# the same required-check names when this one is skipped, otherwise PRs
# that only touch docs would hang forever on "Waiting for status to be
# reported" (GitHub's well-known paths-filter + required-check gotcha).
paths-ignore:
- '**/*.md'
- 'demos/**'
- 'website/**'
- 'LICENSE'
- '.gitattributes'
- '.editorconfig'
- '.prettierignore'
- '.prettierrc'
- '.nvmrc'
- '.gitignore'
- '.husky/**'
- '.pre-commit-config.yaml'
- 'osv-scanner.toml'
- '.github/ISSUE_TEMPLATE.md'
- '.github/PULL_REQUEST_TEMPLATE.md'
- '.github/FUNDING.yml'
- '.github/dependabot.yml'
- '.github/workflows/codeql-analysis.yml'
- '.github/workflows/dependency-review.yml'
- '.github/workflows/fuzz.yml'
- '.github/workflows/scorecard.yml'
- '.github/workflows/sign-release.yml'
- '.github/workflows/slsa-provenance.yml'
pull_request:
paths-ignore:
- '**/*.md'
- 'demos/**'
- 'website/**'
- 'LICENSE'
- '.gitattributes'
- '.editorconfig'
- '.prettierignore'
- '.prettierrc'
- '.nvmrc'
- '.gitignore'
- '.husky/**'
- '.pre-commit-config.yaml'
- 'osv-scanner.toml'
- '.github/ISSUE_TEMPLATE.md'
- '.github/PULL_REQUEST_TEMPLATE.md'
- '.github/FUNDING.yml'
- '.github/dependabot.yml'
- '.github/workflows/codeql-analysis.yml'
- '.github/workflows/dependency-review.yml'
- '.github/workflows/fuzz.yml'
- '.github/workflows/scorecard.yml'
- '.github/workflows/sign-release.yml'
- '.github/workflows/slsa-provenance.yml'

permissions:
contents: read

# Cancel superseded runs on the same PR to save minutes on rapid pushes.
# Pushes to protected branches are NOT cancelled - we want full CI history
# for every merged commit.
concurrency:
group: build-test-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
# Fast feedback: lint, jsdom, chromium-only browser test across Node versions.
# Runs on every push and every PR.
install:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x, 22.x, 24.x, 25.x]
node-version: [20.x, 22.x, 24.x, 25.x, 26.x]

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
with:
egress-policy: audit

- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache: npm

- name: Install Dependencies
run: npm ci
run: npm ci --ignore-scripts

# All three engines - test:ci runs the full browser matrix (no
# --project flag, unlike local `npm test`). DOMPurify's security
# posture depends on per-engine HTML parser behaviour being exercised,
# so this coverage is kept on every PR despite the download cost.
- name: Install Playwright Browsers
run: ./node_modules/.bin/playwright install --with-deps chromium firefox webkit

- name: Build
run: npm run build

- name: Verify dist/ matches src/
run: |
if ! git diff --quiet dist/; then
echo "::error::dist/ is out of sync with src/. The husky pre-commit hook should have rebuilt dist/ before commit. Did you commit without running 'npm install' first (which wires up the hook), or bypass hooks with --no-verify?"
echo "--- dist/ diff ---"
git diff --stat dist/
git diff dist/ | head -100
exit 1
fi
echo "dist/ matches src/ ✓"

- name: Lint
run: npm run lint

- name: Test
uses: GabrielBB/xvfb-action@v1.7
with:
run: npm run test:ci
env:
TEST_BROWSERSTACK: ${{ startsWith(matrix.node-version, '24') }}
TEST_PROBE_ONLY: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/2.x' }}
BS_USERNAME: ${{ secrets.BS_USERNAME }}
BS_ACCESSKEY: ${{ secrets.BS_ACCESSKEY }}
run: npm run test:ci

- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-node-${{ matrix.node-version }}
path: playwright-report/
retention-days: 7

- name: Verify TypeScript
run: npm run verify-typescript

# Browser diversity: chromium + firefox + webkit across Ubuntu, macOS, and
# Windows. Catches OS-specific rendering quirks (e.g. macOS WebKit ≈ real
# Safari engine, Windows font shaping, Linux-specific parser paths).
#
# Only runs on release branches (main, 2.x, 3.x) to conserve runner minutes.
# PRs get chromium-only coverage from the "install" job above, which is
# sufficient for catching regressions.
browser-matrix:
if: github.event_name == 'push'
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
with:
egress-policy: audit

- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Setup Node.js 25.x
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 25.x
cache: npm

- name: Install Dependencies
run: npm ci --ignore-scripts

- name: Install Playwright Browsers (Linux)
if: runner.os == 'Linux'
run: ./node_modules/.bin/playwright install --with-deps chromium firefox webkit

- name: Install Playwright Browsers (macOS / Windows)
if: runner.os != 'Linux'
run: ./node_modules/.bin/playwright install chromium firefox webkit

- name: Build
run: npm run build

- name: Run browser tests (all engines)
run: npm run test:browser

- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-${{ matrix.os }}
path: playwright-report/
retention-days: 7
Loading
Loading