Release#
Use this runbook for every quantem.widget release candidate or TestPyPI
release. Do not push a widget-v* tag until the local gates below pass.
Release target#
quantem.widget publishes release candidates to TestPyPI through the
Widget release GitHub Actions workflow. TestPyPI is the staging Python package
index. It is not PyPy, the Python runtime.
The release workflow is triggered by tags named:
widget-vX.Y.Z
widget-vX.Y.ZrcN
widget-vX.Y.Z.postN
For testing, prefer release-candidate tags such as:
widget-v0.0.1rc1
Before tagging#
Start from a clean, updated main:
git switch main
git pull origin main
git status --short
If the worktree contains scratch files, generated ._* metadata, notebooks with
large outputs, or unrelated experiments, stop and clean or move them before
continuing.
Local gates#
Run the full Python and frontend checks:
PYTHONPATH=src:. pytest -q
npm run build
For widget/export changes, also run:
PYTHONPATH=src:. pytest -q tests/test_html_export_protocol.py tests/test_showeds.py
For release packaging, run:
scripts/widget_release_check.sh
This script runs the frontend typecheck/tests/build, standalone browser build, offline browser build, Python compile smoke, local wheel build, and wheel-content checks.
Before uploading to TestPyPI or PyPI, build fresh artifacts and inspect the
actual upload payload. Do not upload stale files from an old local dist/
directory.
rm -rf /tmp/quantem-widget-release-audit
mkdir -p /tmp/quantem-widget-release-audit
python -m build --outdir /tmp/quantem-widget-release-audit
tar -tzf /tmp/quantem-widget-release-audit/*.tar.gz | less
unzip -l /tmp/quantem-widget-release-audit/*.whl | less
Confirm the wheel and sdist contain no private microscope data, generated
reports, screenshots, built docs, caches, or large local artifacts. In
particular, no .h5, .hdf5, .emd, .npy, .npz, .zarr, .tif, .dm3,
.dm4, .raw, generated tutorial HTML, or private JSON/CSV report should be
present. The expected wheel contents are Python source, package metadata,
licenses, and built widget JavaScript/static assets.
Visual signoff#
Widgets can import successfully while still rendering blank canvases. Before a release candidate, create an agent signoff packet and drive the affected widgets in the browser:
scripts/widget_agent_signoff.sh --quick
The agent signoff is a fix-and-redrive loop: choose the relevant scientific stories from Storyboard, open the docs page, notebook, or exported HTML; click, drag, zoom, scrub, resize, and export; patch anything that feels wrong; rebuild; refresh; and redrive the same story. Save final screenshots or short videos in the packet before tagging. See Agent signoff.
Also run at least the quick visual smoke:
scripts/widget_visual_signoff.sh --quick
For Show4DSTEM/WebGPU-sensitive changes, run:
scripts/widget_visual_signoff.sh --show4dstem
For a release-candidate tag, prefer the full signoff:
scripts/widget_visual_signoff.sh --full
For broad UI releases, pair it with:
scripts/widget_agent_signoff.sh --full
The full signoff includes generic widget visual tests, Show4DSTEM WebGPU browser and Jupyter smokes, plus the local release build/check gate. The human-readable report should cite storyboard IDs that were verified or skipped. Hardware- dependent real-data CUDA/MPS checks may still need a separate machine-specific runbook.
Tag and publish to TestPyPI#
After the local gates pass, create and push the release-candidate tag:
git tag widget-v0.0.1rc1
git push origin widget-v0.0.1rc1
GitHub Actions will:
build frontend widget assets,
build the standalone browser GUI,
stamp the package version from the tag,
build the wheel,
run
twine check,verify required wheel contents,
publish to TestPyPI.
Watch the Widget release workflow until it completes.
TestPyPI install check#
After the workflow publishes, install the candidate in a fresh environment:
python -m venv /tmp/quantem-widget-rc
source /tmp/quantem-widget-rc/bin/activate
python -m pip install --upgrade pip
python -m pip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
quantem-widget==0.0.1rc1
python - <<'PY'
import quantem.widget as qw
print(qw.__version__)
from quantem.widget import Show2D, Show3D, Show3DSlices, Show4DSTEM, ShowEDS
print("widgets import ok")
PY
If possible, also open a small notebook or exported HTML with each widget before promoting the release.
If something fails#
Do not overwrite a published tag. Create a new release-candidate tag instead:
widget-v0.0.1rc2
Fix the issue on a normal branch, merge through a PR, pull updated main, rerun
the gates, and then push the next release-candidate tag.