Skip to content

feat(versioning): diff nesting changes in place #9700

feat(versioning): diff nesting changes in place

feat(versioning): diff nesting changes in place #9700

Workflow file for this run

name: build
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, edited]
permissions:
contents: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
build:
name: Build
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 100
persist-credentials: false
- uses: voidzero-dev/setup-vp@3754dd7dbdb32bd8f6d28b6043de13ad3a75f21f # v1.21.1
with:
node-version-file: ".node-version"
cache: true
- uses: $/.github/actions/typst-cache
- name: Select task-cache generation
id: task-cache-generation
# Start fresh each ISO week instead of carrying old task results forever.
run: echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT"
- name: Restore build task cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: node_modules/.vite/task-cache
# Immutable per merge commit: reruns reuse it without duplicate uploads.
key: vite-task-v3-${{ runner.os }}-${{ runner.arch }}-${{ steps.task-cache-generation.outputs.week }}-${{ github.sha }}
restore-keys: |
vite-task-v3-${{ runner.os }}-${{ runner.arch }}-${{ steps.task-cache-generation.outputs.week }}-
# Unchanged Rust uses the cached WASM even when the TS build misses.
# Other package outputs are restored by Vite Task's own fingerprints.
- name: Build packages
run: vp run -r build
- name: Lint packages
run: vp run lint
- name: Run unit tests
# Always execute tests: only build results are reusable across CI runs.
run: vp run --no-cache test
- name: Run Next.js integration test (production build)
run: NEXTJS_TEST_MODE=build vp test run src/unit/nextjs/serverUtil.test.ts
working-directory: tests
- name: Upload webpack stats artifact (editor)
uses: relative-ci/agent-upload-artifact-action@a2b5741b4f7e6a989c84ec1a3059696b23c152e5 # v2
with:
webpackStatsFile: ./playground/dist/webpack-stats.json
artifactName: relative-ci-artifacts-editor
- name: Soft release
id: soft-release
# xl-typst-compiler is excluded: its wasm makes the package ~25MB,
# which pkg.pr.new rejects (413; multipart uploads are whitelisted -
# https://github.com/stackblitz-labs/pkg.pr.new/blob/main/.whitelist).
# Preview installs of the PDF exporter therefore lack the compiler
# until the repo is whitelisted or the wasm ships separately.
# TODO disabled only for AI branch--compact
run: |
packages=()
for dir in ./packages/*/; do
if [[ "$dir" != *"/xl-typst-compiler/"* ]]; then
packages+=("${dir%/}")
fi
done
vp dlx pkg-pr-new publish "${packages[@]}"
build-typst-compiler:
# The one package the e2e suite consumes through build outputs instead of
# src/ aliases: @blocknote/xl-typst-compiler (its /pkg and /wasm subpaths
# are wasm build artifacts - see tests/vite.config.browser.ts). Built once
# on a bare runner - the Playwright container has no C toolchain for the
# Rust build - and shared with the shards as an artifact.
name: Build Typst compiler
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 100
persist-credentials: false
- uses: voidzero-dev/setup-vp@3754dd7dbdb32bd8f6d28b6043de13ad3a75f21f # v1.21.1
with:
node-version-file: ".node-version"
cache: true
- uses: $/.github/actions/typst-cache
# Compiles the Rust wasm when missing/stale (rustup is bootstrapped by
# the build task itself) plus the TS wrapper's dist/types.
- name: Build Typst compiler package
run: vp run --filter @blocknote/xl-typst-compiler build
- name: Upload compiler build outputs
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: typst-compiler-build
path: |
packages/xl-typst-compiler/pkg
packages/xl-typst-compiler/dist
packages/xl-typst-compiler/types
include-hidden-files: true
e2e:
# Vitest Browser Mode runs in the Playwright Linux container — the same
# environment as the local Docker run — so behaviour matches local dev.
# The suite resolves every `@blocknote/*` import to its `src/` via the
# aliases in `tests/vite.config.browser.ts` (vite transpiles the package
# sources on the fly), so the packages do NOT need to be built to `dist`
# first. PDF tests run separately below so these shards start immediately,
# without waiting for a cold Rust build.
name: "E2E - ${{ matrix.browser }} (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})"
runs-on: ubuntu-latest
timeout-minutes: 30
container:
image: mcr.microsoft.com/playwright:v1.60.0-noble
strategy:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit]
shardIndex: [1, 2]
shardTotal: [2]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 100
persist-credentials: false
- uses: voidzero-dev/setup-vp@3754dd7dbdb32bd8f6d28b6043de13ad3a75f21f # v1.21.1
with:
node-version-file: ".node-version"
cache: true
# Build jobs populate this same dependency cache. Avoid six redundant
# ~500 MB uploads racing on a cold key (observed up to 72s per shard).
cache-save: false
# No preview server: Vitest Browser Mode serves the tests + mounted example
# apps itself. `--browser` selects this matrix job's browser and
# `--shard=<index>/<total>` splits that browser's test files across two
# parallel machines. Each shard records a machine-readable `blob` report
# (named per browser+shard so they don't collide); the `merge-reports` job
# stitches every browser's shards into one HTML report afterwards.
- name: Run e2e tests (${{ matrix.browser }} ${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
run: HOME=/root vp test -c vite.config.browser.ts --run --browser ${{ matrix.browser }} --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --reporter=default --reporter=blob --outputFile.blob=blob-report/blob-${{ matrix.browser }}-${{ matrix.shardIndex }}.json
env:
BLOCKNOTE_E2E_GROUP: non-pdf
working-directory: tests
- name: Upload blob report (${{ matrix.browser }} ${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: ${{ !cancelled() }}
with:
name: blob-report-${{ matrix.browser }}-${{ matrix.shardIndex }}
path: tests/blob-report/
retention-days: 1
- name: Upload failure artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: ${{ failure() }}
with:
name: e2e-attachments-${{ matrix.browser }}-${{ matrix.shardIndex }}
path: tests/.vitest-attachments/
# The attachments dir is a dot-directory; without this the action
# silently uploads nothing ("No files were found").
include-hidden-files: true
retention-days: 7
e2e-pdf:
# Only these two files load the compiled WASM. All other browser coverage
# runs concurrently with build-typst-compiler in the e2e job above.
name: "E2E PDF - ${{ matrix.browser }}"
runs-on: ubuntu-latest
timeout-minutes: 30
needs: build-typst-compiler
container:
image: mcr.microsoft.com/playwright:v1.60.0-noble
strategy:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 100
persist-credentials: false
- uses: voidzero-dev/setup-vp@3754dd7dbdb32bd8f6d28b6043de13ad3a75f21f # v1.21.1
with:
node-version-file: ".node-version"
cache: true
cache-save: false
- name: Download Typst compiler build outputs
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: typst-compiler-build
path: packages/xl-typst-compiler
- name: Run PDF browser tests
run: HOME=/root vp test -c vite.config.browser.ts --run typstPdfImages.test.tsx compileTypst.browser.test.ts --browser ${{ matrix.browser }} --reporter=default --reporter=blob --outputFile.blob=blob-report/blob-pdf-${{ matrix.browser }}.json
working-directory: tests
- name: Upload PDF blob report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: ${{ !cancelled() }}
with:
name: blob-report-pdf-${{ matrix.browser }}
path: tests/blob-report/
retention-days: 1
- name: Upload failure artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: ${{ failure() }}
with:
name: e2e-attachments-pdf-${{ matrix.browser }}
path: tests/.vitest-attachments/
include-hidden-files: true
retention-days: 7
merge-reports:
# Stitch every browser+shard blob report into a single navigable HTML
# report (the Vitest equivalent of `playwright merge-reports`). Runs even
# when a shard failed, so the report always covers every browser.
name: "E2E Report"
runs-on: ubuntu-latest
needs: [e2e, e2e-pdf]
if: ${{ !cancelled() }}
timeout-minutes: 15
# Keep the browser configuration to resolve the recorded projects, but
# merging replays results without launching browsers or needing their image.
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 100
persist-credentials: false
- uses: voidzero-dev/setup-vp@3754dd7dbdb32bd8f6d28b6043de13ad3a75f21f # v1.21.1
with:
node-version-file: ".node-version"
cache: true
cache-save: false
# Gather every shard's blob into one directory (blob-report-chromium-1, …).
- name: Download blob reports
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
path: tests/blob-report
pattern: blob-report-*
merge-multiple: true
# Re-emit a single HTML report from the merged blobs (no tests are run).
# Blob source paths use the producer containers' /__w checkout location.
# Vitest also derives result IDs from the canonical root, so a forward
# symlink alone loses its success/failure lookup. Move the disposable
# checkout and leave a backlink for artifact actions using GITHUB_WORKSPACE.
- name: Map container report paths
run: |
repo_name="${GITHUB_REPOSITORY#*/}"
container_root="/__w/$repo_name/$repo_name"
sudo mkdir -p "$(dirname "$container_root")"
sudo mv "$GITHUB_WORKSPACE" "$container_root"
sudo ln -s "$container_root" "$GITHUB_WORKSPACE"
- name: Merge into HTML report
run: vp test -c vite.config.browser.ts --mergeReports=blob-report --reporter=html
working-directory: tests
- name: Upload merged HTML report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: ${{ !cancelled() }}
with:
name: e2e-report
path: tests/playwright-report/
retention-days: 7
deploy-report:
# Publish the merged report to a GitHub Pages PR preview and comment the
# link on the PR (Vercel-style). Pages serves it over HTTP, so the report's
# data loads correctly — unlike opening the downloaded artifact over file://
# (the @vitest/ui report fetches its data and is blocked by CORS there).
#
# Default `needs` semantics: this runs only when `merge-reports` succeeded
# (i.e. a report exists) — but regardless of whether the tests passed, so a
# red run still gets a navigable preview. Skipped for fork PRs, whose
# read-only token can't push to gh-pages or comment (they keep the artifact).
name: "E2E Report Preview"
runs-on: ubuntu-latest
needs: merge-reports
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }}
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Download merged report
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: e2e-report
path: e2e-report
# Deploys to the `gh-pages` branch under `pr-preview/pr-<N>/` and posts a
# sticky comment with the URL. The companion `pr-preview-cleanup` workflow
# removes it when the PR closes.
- name: Deploy report to PR preview
uses: rossjrw/pr-preview-action@ffa7509e91a3ec8dfc2e5536c4d5c1acdf7a6de9 # v1
with:
source-dir: e2e-report
preview-branch: gh-pages
umbrella-dir: pr-preview
action: deploy