Skip to content
Draft
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
6 changes: 6 additions & 0 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
.claude/
.github/CODEOWNERS
.github/workflows/claude-code.yml
.github/workflows/ci.yml
.gitignore
WASM_VERSION
scripts/download-wasm.sh
scripts/e2e-pack.sh
CLAUDE.md
LICENSE
README.md
examples/
testapp/
testapp-packaged/
src/SchematicHQ.Client.Test/Cache/
src/SchematicHQ.Client.Test/Datastream/
src/SchematicHQ.Client.Test/Integration/
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ concurrency:

env:
DOTNET_NOLOGO: true
# Authenticates `gh release download` in scripts/download-wasm.sh; the rules engine
# WASM lives in the private SchematicHQ/schematic-api repo, so the default
# GITHUB_TOKEN (scoped to this repo) cannot read it. Requires a GH_TOKEN repo
# secret with read access to schematic-api releases.
GH_TOKEN: ${{ secrets.GH_TOKEN }}

jobs:
ci:
Expand All @@ -22,6 +27,9 @@ jobs:
with:
dotnet-version: 10.x

- name: Download WASM binary
run: ./scripts/download-wasm.sh

- name: Install tools
run: dotnet tool restore

Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,10 @@ $RECYCLE.BIN/

# Vim temporary swap files
*.swp

# Rules engine WASM binary (downloaded at build time from schematic-api GitHub Releases)
src/SchematicHQ.Client/RulesEngine/Wasm/rulesengine.wasm
src/SchematicHQ.Client/RulesEngine/Wasm/.wasm_version

# Local NuGet feed produced by scripts/e2e-pack.sh for the packaged-artifact E2E variant
artifacts/
2 changes: 1 addition & 1 deletion WASM_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.0
0.5.0
68 changes: 68 additions & 0 deletions scripts/download-wasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/bash
set -e

# Downloads the rules engine WASM binary from the schematic-api GitHub Release.
# Reads the pinned version from WASM_VERSION at the repo root.
#
# The binary is intentionally NOT tracked in git (see .gitignore); it is fetched
# at build time both locally (via the DownloadWasm MSBuild target) and in CI.

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
WASM_DIR="$REPO_ROOT/src/SchematicHQ.Client/RulesEngine/Wasm"
VERSION_FILE="$REPO_ROOT/WASM_VERSION"

GITHUB_REPO="SchematicHQ/schematic-api"

if [ ! -f "$VERSION_FILE" ]; then
echo "ERROR: WASM_VERSION file not found at $VERSION_FILE"
exit 1
fi

VERSION=$(tr -d '[:space:]' < "$VERSION_FILE")
TAG="rulesengine/v${VERSION}"
ASSET_NAME="rulesengine-wasm-csharp-v${VERSION}.tar.gz"

# Skip download if binary already exists and version matches
if [ -f "$WASM_DIR/rulesengine.wasm" ] && [ -f "$WASM_DIR/.wasm_version" ]; then
CURRENT=$(tr -d '[:space:]' < "$WASM_DIR/.wasm_version")
if [ "$CURRENT" = "$VERSION" ]; then
echo "WASM binary already at version $VERSION, skipping download."
exit 0
fi
fi

echo "Downloading rules engine WASM v${VERSION}..."
mkdir -p "$WASM_DIR"

TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT

if ! gh release download "$TAG" \
-R "$GITHUB_REPO" \
-p "$ASSET_NAME" \
-D "$TMPDIR" 2>/dev/null; then
echo "ERROR: Failed to download WASM binary"
echo "Tag: $TAG"
echo "Asset: $ASSET_NAME"
echo ""
echo "If this is a new version, ensure a release exists at:"
echo " https://github.com/${GITHUB_REPO}/releases/tag/${TAG}"
echo ""
echo "Ensure the GitHub CLI is authenticated with access to ${GITHUB_REPO}: gh auth status"
exit 1
fi

tar -xzf "$TMPDIR/$ASSET_NAME" -C "$TMPDIR"

if [ ! -f "$TMPDIR/rulesengine.wasm" ]; then
echo "ERROR: rulesengine.wasm not found in release archive"
ls -la "$TMPDIR"
exit 1
fi

cp "$TMPDIR"/rulesengine.wasm "$WASM_DIR/"

echo "$VERSION" > "$WASM_DIR/.wasm_version"

echo "Downloaded rules engine WASM v${VERSION} to $WASM_DIR/"
61 changes: 61 additions & 0 deletions scripts/e2e-pack.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
set -euo pipefail

# Packs the SchematicHQ.Client SDK into a local NuGet feed for the packaged-artifact
# E2E variant (testapp-packaged/). This validates the real distribution artifact:
# the embedded rulesengine.wasm and the transitive Wasmtime native library must
# survive pack -> restore -> run, which a plain <ProjectReference> build never
# exercises.
#
# Produces: artifacts/local-feed/SchematicHQ.Client.<version>.nupkg
# Consumed by: testapp-packaged/Testapp.Packaged.csproj (via testapp-packaged/nuget.config)

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
FEED_DIR="$REPO_ROOT/artifacts/local-feed"
PKG_VERSION="${SCHEMATIC_E2E_PKG_VERSION:-0.0.0-e2e}"

# Ensure the rules engine WASM is present before packing so it gets embedded.
"$SCRIPT_DIR/download-wasm.sh"

echo "Packing SchematicHQ.Client v${PKG_VERSION} -> ${FEED_DIR}"
rm -rf "$FEED_DIR"
mkdir -p "$FEED_DIR"

dotnet pack "$REPO_ROOT/src/SchematicHQ.Client/SchematicHQ.Client.csproj" \
-c Release \
-p:Version="$PKG_VERSION" \
-o "$FEED_DIR"

NUPKG="$FEED_DIR/SchematicHQ.Client.${PKG_VERSION}.nupkg"
if [ ! -f "$NUPKG" ]; then
echo "ERROR: expected package not produced: $NUPKG" >&2
exit 1
fi

# Guard: fail loudly if the embedded WASM did not make it into the packaged DLL.
# The wasm (~672 KB) is an embedded manifest resource inside SchematicHQ.Client.dll,
# not a loose package entry, so we verify by DLL size — the exact packaging
# regression this variant exists to catch (an empty/stripped resource ships a
# DLL hundreds of KB smaller).
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
unzip -o -q "$NUPKG" -d "$TMP"

DLL="$TMP/lib/net8.0/SchematicHQ.Client.dll"
if [ ! -f "$DLL" ]; then
echo "ERROR: lib/net8.0/SchematicHQ.Client.dll missing from package" >&2
exit 1
fi

# Cross-platform file size (macOS: stat -f%z, Linux: stat -c%s).
DLL_SIZE=$(stat -f%z "$DLL" 2>/dev/null || stat -c%s "$DLL")
MIN_SIZE=600000 # rulesengine.wasm is ~672 KB; a DLL without it is far smaller.
if [ "$DLL_SIZE" -lt "$MIN_SIZE" ]; then
echo "ERROR: packaged DLL is ${DLL_SIZE} bytes (< ${MIN_SIZE})." >&2
echo " rulesengine.wasm appears NOT embedded — the package would silently" >&2
echo " fall back to flag defaults at runtime." >&2
exit 1
fi

echo "Packed OK: $NUPKG (embedded DLL ${DLL_SIZE} bytes)"
154 changes: 0 additions & 154 deletions src/SchematicHQ.Client.Test/RulesEngine/CompanyTests.cs

This file was deleted.

Loading
Loading