open-standards/wai/wai-quantum-py/ci/check.sh
Transaction Science a4dee88425 wai-quantum contract over the durable service: sets, provenance, dry runs, the receipt key set and the lease, each with its schema
The durable service's documents join the version contract. A set's result
(wai.quantum.set/1) and a result's provenance (wai.quantum.provenance/1) are
engine schemas; the service's receipt key set (wai.quantum.receipt-keys/1,
with its signed transitions) and the command line's scheduler lease
(wai.quantum.lease/1) are their hosts'. The job request names programs, sweep
and dry_run, a job's result may be a set's, an energy figure may be the
processor packages', and a job names its store digests.

A set's head now names the engine and its schema, inside what its receipt
seals, as every other result does. A result's provenance names the gate set
its compile wrote as basis (it read the compile summary's old target field,
which the rename left empty).

run_quantum_set and dry_run_quantum_job answer to output schemas, each with
its verdict whether refused or not, and run_quantum_circuit asked as a dry
run answers as one. The strict tests call both and hold every answer, the
job's set form and the key set after a rotation to their schemas; the
contract workflow requires the new tests by name, and check_schemas.py reads
the new files and holds a set's run to its schema.

The service's store stays at ~/.local/share/wai-quantum-service/store by
default; the Python check and its tests start the service with a store in
their own scratch, as the service workflow's legs already do.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 08:42:53 -04:00

94 lines
5 KiB
Shell

#!/usr/bin/env bash
# The Python package's whole check, as CI runs it (.github/workflows/wai-quantum-py.yml)
# and as a person runs it on a build host:
#
# bash wai/wai-quantum-py/ci/check.sh [--write-notebooks]
#
# 1. builds the command line and the job service from this checkout (the surfaces
# the package is held to);
# 2. clippy on the extension module, warnings as errors;
# 3. builds the wheel with maturin (pinned), and installs it in a fresh venv with
# the pinned, hashed test requirements (tests/requirements.lock);
# 4. pytest, every test required (none may skip: WAI_QUANTUM_REQUIRE_ALL=1);
# 5. runs the doc notebooks against a job service started here, each held to its
# stored outputs (--write-notebooks stores them instead);
# 6. installs the same wheel alone on Python 3.9 and runs tests/smoke.py.
#
# Needs cargo (the toolchain rust-toolchain.toml names), uv and node (or WAI_QUANTUM_NODE). Scratch goes
# under $WORK (default: $RUNNER_TEMP/wai-quantum-py, or a new temporary directory);
# cargo builds into $CARGO_TARGET_DIR (default: $WORK/target).
set -euo pipefail
PKG="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WAI="$(cd "$PKG/.." && pwd)"
WRITE=0
[ "${1:-}" = "--write-notebooks" ] && WRITE=1
WORK="${WORK:-${RUNNER_TEMP:-$(mktemp -d)}/wai-quantum-py}"
mkdir -p "$WORK"
export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$WORK/target}"
PY="${WAI_QUANTUM_PYTHON:-3.12}"
MATURIN=1.15.0
step() { echo; echo "== $*"; }
step "the command line and the job service, from this checkout"
(cd "$WAI/wai-quantum-cli" && cargo build --locked --release)
(cd "$WAI/wai-quantum-service" && cargo build --locked --release)
CLI="$CARGO_TARGET_DIR/release/wai-quantum"
SVC="$CARGO_TARGET_DIR/release/wai-quantum-service"
"$CLI" --version
step "clippy on the extension module"
(cd "$PKG" && cargo clippy --locked --release --all-targets -- -D warnings)
step "the wheel (maturin $MATURIN)"
rm -rf "$WORK/tools" "$WORK/dist" "$WORK/test" "$WORK/py39"
uv venv -q --python "$PY" "$WORK/tools"
uv pip install -q --python "$WORK/tools/bin/python" "maturin==$MATURIN"
(cd "$PKG" && "$WORK/tools/bin/maturin" build --release --locked -o "$WORK/dist")
WHEEL="$(ls "$WORK"/dist/wai_quantum-*.whl)"
echo "built $(basename "$WHEEL")"
case "$(basename "$WHEEL")" in *-cp39-abi3-*) ;; *) echo "::error::the wheel is not abi3 from Python 3.9: $WHEEL"; exit 1 ;; esac
step "a fresh venv: the wheel and the pinned test requirements"
uv venv -q --python "$PY" "$WORK/test"
uv pip install -q --python "$WORK/test/bin/python" --require-hashes -r "$PKG/tests/requirements.lock"
uv pip install -q --python "$WORK/test/bin/python" --no-deps "$WHEEL"
"$WORK/test/bin/python" -I -c 'import wai_quantum, wai_quantum.widgets as w; assert w.HAVE_WIDGETS; print("wai_quantum", wai_quantum.__version__, "from", wai_quantum.__file__)'
step "node: the widgets' front ends parse"
NODE="${WAI_QUANTUM_NODE:-$(command -v node || true)}"
[ -n "$NODE" ] || { echo "::error::no node (or WAI_QUANTUM_NODE): the widgets' front ends are tested with it"; exit 1; }
export WAI_QUANTUM_NODE="$NODE"
"$NODE" --version
for f in "$PKG"/python/wai_quantum/static/*.js "$PKG"/tests/front_ends.mjs; do "$NODE" --check "$f"; done
step "pytest"
export WAI_QUANTUM_CLI="$CLI" WAI_QUANTUM_SERVICE_BIN="$SVC" WAI_QUANTUM_REQUIRE_ALL=1
export IPYTHONDIR="$WORK/ipython" JUPYTER_PLATFORM_DIRS=1
(cd "$PKG" && "$WORK/test/bin/pytest" -q -p no:cacheprovider tests 2>&1 | tee "$WORK/pytest.log")
grep -qE '^[0-9]+ passed' "$WORK/pytest.log" || { echo "::error::pytest did not report passes"; exit 1; }
if grep -qE '[0-9]+ (failed|skipped|error)' "$WORK/pytest.log"; then echo "::error::a test failed, erred or skipped"; exit 1; fi
step "the doc notebooks, against a job service started here"
port=$(( 18300 + RANDOM % 500 ))
cfg="$WORK/qsvc"; rm -rf "$cfg"; mkdir -p "$cfg"
WAI_QSVC_KEY="$cfg/service.key" WAI_QSVC_STORE="$cfg/store" WAI_QSVC_ADDR="127.0.0.1:$port" WAI_QSVC_BUDGET_GB=4 WAI_QSVC_JOB_GB=2 WAI_QSVC_WORKERS=1 \
WAI_QSVC_MIN_FREE_PCT=0 WAI_QSVC_CLIENT_BURST=10000 "$SVC" serve > "$cfg/service.log" 2>&1 &
pid=$!
trap 'kill $pid 2>/dev/null || true' EXIT
for _ in $(seq 1 100); do curl -fs -o /dev/null "http://127.0.0.1:$port/v1/health" && break; sleep 0.2; done
nb=(getting-started bell-receipt equivalence noisy-run service-job)
files=(); for n in "${nb[@]}"; do files+=("$PKG/notebooks/$n.ipynb"); done
# (An empty array expands under set -u only this way in the bash macOS ships.)
args=(); [ "$WRITE" = 1 ] && args=(--write)
(cd "$PKG" && XDG_CONFIG_HOME="$WORK/nbconfig" WAI_QUANTUM_SERVICE="http://127.0.0.1:$port" "$WORK/test/bin/python" tests/run_notebooks.py ${args[@]+"${args[@]}"} "${files[@]}")
kill $pid 2>/dev/null || true
wait $pid 2>/dev/null || true
trap - EXIT
step "the same wheel alone on Python 3.9"
uv venv -q --python 3.9 "$WORK/py39"
uv pip install -q --python "$WORK/py39/bin/python" --no-deps "$WHEEL"
(cd "$WORK" && "$WORK/py39/bin/python" -I "$PKG/tests/smoke.py")
echo
echo "wai-quantum-py: every check passed ($(grep -E '^[0-9]+ passed' "$WORK/pytest.log"))"