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; }