Skip to content

Version npm packages #106

Version npm packages

Version npm packages #106

Workflow file for this run

name: CI
on:
push:
branches: [develop]
pull_request:
branches: [develop]
concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
BUN_VERSION: "1.3.14"
NODE_VERSION: "24.3.0"
NPM_VERSION: "11.18.0"
RUST_VERSION: "1.96.0"
WASM_TARGET: "wasm32-unknown-unknown"
WASM_PACK_VERSION: "0.15.0"
CARGO_AUDIT_VERSION: "0.22.2"
CARGO_LLVM_COV_VERSION: "0.8.7"
jobs:
preflight:
name: Preflight
runs-on: ubuntu-latest
timeout-minutes: 20
outputs:
docs_required: ${{ steps.paths.outputs.docs_required }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install pinned npm
run: npm install --global "npm@$NPM_VERSION"
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Classify documentation impact
id: paths
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
run: bun scripts/ci-paths.ts >> "$GITHUB_OUTPUT"
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Assert clean checkout and exact toolchain
run: |
test -z "$(git status --porcelain --untracked-files=all)"
bun scripts/verify-clean-build.ts --assert-absent
test "$(bun --version)" = "$BUN_VERSION"
test "$(node --version)" = "v$NODE_VERSION"
test "$(npm --version)" = "$NPM_VERSION"
test "$(rustc --version | cut -d' ' -f2)" = "$RUST_VERSION"
- name: Changeset status
if: github.event_name != 'pull_request' || github.head_ref != 'changeset-release/develop'
run: bun run changeset:status -- --since=origin/develop
- name: Install checksum-pinned wasm-pack
run: bun scripts/install-wasm-pack.ts
- name: Tooling contracts
env:
SKIP_CHANGESET_STATUS: ${{ github.event_name == 'pull_request' && github.head_ref == 'changeset-release/develop' }}
run: bun run test:tooling
- name: Import cycles
run: bun run check:cycles
- name: JavaScript dependency audit
run: bun run audit:js
- name: Cache cargo-audit
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/bin/cargo-audit
~/.cargo/registry
~/.cargo/git
key: cargo-audit-${{ runner.os }}-${{ env.RUST_VERSION }}-${{ env.CARGO_AUDIT_VERSION }}
- name: Install cargo-audit
run: command -v cargo-audit >/dev/null || cargo install cargo-audit --version "$CARGO_AUDIT_VERSION" --locked
- name: Rust dependency audit
working-directory: packages/wasm
run: cargo audit
- name: Lint
run: bun run lint
unit-coverage:
name: Unit Tests & Coverage
needs: artifact-build
runs-on: ubuntu-latest
timeout-minutes: 35
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Cache Rust and WASM compilation
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: packages/wasm/target
key: wasm-target-${{ runner.os }}-${{ env.RUST_VERSION }}-${{ hashFiles('rust-toolchain.toml', 'packages/wasm/Cargo.lock', 'packages/wasm/Cargo.toml', 'packages/wasm/src/**/*.rs') }}
restore-keys: |
wasm-target-${{ runner.os }}-${{ env.RUST_VERSION }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Install coverage toolchain
run: cargo install cargo-llvm-cov --version "$CARGO_LLVM_COV_VERSION" --locked
- name: Install benchmark browser
run: bun run browser:install
- name: Download canonical tarballs
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: canonical-release-artifacts
path: test-results/release-artifacts
- name: Verify and hydrate canonical package outputs
env:
ARTIFACT_DIGEST: ${{ needs.artifact-build.outputs.artifact_digest }}
run: |
test -n "$ARTIFACT_DIGEST"
bun scripts/hydrate-release-artifacts.ts test-results/release-artifacts
- name: Unit and Rust tests
run: |
bun test packages test/browser/canvas-assertions.test.ts scripts/public-api.test.ts scripts/conformance.test.ts scripts/docs.test.ts bench/test
cargo test --manifest-path packages/wasm/Cargo.toml
- name: Type checks and public API
run: |
bun run typecheck
bun run api:check
- name: Benchmark smoke and safety ceilings (not regression evidence)
run: bun run --filter '@sheetwrite/bench' bench:verify
- name: Source coverage
run: bun run test:coverage
- name: Upload coverage evidence on failure
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: unit-coverage-failure-evidence
path: |
test-results/
coverage/
if-no-files-found: warn
artifact-build:
name: Canonical Artifacts
needs: preflight
runs-on: ubuntu-latest
timeout-minutes: 25
outputs:
artifact_digest: ${{ steps.upload.outputs.artifact-digest }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install pinned npm
run: npm install --global "npm@$NPM_VERSION"
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Cache Rust and WASM compilation
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: packages/wasm/target
key: wasm-target-${{ runner.os }}-${{ env.RUST_VERSION }}-${{ hashFiles('rust-toolchain.toml', 'packages/wasm/Cargo.lock', 'packages/wasm/Cargo.toml', 'packages/wasm/src/**/*.rs') }}
restore-keys: |
wasm-target-${{ runner.os }}-${{ env.RUST_VERSION }}-
- name: Cache release verification tools
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/bin/cargo-audit
~/.cargo/bin/cargo-llvm-cov
~/.cargo/registry
~/.cargo/git
key: release-tools-${{ runner.os }}-${{ env.RUST_VERSION }}-${{ env.CARGO_AUDIT_VERSION }}-${{ env.CARGO_LLVM_COV_VERSION }}
- name: Install release verification tools
run: |
command -v cargo-audit >/dev/null || cargo install cargo-audit --version "$CARGO_AUDIT_VERSION" --locked
command -v cargo-llvm-cov >/dev/null || cargo install cargo-llvm-cov --version "$CARGO_LLVM_COV_VERSION" --locked
- name: Install dependencies and wasm-pack
run: |
bun install --frozen-lockfile
bun scripts/install-wasm-pack.ts
- name: Validate compatibility test set
run: bun run compatibility:validate
- name: Build and pack once
run: bun run release:prepare -- --mode release --output test-results/release-artifacts
- name: Verify local compatibility results
run: bun run compatibility:check -- --allow-unclaimed
- name: Verify manifest before upload
run: bun run release:verify-artifacts -- --input test-results/release-artifacts
- name: Upload canonical tarballs
id: upload
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: canonical-release-artifacts
path: test-results/release-artifacts/
if-no-files-found: error
retention-days: 7
packed-consumers:
name: Packed Consumers
needs: artifact-build
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install pinned npm
run: npm install --global "npm@$NPM_VERSION"
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Install Chromium
run: bun run browser:install:chromium
- name: Download canonical tarballs
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: canonical-release-artifacts
path: test-results/release-artifacts
- name: Verify downloaded bytes and digest contract
env:
ARTIFACT_DIGEST: ${{ needs.artifact-build.outputs.artifact_digest }}
run: |
test -n "$ARTIFACT_DIGEST"
bun run release:verify-artifacts -- --input test-results/release-artifacts
- name: Test locked packed consumers
run: bun run verify:packed -- --artifacts test-results/release-artifacts --locked
bundler-consumers:
name: Bundler Consumers
needs: artifact-build
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install pinned npm
run: npm install --global "npm@$NPM_VERSION"
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Install Chromium
run: bun run browser:install:chromium
- name: Download canonical tarballs
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: canonical-release-artifacts
path: test-results/release-artifacts
- name: Verify downloaded bytes and digest contract
env:
ARTIFACT_DIGEST: ${{ needs.artifact-build.outputs.artifact_digest }}
run: |
test -n "$ARTIFACT_DIGEST"
bun run release:verify-artifacts -- --input test-results/release-artifacts
- name: Test locked bundler consumers
run: bun run verify:bundlers -- --artifacts test-results/release-artifacts --locked
delivery-size:
name: Delivery Size
needs: artifact-build
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install pinned npm
run: npm install --global "npm@$NPM_VERSION"
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Install Chromium
run: bun run browser:install:chromium
- name: Download canonical tarballs
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: canonical-release-artifacts
path: test-results/release-artifacts
- name: Verify downloaded bytes and digest contract
env:
ARTIFACT_DIGEST: ${{ needs.artifact-build.outputs.artifact_digest }}
run: |
test -n "$ARTIFACT_DIGEST"
bun run release:verify-artifacts -- --input test-results/release-artifacts
- name: Record delivery sizes
run: bun scripts/size-report.ts report --artifacts test-results/release-artifacts
- name: Upload delivery size evidence
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: size-evidence
path: scripts/size-report.json
if-no-files-found: error
retention-days: 7
docs-build:
name: Production Docs
needs: [preflight, artifact-build, delivery-size]
if: needs.preflight.outputs.docs_required == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Download canonical tarballs
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: canonical-release-artifacts
path: test-results/release-artifacts
- name: Download delivery size evidence
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: size-evidence
path: scripts
- name: Verify and hydrate canonical package outputs
env:
ARTIFACT_DIGEST: ${{ needs.artifact-build.outputs.artifact_digest }}
run: |
test -n "$ARTIFACT_DIGEST"
bun scripts/hydrate-release-artifacts.ts test-results/release-artifacts
- name: Generate, check, and build production docs
run: |
bun run docs:generate
bun run --filter '@sheetwrite/docs-start' typecheck
bun run --filter '@sheetwrite/docs-start' build
- name: Upload production docs
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: production-docs
path: docs/dist/client/
if-no-files-found: error
retention-days: 1
browser-smoke:
name: Browser Smoke
needs: docs-build
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install dependencies and browser engines
run: |
bun install --frozen-lockfile
bun run browser:install
- name: Download production docs
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: production-docs
path: docs/dist/client
- name: Exercise production site
run: bun run test:browser
- name: Upload browser evidence on failure
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: browser-failure-evidence
path: |
test-results/playwright/
playwright-report/
if-no-files-found: warn
controlled-performance:
name: Matched Zero-Regression Performance
needs: artifact-build
runs-on: sheetwrite-perf-i9-12900h-cachyos
timeout-minutes: 90
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
bun-version: ${{ env.BUN_VERSION }}
- name: Install exact dependencies and benchmark browser
run: |
bun install --frozen-lockfile
bunx playwright install chromium
- name: Build controlled render harness
run: bun run --filter '@sheetwrite/bench' bench:render:prepare
- name: Capture repeated full matched samples
working-directory: bench
run: |
bun run src/render-driver.ts \
--rounds 10 \
--output results/render-fresh.json \
--markdown-output results/render-fresh.md
- name: Require matched zero-regression decision
working-directory: bench
run: |
bun run src/check.ts \
--baseline results/render-baseline.json \
--fresh results/render-fresh.json \
--power-mode balanced \
--concurrency 1
- name: Upload controlled raw samples
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: controlled-performance-raw-${{ github.sha }}
path: |
bench/results/render-fresh.json
bench/results/render-fresh.md
if-no-files-found: error
retention-days: 30
required:
name: Required CI
if: always()
needs:
- preflight
- unit-coverage
- artifact-build
- packed-consumers
- bundler-consumers
- delivery-size
- docs-build
- browser-smoke
- controlled-performance
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Require every CI branch
env:
PREFLIGHT: ${{ needs.preflight.result }}
UNIT_COVERAGE: ${{ needs.unit-coverage.result }}
ARTIFACT_BUILD: ${{ needs.artifact-build.result }}
PACKED: ${{ needs.packed-consumers.result }}
BUNDLERS: ${{ needs.bundler-consumers.result }}
SIZE: ${{ needs.delivery-size.result }}
DOCS: ${{ needs.docs-build.result }}
BROWSER: ${{ needs.browser-smoke.result }}
PERFORMANCE: ${{ needs.controlled-performance.result }}
DOCS_REQUIRED: ${{ needs.preflight.outputs.docs_required }}
run: |
test "$PREFLIGHT" = success
test "$UNIT_COVERAGE" = success
test "$ARTIFACT_BUILD" = success
test "$PACKED" = success
test "$BUNDLERS" = success
test "$SIZE" = success
test "$PERFORMANCE" = success
if [ "$DOCS_REQUIRED" = "true" ]; then
test "$DOCS" = success
test "$BROWSER" = success
else
test "$DOCS_REQUIRED" = "false"
test "$DOCS" = skipped
test "$BROWSER" = skipped
fi