Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/api-client.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
24647a217c868be35a63ee1903256fee5464a2dce8227b2d1e93e53a0da6e1bf packages/api_client/Cargo.toml
e89d6b353b59e2f939429c030feaaed4a756f38028e0d5c86adb154be6723ee9 packages/api_client/src/api.rs
b564b8cf3ddcd4688f2ec9813201f8100d428e9aac36efaccef5583c985ea47b packages/api_client/src/http_client.rs
53df6aded4c3f32b88a266a0b37965702a7f56fb3ea0168746945320cb6e627b packages/api_client/src/ip_resource.rs
d08117991790a4a09793a0c23782a7b4e0abb307556bf95f7533042b619c093d packages/api_client/src/lib.rs
14 changes: 14 additions & 0 deletions .github/scripts/check-api-client-frozen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail

repository_root="$(git rev-parse --show-toplevel)"
cd "$repository_root"

actual_manifest="$(mktemp)"
trap 'rm -f "$actual_manifest"' EXIT

find packages/api_client -type f -print0 \
| LC_ALL=C sort -z \
| xargs -0 sha256sum > "$actual_manifest"

diff --unified .github/api-client.sha256 "$actual_manifest"
118 changes: 118 additions & 0 deletions .github/scripts/check-dependency-boundaries.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env bash
set -euo pipefail

repository_root="$(git rev-parse --show-toplevel)"
cd "$repository_root"

forbidden_api='playit_api_client|playit-api-client|PlayitApi'
if grep -R -n -E "$forbidden_api" packages/agent_core packages/playitd/src packages/playitd/Cargo.toml; then
echo "agent_core and playitd must access the generated API client through playit-runtime" >&2
exit 1
fi

if grep -R -n -E 'playit_runtime|playit-runtime' \
packages/agent_core/src packages/agent_core/Cargo.toml; then
echo "agent_core must not depend on the application runtime" >&2
exit 1
fi

forbidden_ipc='playit_api_client|playit-api-client|PlayitApi|reqwest|login_guest|guest_login_cache'
if grep -R -n -E "$forbidden_ipc" packages/playit-ipc packages/playitd/src/ipc_server.rs; then
echo "IPC must not own HTTP clients or login caches" >&2
exit 1
fi

if grep -R -n -E 'Client[A-Z][A-Za-z]*View|playit_ipc|playit-ipc|interprocess|reqwest|tokio|windows[_-](sys|service)' \
packages/playit-model/src packages/playit-model/Cargo.toml; then
echo "playit-model must not contain presentation, IPC, HTTP, runtime, or OS types" >&2
exit 1
fi

if grep -R -n -E 'playit[_-](model|runtime)|api_client|playit-api-client' \
packages/playit-platform/src packages/playit-platform/Cargo.toml; then
echo "playit-platform must contain OS mechanisms, not application lifecycle or API policy" >&2
exit 1
fi

if grep -R -n -E '^pub use playit_platform' packages/playitd/src packages/playit-ipc/src; then
echo "entry-point and IPC crates must not re-export platform compatibility paths" >&2
exit 1
fi

if [ -e packages/playit-ipc/src/paths.rs ] || grep -q '^pub mod paths;' packages/playit-ipc/src/lib.rs; then
echo "playit-ipc path forwarding must not return" >&2
exit 1
fi

if [ -e packages/playit-runtime/src/gateway.rs ] || \
grep -R -n -E '^pub use (playit_agent_core|crate::gateway)' \
packages/playit-runtime/src packages/agent_core/src; then
echo "runtime and agent_core migration re-exports must not return" >&2
exit 1
fi

api_adapter_files="$(grep -R -l -E 'playit_api_client|PlayitApi' \
packages --include='*.rs' --exclude-dir=api_client || true)"
if [ "$api_adapter_files" != "packages/playit-runtime/src/generated_gateway.rs" ]; then
echo "expected one generated API adapter source, found:" >&2
printf '%s\n' "$api_adapter_files" >&2
exit 1
fi

require_one_definition() {
local pattern="$1"
local label="$2"
local count
count="$(grep -R -h -E "$pattern" packages --include='*.rs' | wc -l)"
if [ "$count" -ne 1 ]; then
echo "expected exactly one $label definition, found $count" >&2
exit 1
fi
}

require_one_definition '^pub enum Phase[[:space:]]*\{' 'application lifecycle enum'
require_one_definition '^pub struct AppSnapshot[[:space:]]*\{' 'application snapshot'
require_one_definition '^pub struct SnapshotStore[[:space:]]*\{' 'snapshot authority'
require_one_definition '^pub struct AppSupervisor[[:space:]]*\{' 'application supervisor'
require_one_definition '^pub struct EngineSupervisor[[:space:]]*\{' 'engine supervisor'
require_one_definition '^pub struct GeneratedClientGateway[[:space:]]*\{' 'generated API adapter'
require_one_definition '^pub struct SupervisedEnginePort[[:space:]]*\{' 'engine application adapter'
require_one_definition '^pub async fn stop_installed_service_with_fallback' 'installed-service stop policy'
require_one_definition '^pub enum EngineExit[[:space:]]*\{' 'engine exit type'
require_one_definition '^pub enum EngineService[[:space:]]*\{' 'engine service type'
require_one_definition '^pub enum ServiceExit[[:space:]]*\{' 'service exit type'

if grep -R -n 'PhaseKind' packages --include='*.rs'; then
echo "application lifecycle projections must match directly on Phase" >&2
exit 1
fi

owned_task_sources=(
packages/playit-cli/src/main.rs
packages/playit-cli/src/signal_handle.rs
packages/playitd/src/daemon.rs
packages/playitd/src/ipc_server.rs
packages/playit-runtime/src/engine.rs
packages/agent_core/src/playit_agent.rs
packages/agent_core/src/network
)
if grep -R -n -E '^[[:space:]]*tokio::spawn[[:space:]]*\(' "${owned_task_sources[@]}"; then
echo "production tasks must retain a join owner" >&2
exit 1
fi

if grep -n -E '^playitd[[:space:]]*=' \
packages/playit-cli/Cargo.toml \
packages/playitd-tray/Cargo.toml \
packages/playitd-windows-setup/Cargo.toml; then
echo "clients and installer helpers must use playit-platform instead of playitd platform internals" >&2
exit 1
fi

shortcut_owners="$(grep -R -l 'CoCreateInstance.*ShellLink\|CoCreateInstance(&ShellLink' \
packages --include='*.rs' || true)"
if [ "$(printf '%s\n' "$shortcut_owners" | sed '/^$/d' | wc -l)" -ne 1 ]; then
echo "expected exactly one Windows COM shortcut implementation, found:" >&2
printf '%s\n' "$shortcut_owners" >&2
exit 1
fi
35 changes: 35 additions & 0 deletions .github/workflows/compatibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Compatibility

on:
pull_request:
push:
branches: [master]

jobs:
frozen-api-client:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Reject api_client changes in pull requests
if: github.event_name == 'pull_request'
run: git diff --exit-code ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- packages/api_client
- name: Reject api_client drift
run: bash .github/scripts/check-api-client-frozen.sh
- name: Reject forbidden runtime dependencies
run: bash .github/scripts/check-dependency-boundaries.sh

test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- name: Test workspace
run: cargo test --workspace --all-targets
102 changes: 73 additions & 29 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading