The extension contributes breakpoints for OpenQASM and a `wai-quantum` debugger whose launch settings (program, stopOnEntry, inputs, noise, method, outcomes) are the ones `wai-quantum dap` reads; it starts the adapter as the command line's dap verb, and "Debug the program" debugs the file in the editor. The Lua configuration registers the adapter with the debug adapter plugin, and languages.toml declares it with a launch template. test/check.mjs holds the manifest to the adapter's source and checks the client starts it; the editors workflow runs the debugger's module tests and tests/dap.rs on Linux and macOS. Co-Authored-By: Claude Opus 5.5 <[email protected]>
204 lines
10 KiB
YAML
204 lines
10 KiB
YAML
name: wai-quantum editors
|
|
|
|
# The engine in editors:
|
|
# - the language service (wai/wai-quantum/src/engine/editor): its unit tests,
|
|
# each module by name, on Linux and macOS;
|
|
# - the language server, `wai-quantum lsp`, driven over standard input and
|
|
# output by a scripted session from initialize to exit (tests/lsp.rs), on
|
|
# Linux and macOS;
|
|
# - the debugger (wai/wai-quantum/src/engine/debug.rs, with the visual edits
|
|
# and the statistical tests beside it), each module by name, and the debug
|
|
# adapter, `wai-quantum dap`, driven by scripted sessions from initialize
|
|
# to disconnect (tests/dap.rs), on Linux and macOS;
|
|
# - `wai-quantum fmt` on every program in the repository: formatting the
|
|
# formatted program changes nothing, and the engine draws the same circuit;
|
|
# - the tree-sitter grammar (wai/tools/tree-sitter-openqasm): regenerated
|
|
# with the pinned command line and identical to the committed parser, its
|
|
# corpus and highlighting tests, and every program in the repository's
|
|
# conformance material and examples parsed with no error;
|
|
# - the editor extension (wai/tools/wai-quantum-editor): built, packaged as a
|
|
# .vsix with the pinned packaging tool, and checked (its manifest against
|
|
# the server, its highlighting, its message when the command line is
|
|
# missing, the other editors' configurations, and the package's files);
|
|
# - the extension for editors with WebAssembly extensions, built for
|
|
# wasm32-wasip2.
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'wai/wai-quantum/**'
|
|
- 'wai/wai-quantum-cli/**'
|
|
- 'wai/tools/tree-sitter-openqasm/**'
|
|
- 'wai/tools/wai-quantum-editor/**'
|
|
- 'wai/quantum-studio/src/examples.js'
|
|
- 'wai/quantum-ops-conformance/**'
|
|
- 'rust-toolchain.toml'
|
|
- '.github/workflows/wai-quantum-editors.yml'
|
|
pull_request:
|
|
paths:
|
|
- 'wai/wai-quantum/**'
|
|
- 'wai/wai-quantum-cli/**'
|
|
- 'wai/tools/tree-sitter-openqasm/**'
|
|
- 'wai/tools/wai-quantum-editor/**'
|
|
- 'wai/quantum-studio/src/examples.js'
|
|
- 'wai/quantum-ops-conformance/**'
|
|
- 'rust-toolchain.toml'
|
|
- '.github/workflows/wai-quantum-editors.yml'
|
|
|
|
jobs:
|
|
relevant:
|
|
name: does this change touch it
|
|
runs-on: linux-arm64
|
|
outputs:
|
|
run: ${{ steps.gate.outputs.run }}
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
with:
|
|
fetch-depth: 0
|
|
- id: gate
|
|
run: |
|
|
set -euo pipefail
|
|
r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-quantum-editors.yml \
|
|
"${{ github.event.pull_request.base.sha }}" \
|
|
"${{ github.event.pull_request.head.sha }}")
|
|
echo "this change touches the editors' support: $r"
|
|
echo "run=$r" >> "$GITHUB_OUTPUT"
|
|
|
|
editors-linux:
|
|
name: editors · linux
|
|
needs: relevant
|
|
if: needs.relevant.outputs.run == 'true'
|
|
runs-on: linux
|
|
timeout-minutes: 60
|
|
# The grammar's tree-sitter command (from npm, a prebuilt binary) needs glibc
|
|
# 2.39, which the runner's default image (act-22.04, glibc 2.35) lacks; this
|
|
# image has it, as wai-neural-e2e.yml's job does for its libraries.
|
|
container:
|
|
image: catthehacker/ubuntu:act-24.04
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
- name: Install Rust 1.98.0 with the wasm32-wasip2 target
|
|
shell: bash
|
|
run: |
|
|
export PATH="$HOME/.cargo/bin:$PATH"
|
|
command -v rustup >/dev/null 2>&1 || \
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
|
|
rustup toolchain install 1.98.0 --profile minimal
|
|
rustup default 1.98.0
|
|
rustup target add --toolchain 1.98.0 wasm32-wasip2
|
|
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
# The filters are module paths, and a filter that matches nothing passes, so
|
|
# each module must show a test that passed.
|
|
- name: The language service's tests
|
|
shell: bash
|
|
working-directory: wai/wai-quantum
|
|
run: |
|
|
set -euo pipefail
|
|
cargo test --locked --features full --lib engine::editor:: 2>&1 | tee "$RUNNER_TEMP/service.log"
|
|
for m in lex index gates format tests; do
|
|
grep -qE "^test engine::editor::$m::.* \.\.\. ok$" "$RUNNER_TEMP/service.log" || { echo "::error::no test of engine::editor::$m ran"; exit 1; }
|
|
done
|
|
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/service.log"
|
|
- name: The language server over standard input and output, and the verbs' parsing
|
|
shell: bash
|
|
working-directory: wai/wai-quantum-cli
|
|
run: |
|
|
set -euo pipefail
|
|
cargo test --locked --release --test lsp 2>&1 | tee "$RUNNER_TEMP/lsp.log"
|
|
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/lsp.log" || { echo "::error::the protocol session did not pass"; exit 1; }
|
|
cargo test --locked --release --bin wai-quantum -- lsp:: the_command_line_parses_as_documented 2>&1 | tee "$RUNNER_TEMP/unit.log"
|
|
grep -qE '^test result: ok\. 4 passed; 0 failed' "$RUNNER_TEMP/unit.log" || { echo "::error::the server's unit tests did not all run"; exit 1; }
|
|
cargo build --locked --release
|
|
- name: The debugger's tests, and the debug adapter over standard input and output
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
cd wai/wai-quantum
|
|
cargo test --locked --features full --lib -- engine::debug:: engine::visual:: engine::stats:: 2>&1 | tee "$RUNNER_TEMP/debug.log"
|
|
for m in debug visual stats; do
|
|
grep -qE "^test engine::$m::.* \.\.\. ok$" "$RUNNER_TEMP/debug.log" || { echo "::error::no test of engine::$m ran"; exit 1; }
|
|
done
|
|
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/debug.log"
|
|
cd ../wai-quantum-cli
|
|
cargo test --locked --release --test dap 2>&1 | tee "$RUNNER_TEMP/dap.log"
|
|
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/dap.log" || { echo "::error::the debug adapter's sessions did not pass"; exit 1; }
|
|
- name: The grammar, regenerated as committed; its corpus, its highlighting, and every program in the repository
|
|
shell: bash
|
|
working-directory: wai/tools/tree-sitter-openqasm
|
|
run: |
|
|
set -euo pipefail
|
|
npm ci --no-audit --no-fund
|
|
npx tree-sitter generate --abi 14
|
|
git diff --exit-code -- src || { echo "::error::src/ is not what grammar.js generates: regenerate and commit it"; exit 1; }
|
|
npx tree-sitter test
|
|
node script/check-programs.mjs --out "$RUNNER_TEMP/programs"
|
|
- name: wai-quantum fmt on every program in the repository
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
w="$PWD/wai/wai-quantum-cli/target/release/wai-quantum"
|
|
n=0
|
|
for f in "$RUNNER_TEMP"/programs/*.qasm; do
|
|
"$w" fmt "$f" > "$RUNNER_TEMP/once.qasm"
|
|
"$w" fmt "$RUNNER_TEMP/once.qasm" > "$RUNNER_TEMP/twice.qasm"
|
|
cmp -s "$RUNNER_TEMP/once.qasm" "$RUNNER_TEMP/twice.qasm" || { echo "::error::formatting $f again changed it"; diff "$RUNNER_TEMP/once.qasm" "$RUNNER_TEMP/twice.qasm" || true; exit 1; }
|
|
# The engine draws the formatted program as it draws the program, or refuses
|
|
# both (a refusal names a line, which formatting may move).
|
|
args=(); grep -qE '^\s*input\s+u?int' "$f" && args=(--input n=5)
|
|
a_out=$("$w" "${args[@]}" draw < "$f" 2>/dev/null) && a=0 || a=$?
|
|
b_out=$("$w" "${args[@]}" draw < "$RUNNER_TEMP/once.qasm" 2>/dev/null) && b=0 || b=$?
|
|
[ "$a" = "$b" ] || { echo "::error::the engine reads $f (status $a) and its formatted form (status $b) differently"; exit 1; }
|
|
[ "$a" != 0 ] || [ "$a_out" = "$b_out" ] || { echo "::error::the engine draws the formatted $f differently"; diff <(echo "$a_out") <(echo "$b_out") || true; exit 1; }
|
|
n=$((n + 1))
|
|
done
|
|
[ "$n" -ge 20 ] || { echo "::error::only $n programs were formatted"; exit 1; }
|
|
echo "fmt: $n programs, each stable, each drawn the same or refused alike"
|
|
- name: The editor extension, packaged and checked
|
|
shell: bash
|
|
working-directory: wai/tools/wai-quantum-editor
|
|
run: |
|
|
set -euo pipefail
|
|
npm ci --no-audit --no-fund
|
|
npm run package < /dev/null
|
|
WAI_QUANTUM_BIN="$GITHUB_WORKSPACE/wai/wai-quantum-cli/target/release/wai-quantum" node test/check.mjs --vsix wai-quantum.vsix
|
|
- name: The extension for editors with WebAssembly extensions, for wasm32-wasip2
|
|
shell: bash
|
|
working-directory: wai/tools/wai-quantum-editor/editors/extension
|
|
run: cargo build --locked --release --target wasm32-wasip2
|
|
|
|
editors-macos:
|
|
name: editors · macos
|
|
needs: relevant
|
|
if: needs.relevant.outputs.run == 'true'
|
|
runs-on: macos
|
|
timeout-minutes: 60
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
# launchd's PATH omits cargo on the macOS host runner.
|
|
- name: Put cargo on PATH
|
|
shell: bash
|
|
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
- name: The language service's tests
|
|
shell: bash
|
|
working-directory: wai/wai-quantum
|
|
run: |
|
|
set -euo pipefail
|
|
nice -n 10 cargo test --locked --features full --lib engine::editor:: 2>&1 | tee "$RUNNER_TEMP/service.log"
|
|
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/service.log"
|
|
- name: The language server over standard input and output
|
|
shell: bash
|
|
working-directory: wai/wai-quantum-cli
|
|
run: |
|
|
set -euo pipefail
|
|
nice -n 10 cargo test --locked --release --test lsp 2>&1 | tee "$RUNNER_TEMP/lsp.log"
|
|
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/lsp.log" || { echo "::error::the protocol session did not pass"; exit 1; }
|
|
nice -n 10 cargo test --locked --release --test dap 2>&1 | tee "$RUNNER_TEMP/dap.log"
|
|
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/dap.log" || { echo "::error::the debug adapter's sessions did not pass"; exit 1; }
|