Skip to content

Add collaborative spreadsheet blocks inside documents #539

Add collaborative spreadsheet blocks inside documents

Add collaborative spreadsheet blocks inside documents #539

Workflow file for this run

name: WASM bundle size
# Phase 5 M-P9 piece B — bundle-size CI gate.
#
# Builds the frontend with `trunk build --release` (so wasm-opt=z
# runs, matching the deployed artifact), measures the gzipped
# `*_bg.wasm`, and fails the build if it exceeds the threshold
# codified in design/performance-budgets.md.
#
# Threshold tracks the current measured baseline plus ~7% headroom,
# not the aspirational 800 KB figure. A separate optimization
# track tightens it; this gate just stops further regression. See
# the "Ratchet, not anchor" subsection in performance-budgets.md.
on:
push:
# `main` is the default branch of the public repo (the pre-OSS
# private repo used `master`). With the stale name this gate never
# ran on default-branch pushes, so the bundle drifted ~5.4 KB past
# the limit unseen — see the 2026-07-08 rebaseline below.
branches: [main]
pull_request:
concurrency:
group: bundle-size-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
# Hard threshold in bytes — change this only in lockstep with
# `design/performance-budgets.md`'s "CI gate threshold" row. The
# gate steps DOWN as bundle-shrinking work lands; bumps UP require
# an explicit, doc-noted reason.
#
# 2026-06-03 re-baseline: the measured bundle reached 2,168,852 B
# gzipped (~2.07 MiB) — ~2 weeks of accumulated Phase-5 features off
# the stale 1.87 MB / 2026-05-21 baseline (link sharing was the last
# ~10–30 KB that crossed the old 2.0 MiB gate).
#
# 2026-06-04 ratchet DOWN: deploy builds now apply size-optimizing
# profile overrides (CARGO_PROFILE_RELEASE_OPT_LEVEL=z, LTO=fat,
# CODEGEN_UNITS=1, STRIP, PANIC=abort — see the "Build frontend" step
# and Dockerfile Stage 2) plus wasm-opt --all-features. Measured
# bundle dropped to ~1,425,747 B gzipped (~1.36 MiB), a ~34% cut.
# Gate set to the new measurement + ~9% headroom (absorbs local↔CI
# toolchain drift); tighten after the first CI baseline confirms.
# See performance-budgets.md → "Bundle size".
#
# 2026-07-02 rebaseline: #142 Phase 2 mail-merge added the values-fill
# form + the placeholder DTO on TemplateItem, pushing the measured
# bundle to 1,561,511 B — ~11 KB over the previous 1,550,000 limit.
# Bumping to 1,600,000 (~1.52 MiB) with ~40 KB headroom to absorb
# Phase 3 (Sample gallery) without a further churn.
#
# 2026-07-04 rebaseline: #137 Kanban Phase 2 added the card modal,
# click observer, and column/card commands; #136 Calendar fixes
# added the data-atom-size DOM walk handlers. Measured bundle
# 1,616,644 B — ~17 KB over the previous 1,600,000 limit.
# Bumping to 1,650,000 (~1.57 MiB) with ~33 KB headroom for
# incremental Phase 5 work.
#
# 2026-07-08 rebaseline: the `push` trigger above was still `master`
# after the 2026-07-07 re-publish switched the default branch to
# `main`, so the gate never ran on default-branch pushes and the
# 33 KB headroom eroded unseen. Two unrelated PRs off the same
# merge-base (9b2ae1f) measured 1,655,497 B and 1,655,687 B — 190 B
# apart, proving the drift is on main, not in either diff. Bumping
# to 1,700,000 (~1.62 MiB) ≈ measurement + ~2.7% headroom; ratchet
# down after the first green main run establishes a fresh baseline.
#
# 2026-07-09 rebaseline: PR #23 (code-block syntax highlighting,
# +17.6 KB measured against its merge-base) tripped the gate at
# 1,702,855 B — 2,855 B over. Attribution in issue #21: main-side
# growth since 2026-07-02 (Mermaid slice 2 #17, coverage suite,
# et al.) consumed the headroom; the highlighting branch was the
# straw. Bumping to 1,850,000 (~1.76 MiB) ≈ measurement + ~8.6%
# headroom, matching the 2026-06-04 ratio. The optimization /
# ratchet-down pass stays tracked in #21 — do not bump again
# without closing or updating that issue.
#
# 2026-07-10 optimization pass (#21, closed): measured 1,743,301 B
# on main at 07c0514 (~6.1% headroom). twiggy attribution and two
# tested levers concluded the bundle is efficiently packed —
# opt-level=z + fat LTO + wasm-opt -z + pervasive .into_any()
# erasure already claimed the wins (breaking up the largest single
# function recovered 0.07%). The one remaining cut (fetch-on-demand
# locales, ~55 KB gz) was declined to keep instant locale switching.
# Gate stays at 1,850,000; future headroom is managed by this file's
# rebaseline policy, not an optimization backlog.
# 2026-10-01: owner-requested 20% increase for the Mermaid work.
WASM_GZ_LIMIT: "2406000" # ~2.29 MiB, up from 2,005,000 B
# Soft regression budget — a no-op-change PR that adds > 5% to the
# bundle (without crossing the hard limit) gets a warning so a
# quiet drift can be caught before it eats the headroom.
WASM_GZ_SOFT_DELTA_PCT: "5"
jobs:
bundle-size:
name: WASM bundle size gate
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- name: Install Rust (stable + wasm32)
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target
frontend -> target
shared-key: bundle-size
# Pinned: `version: latest` resolved to trunk 0.19.1 on one runner and
# 0.21.14 on another ten minutes apart (2026-09-26). 0.19.1 ignores
# index.html's data-wasm-opt-params, so its wasm-opt 116 rejected the
# bulk-memory ops rustc now emits for wasm32. 0.21.14 matches local dev.
- name: Install trunk
uses: taiki-e/install-action@5488ac5a951645ce95062214902ac4b6bc1a1037 # v2
with:
tool: trunk@0.21.14
# Trunk downloads the wasm-bindgen version pinned in frontend/Cargo.lock.
- name: Build frontend (release)
working-directory: frontend
# Size-optimizing profile overrides, applied here (not in
# frontend/Cargo.toml [profile.release]) so local dev / e2e builds
# stay fast. These MUST match the Dockerfile Stage 2 build so the
# gate measures exactly what ships. wasm-opt=z still runs post-link
# via index.html's data-wasm-opt directive.
env:
CARGO_PROFILE_RELEASE_OPT_LEVEL: z
CARGO_PROFILE_RELEASE_LTO: fat
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "1"
CARGO_PROFILE_RELEASE_STRIP: "true"
CARGO_PROFILE_RELEASE_PANIC: abort
run: trunk build --release
- name: Measure WASM bundle
id: measure
working-directory: frontend/dist
run: |
set -euo pipefail
WASM=$(ls *_bg.wasm 2>/dev/null | head -1)
if [ -z "$WASM" ]; then
echo "::error::No *_bg.wasm produced in frontend/dist/"
ls -la
exit 1
fi
RAW=$(stat -c%s "$WASM")
GZ=$(gzip -9 -c "$WASM" | wc -c)
echo "wasm=$WASM" | tee -a "$GITHUB_OUTPUT"
echo "raw=$RAW" | tee -a "$GITHUB_OUTPUT"
echo "gz=$GZ" | tee -a "$GITHUB_OUTPUT"
{
echo "## WASM bundle size"
echo ""
echo "| metric | bytes | human |"
echo "|---|---|---|"
printf "| raw | %s | %s |\n" "$RAW" "$(numfmt --to=iec --suffix=B "$RAW")"
printf "| gzip -9 | %s | %s |\n" "$GZ" "$(numfmt --to=iec --suffix=B "$GZ")"
printf "| limit | %s | %s |\n" "${WASM_GZ_LIMIT}" "$(numfmt --to=iec --suffix=B "${WASM_GZ_LIMIT}")"
} >> "$GITHUB_STEP_SUMMARY"
- name: Gate on threshold
env:
GZ: ${{ steps.measure.outputs.gz }}
run: |
set -euo pipefail
if [ "$GZ" -gt "$WASM_GZ_LIMIT" ]; then
echo "::error::WASM bundle ${GZ} bytes > limit ${WASM_GZ_LIMIT} bytes (gzipped)."
echo "See design/performance-budgets.md → 'Bundle size'."
exit 1
fi
echo "::notice::WASM bundle within budget: ${GZ} / ${WASM_GZ_LIMIT} (gz)."