Files
clide/.github/workflows/test.yml
T
jpmschweitzerandClaude Opus 4.8 ca08c2a17d feat(web): fence dart:ffi behind web stubs so the WASM build compiles (T-438, D-100)
`flutter build web --wasm` had been broken since the tree-sitter/PTY dart:ffi
pivot. Per D-100 (resolving Q-50: keep the web "happy accident" alive), every
native binding now sits behind a `dart.library.ffi` conditional import with a
graceful web stub. Desktop builds are unchanged — no fidelity loss; the web
target degrades (no terminal, native git, or syntax highlighting).

Discriminator is `dart.library.ffi`, not `dart.library.io` — dart2wasm provides
dart:io, so FFI is the only blocker.

Fences:
- PTY: pty_session → pty_backend_io / pty_backend_web (stub throws).
- tree-sitter: pure types → syntax_result.dart; tree_sitter_service is now a
  facade over _ffi/_stub; tree_sitter_boot_io/stub fences TreeSitterLib.init().
- watchdog: watchdog_windows_stub (all -1 sampler).
- claude ABI probe: native_abi_io/stub (was `dart:ffi show Abi`).
- testmode fd-check: fd_check_io/stub.

Also dart2js-safe: the 64-bit FNV literals in session_naming.dart + paths.dart
(the dual JS fallback rejected them) — split into 32-bit halves, dropped a
no-op 64-bit mask. Desktop/wasm hash values unchanged.

CI: added a `web-wasm` job (flutter build web --wasm) so the fence can't rot.
Two FFI-constructing tree-sitter tests import _ffi.dart directly (the analyzer
resolves the conditional facade to the stub branch).

Verified: `flutter build web --wasm` → built; `flutter analyze` clean;
`make test` green. Full Playwright e2e harness wiring is the tracked follow-on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:31:24 +02:00

153 lines
6.1 KiB
YAML

name: test
# Linux CI for clide (GitHub Actions). Moved here from .gitea/workflows/ when CI
# consolidated onto GitHub (the primary remote); the Gitea secondary has Actions
# disabled. Pairs with windows.yml (ConPTY suite on windows-latest) and
# release.yml (versioned release bundles).
#
# Steps go through the make targets (the repo's tooling-discipline rule: the
# make layer sets up the environment — gen-build-info etc. — and stays correct
# if a wrapped script moves).
on:
push:
branches: [main]
pull_request:
jobs:
unit:
name: unit + widget + golden + a11y + coverage gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with: { channel: stable, cache: true }
- run: flutter pub get
- name: install pql
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release download --repo postmeridiem/pql --pattern 'pql_*_Linux_x86_64.tar.gz' --output /tmp/pql.tgz
tar -xzf /tmp/pql.tgz -C /tmp
sudo install -m 0755 /tmp/pql /usr/local/bin/pql
pql --version
# The pql tests query the repo's vault, but .pql/pql.db is gitignored
# (the post-checkout hook rebuilds it from the committed changelog).
# A fresh CI checkout has the changelog but no db — materialize it,
# and sync decision records from the governance/ DQR markdown tree
# (tickets come from the changelog; decisions from `decisions sync`).
pql plan import
pql decisions sync
# test-coverage runs the full fast suite WITH coverage (it includes the
# a11y suite — see the push-check note in the Makefile), which is what
# coverage-gate consumes.
- run: make test-coverage
- run: make coverage-gate
integration:
name: integration_test (xvfb)
runs-on: ubuntu-latest
needs: unit
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with: { channel: stable, cache: true }
- run: sudo apt-get update && sudo apt-get install -y xvfb ninja-build libgtk-3-dev
- run: flutter pub get
- name: install pql
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release download --repo postmeridiem/pql --pattern 'pql_*_Linux_x86_64.tar.gz' --output /tmp/pql.tgz
tar -xzf /tmp/pql.tgz -C /tmp
sudo install -m 0755 /tmp/pql /usr/local/bin/pql
pql --version
# The pql tests query the repo's vault, but .pql/pql.db is gitignored
# (the post-checkout hook rebuilds it from the committed changelog).
# A fresh CI checkout has the changelog but no db — materialize it,
# and sync decision records from the governance/ DQR markdown tree
# (tickets come from the changelog; decisions from `decisions sync`).
pql plan import
pql decisions sync
- uses: coactions/setup-xvfb@v1
with: { run: make test-integration }
startup-bundle:
name: bundle smoke (xvfb 5s)
runs-on: ubuntu-latest
needs: unit
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with: { channel: stable, cache: true }
- run: sudo apt-get update && sudo apt-get install -y xvfb ninja-build libgtk-3-dev
- run: flutter pub get
- name: install pql
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release download --repo postmeridiem/pql --pattern 'pql_*_Linux_x86_64.tar.gz' --output /tmp/pql.tgz
tar -xzf /tmp/pql.tgz -C /tmp
sudo install -m 0755 /tmp/pql /usr/local/bin/pql
pql --version
# The pql tests query the repo's vault, but .pql/pql.db is gitignored
# (the post-checkout hook rebuilds it from the committed changelog).
# A fresh CI checkout has the changelog but no db — materialize it,
# and sync decision records from the governance/ DQR markdown tree
# (tickets come from the changelog; decisions from `decisions sync`).
pql plan import
pql decisions sync
# Point the real release app's crash logs at an uploadable workspace dir
# (T-436): if the bundle wedges on boot, the watchdog heartbeat/sample +
# FileLogSink land here and get uploaded below. CLIDE_LOG=debug so the
# file sink captures info/debug, not just the release-default warn.
- name: bundle smoke (logs → artifact)
env:
CLIDE_LOG: debug
CLIDE_LOG_DIR: ${{ github.workspace }}/clide-logs
run: make smoke-bundle
- name: Upload crash logs
if: always()
uses: actions/upload-artifact@v4
with:
name: bundle-crash-logs
path: ${{ github.workspace }}/clide-logs
if-no-files-found: ignore
web-wasm:
name: web build (wasm compile gate)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with: { channel: stable, cache: true }
- run: flutter pub get
# Compile gate for the dart:ffi web fence (D-100 / T-438, resolving Q-50):
# every native binding lives behind a `dart.library.ffi` conditional import
# with a web stub. If a new one lands without its stub, this fails — the
# fence can't silently rot. Build-only for now; the full web-WASM Playwright
# e2e (`make test-e2e`: setup-node + playwright install in tools/ui +
# serve) is the follow-on once the harness is wired back up.
- run: flutter build web --wasm
docs:
name: dart doc (lib API)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with: { channel: stable, cache: true }
- run: flutter pub get
- name: dart doc --validate-links (fail on warning)
run: |
set -o pipefail
dart doc --validate-links 2>&1 | tee dartdoc.log
if grep -q "^ warning:" dartdoc.log; then
echo "::error::dartdoc emitted warnings — see log above"
exit 1
fi
- uses: actions/upload-artifact@v4
with:
name: dart-api-docs
path: doc/api/