release: v0.4.11 — stop hijacking the foreground, fix real-device terminate #178
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main, kuri-browser] | |
| pull_request: | |
| branches: [main, kuri-browser] | |
| jobs: | |
| build-and-test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Zig 0.16.0 | |
| uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.17.0-dev.813+2153f8143 | |
| - name: Cache Zig build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| .zig-cache | |
| ~/.cache/zig | |
| key: zig-${{ runner.os }}-${{ hashFiles('build.zig', 'build.zig.zon') }} | |
| restore-keys: | | |
| zig-${{ runner.os }}- | |
| - name: Build | |
| run: zig build -Doptimize=ReleaseSafe | |
| - name: Run tests | |
| run: zig build test -Doptimize=ReleaseSafe | |
| - name: Run kuri-mobile tests | |
| # kuri-mobile ships in the same tarball but has its own build.zig, so | |
| # the root `test` step never reached it. Its platform-independent | |
| # half — the adb wire protocol, the devicectl JSON decoding, the tool | |
| # registry — is worth checking on Linux too; the macOS-only half is | |
| # covered by the mobile-macos job. | |
| working-directory: kuri-mobile | |
| run: zig build test --summary all -Doptimize=ReleaseSafe | |
| - name: Regression — --help / --version do NOT spawn Chrome (issue #156) | |
| # Old kuri binaries (≤ v0.1.0) silently fell through to the daemon | |
| # path on `--help`, launching headless Chrome and binding :8080. | |
| # Fixed in f0ab19b. This step makes sure no future change re-routes | |
| # `--help` or `--version` through the daemon path again. | |
| run: | | |
| set -euo pipefail | |
| for flag in --help -h --version -V; do | |
| echo "::group::kuri ${flag}" | |
| # Run with hard 5 s timeout; help/version must exit fast. | |
| output=$(timeout 5s ./zig-out/bin/kuri "${flag}" 2>&1) && rc=$? || rc=$? | |
| echo "${output}" | |
| echo "exit=${rc}" | |
| if [ "${rc}" -ne 0 ]; then | |
| echo "::error::kuri ${flag} returned non-zero (${rc}) — should print and exit 0" | |
| exit 1 | |
| fi | |
| # Match the actual log lines emitted by the daemon path | |
| # (`std.log.info(...)` prefixes them with "info: "), not the | |
| # help text — which legitimately documents Chrome-related env | |
| # vars and would otherwise false-positive. | |
| if echo "${output}" | grep -qE "^info: (launching managed Chrome|listening on|launched Chrome|connecting to existing Chrome)"; then | |
| echo "::error::kuri ${flag} appears to have entered daemon startup. See issue #156." | |
| exit 1 | |
| fi | |
| # Confirm at least one expected line was printed. | |
| if [ "${flag}" = "--help" ] || [ "${flag}" = "-h" ]; then | |
| echo "${output}" | grep -q "USAGE" || { echo "::error::kuri ${flag} did not print USAGE"; exit 1; } | |
| else | |
| echo "${output}" | grep -q "kuri " || { echo "::error::kuri ${flag} did not print version"; exit 1; } | |
| fi | |
| echo "::endgroup::" | |
| done | |
| mobile-macos: | |
| # kuri-mobile is the one part of the tree that can be exercised against | |
| # real Apple tooling, and GitHub's macOS runners ship Xcode plus iOS | |
| # simulator runtimes. Before this job the e2e suite only ever ran by hand, | |
| # so nothing caught a regression on the device path — which is exactly how | |
| # the silent `--device` no-op survived from 0.4.6 to 0.4.10. | |
| # | |
| # The suite reports SKIP rather than failing for anything the runner | |
| # cannot provide (notably the Accessibility grant that uitree/find/ | |
| # wait-for-ui need, which no CI runner can give), so it is a stable gate | |
| # rather than a flaky one. | |
| runs-on: macos-latest | |
| defaults: | |
| run: | |
| working-directory: kuri-mobile | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Zig | |
| uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.17.0-dev.813+2153f8143 | |
| - name: Cache Zig build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| kuri-mobile/.zig-cache | |
| ~/.cache/zig | |
| key: zig-mobile-${{ runner.os }}-${{ hashFiles('kuri-mobile/build.zig') }} | |
| restore-keys: | | |
| zig-mobile-${{ runner.os }}- | |
| - name: Show toolchain | |
| run: | | |
| xcode-select -p | |
| xcodebuild -version | |
| ls "$(xcode-select -p)/usr/bin/devicectl" || echo "no devicectl in the selected toolchain" | |
| - name: Build | |
| run: zig build -Doptimize=ReleaseSafe | |
| - name: Unit tests | |
| run: zig build test --summary all | |
| - name: Doctor | |
| # Exits 3 when it finds blocking problems, which on a runner it will | |
| # (no Accessibility grant). Informational only — the assertions live | |
| # in the e2e suite. | |
| continue-on-error: true | |
| run: ./zig-out/bin/kuri-mobile doctor | |
| - name: Boot a simulator | |
| # Deliberately picks and boots through kuri-mobile rather than `xcrun | |
| # simctl`. Two reasons: it exercises `ios list-devices` and `ios boot` | |
| # for real, and bare `xcrun` resolves through xcode-select — the very | |
| # indirection whose failure mode this project exists to avoid. simctl | |
| # is then called by absolute path for `bootstatus`, which kuri has no | |
| # equivalent for. | |
| run: | | |
| set -euo pipefail | |
| udid=$(./zig-out/bin/kuri-mobile ios list-devices \ | |
| | awk -F'\t' '$1 == "simulator" && $4 ~ /iPhone/ { print $2; exit }') | |
| if [ -z "${udid}" ]; then | |
| echo "::error::no iPhone simulator available on this runner" | |
| ./zig-out/bin/kuri-mobile ios list-devices | |
| exit 1 | |
| fi | |
| echo "booting ${udid}" | |
| ./zig-out/bin/kuri-mobile ios boot --udid "${udid}" | |
| # simctl reports Booted well before the runtime has finished coming | |
| # up, so wait on bootstatus — otherwise the first e2e command races | |
| # the boot and fails for a reason unrelated to the change under test. | |
| "$(xcode-select -p)/usr/bin/simctl" bootstatus "${udid}" -b | |
| - name: End-to-end (simulator) | |
| run: zig build e2e-ios | |
| - name: End-to-end (physical device) | |
| # No phone is attached to a runner, so this must report SKIP and exit | |
| # 0. Running it anyway keeps the device suite compiling and proves its | |
| # no-hardware path stays clean — the suite is useless as a local gate | |
| # if it has quietly stopped building. | |
| run: zig build e2e-ios-device | |
| startup-smoke: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Zig 0.16.0 | |
| uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.17.0-dev.813+2153f8143 | |
| - name: Install Chrome | |
| uses: browser-actions/setup-chrome@v2 | |
| with: | |
| install-dependencies: true | |
| - name: Build | |
| run: zig build -Doptimize=ReleaseSafe | |
| - name: Startup smoke test | |
| run: | | |
| set -euo pipefail | |
| ./zig-out/bin/kuri > kuri.log 2>&1 & | |
| kuri_pid=$! | |
| cleanup() { | |
| kill "${kuri_pid}" >/dev/null 2>&1 || true | |
| wait "${kuri_pid}" >/dev/null 2>&1 || true | |
| cat kuri.log | |
| } | |
| trap cleanup EXIT | |
| for _ in $(seq 1 30); do | |
| if curl -sf http://127.0.0.1:8080/health > health.json; then | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| # /health is intentionally unauthenticated (liveness probe). | |
| curl -sf http://127.0.0.1:8080/health | tee health.json | |
| # All other routes now require Authorization: Bearer <token>. | |
| # Token is auto-generated to ~/.kuri/api.token on first launch. | |
| # Also assert that /tabs WITHOUT auth is rejected with 401, so a | |
| # regression that re-opens the credential dump fails this job. | |
| token=$(./zig-out/bin/kuri token) | |
| unauth_status=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/tabs) | |
| if [ "${unauth_status}" != "401" ]; then | |
| echo "expected /tabs without auth to return 401, got ${unauth_status}" >&2 | |
| exit 1 | |
| fi | |
| curl -sf -H "Authorization: Bearer ${token}" http://127.0.0.1:8080/tabs | tee tabs.json | |
| grep '"ok":true' health.json | |
| grep '"tabs":1' health.json | |
| grep '"id":"' tabs.json | |
| windows-cross-compile: | |
| # Verifies the Windows port stays buildable (issue #153). A native | |
| # Windows runtime smoke test is out of scope for this job — Chrome | |
| # automation, daemonization, and signal handling are all stubbed | |
| # with `error.UnsupportedOnWindows` on Windows for now. This job | |
| # exists so a future refactor that re-introduces an ungated POSIX | |
| # call (`fork`, `std.c.open`, raw `setsockopt`/`read` on a socket) | |
| # fails CI instead of silently regressing the Windows build. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Zig 0.16.0 | |
| uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.17.0-dev.813+2153f8143 | |
| - name: Cache Zig build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| .zig-cache | |
| ~/.cache/zig | |
| key: zig-windows-cross-${{ hashFiles('build.zig', 'build.zig.zon') }} | |
| restore-keys: | | |
| zig-windows-cross- | |
| - name: Cross-compile for x86_64-windows-gnu | |
| run: zig build -Dtarget=x86_64-windows-gnu -Doptimize=ReleaseSafe | |
| - name: Verify Windows executables were produced | |
| run: | | |
| set -euo pipefail | |
| for bin in kuri kuri-agent kuri-browse kuri-fetch; do | |
| path="zig-out/bin/${bin}.exe" | |
| if [ ! -f "${path}" ]; then | |
| echo "::error::missing ${path}" | |
| exit 1 | |
| fi | |
| file "${path}" | tee -a windows-build.txt | |
| if ! file "${path}" | grep -q 'PE32+ executable .* for MS Windows'; then | |
| echo "::error::${path} is not a Windows PE binary" | |
| exit 1 | |
| fi | |
| done |