Publish package versions independently from Changesets #76
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| run: bun run changeset:status -- --since=origin/develop | |
| - name: Install checksum-pinned wasm-pack | |
| run: bun scripts/install-wasm-pack.ts | |
| - name: Tooling contracts | |
| 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 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: Deterministic performance gates | |
| 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: Build and pack once | |
| run: bun run release:prepare -- --mode release --output test-results/release-artifacts | |
| - 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: 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: 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: 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: Enforce delivery budgets | |
| run: bun scripts/size-report.ts check --artifacts test-results/release-artifacts | |
| - name: Upload validated delivery evidence | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: delivery-size-evidence | |
| path: test-results/delivery-size/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 validated delivery evidence | |
| uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5 | |
| with: | |
| name: delivery-size-evidence | |
| path: test-results/delivery-size | |
| - 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 | |
| required: | |
| name: Required CI | |
| if: always() | |
| needs: | |
| - preflight | |
| - unit-coverage | |
| - artifact-build | |
| - packed-consumers | |
| - bundler-consumers | |
| - delivery-size | |
| - docs-build | |
| - browser-smoke | |
| 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 }} | |
| 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 | |
| if [ "$DOCS_REQUIRED" = "true" ]; then | |
| test "$DOCS" = success | |
| test "$BROWSER" = success | |
| else | |
| test "$DOCS_REQUIRED" = "false" | |
| test "$DOCS" = skipped | |
| test "$BROWSER" = skipped | |
| fi |