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
14 changes: 14 additions & 0 deletions .github/workflows/ci-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# codegen.sh formats its generated Rust with `cargo +nightly fmt`.
- uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly
with:
toolchain: nightly
components: rustfmt
- uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # stable
- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2.8.1
- uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0
Expand All @@ -31,6 +36,15 @@ jobs:
- uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
with:
gradle-version: "8.9"
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
# truapi-server declares its generated modules unconditionally and they are
# gitignored, so the crate does not compile until codegen has run.
- name: Generate the Rust codegen output
run: |
npm ci --ignore-scripts
TRUAPI_SKIP_PACKAGE_BUILD=1 ./scripts/codegen.sh
- name: Generate UniFFI Kotlin bindings
run: make uniffi-kotlin
- name: Compile the shell against the bindings
Expand Down
117 changes: 91 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ permissions:

jobs:
rust:
needs: codegen
name: Rust workspace
runs-on: ubuntu-latest
env:
Expand All @@ -38,6 +39,11 @@ jobs:

- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2

- name: Download codegen output
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: codegen-output

- name: cargo build
run: cargo build --workspace --all-targets --all-features

Expand Down Expand Up @@ -121,15 +127,18 @@ jobs:
- name: Install workspace deps
run: npm ci --ignore-scripts

- name: Check no generated outputs are committed
run: |
committed="$(git ls-files -ci --exclude-standard)"
if [ -n "$committed" ]; then
echo "$committed"
echo "Generated outputs above are committed. Untrack them with 'git rm --cached'." >&2
exit 1
fi

- name: Run codegen
run: ./scripts/codegen.sh

- name: Check generated Rust output is committed
run: |
git diff --exit-code -- \
rust/crates/truapi-server/src/generated \
rust/crates/truapi-server/src/wasm/generated_bridge.rs

- name: Check Rust/TS wire table parity
run: TRUAPI_REQUIRE_GENERATED_TS=1 cargo test -p truapi-server --test wire_table_ts_parity

Expand All @@ -146,9 +155,12 @@ jobs:
js/packages/truapi/src/explorer/versions.ts
js/packages/truapi-host/src/generated
playground/test/generated
rust/crates/truapi-server/src/generated
rust/crates/truapi-server/src/wasm

ios-bindings:
name: iOS bindings (uniffi)
needs: codegen
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -161,19 +173,24 @@ jobs:

- uses: Swatinem/rust-cache@f0d9c3887740aee45f6153b24b3a6b815192ec16 # v2

# truapi-server declares its generated modules unconditionally, so the
# cdylib bindgen builds from does not compile without the codegen output.
- name: Download codegen output
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: codegen-output

# Swift bindgen is pure Rust codegen, so this needs neither Xcode nor the
# iOS targets, unlike rebuild.sh which also builds the xcframework.
# iOS targets, unlike rebuild.sh which also builds the xcframework. It
# gates that every UniFFI-exposed type still has a binding representation.
- name: Generate Swift bindings
run: make uniffi

- name: Check committed iOS bindings are current
run: ./ios/truapi-host/scripts/sync-bindings.sh --check
- name: Sync iOS bindings into package
run: ./ios/truapi-host/scripts/sync-bindings.sh

# The provider ships its own UniFFI surface and its own committed
# bindings; `rebuild.sh` overwrites them in place, so only this check
# can fail on drift.
- name: Check committed TrUAPIProvider bindings are current
run: make provider-swift-check
- name: Generate TrUAPIProvider bindings
run: make provider-swift

ios-changes:
name: iOS change filter
Expand All @@ -190,10 +207,10 @@ jobs:
# ios-swift on the output. On pull_request the checkout is the merge
# commit, so HEAD^1 is the base. Other events always run the gate.
#
# The list needs no broader rust/ entry: the generated bindings are
# committed under ios/, and ios-bindings runs unconditionally, so a Rust
# change that moves the UniFFI surface either carries an ios/ change or
# fails there first.
# The bindings are generated, not committed, so a UniFFI surface change
# leaves no ios/ diff to key on. The list therefore names every crate the
# bindings are generated from, plus js/container, which is compiled into
# the TrUAPIHost target as a resource.
- name: Detect iOS-relevant changes
id: filter
run: |
Expand All @@ -203,15 +220,15 @@ jobs:
exit 0
fi
if git diff --name-only HEAD^1 HEAD \
| grep -qE '^(ios/|Package\.swift$|Makefile$|rust/crates/truapi-server/src/native|rust/crates/truapi-provider/)'; then
| grep -qE '^(ios/|Package\.swift$|Makefile$|js/container/|rust/crates/truapi/|rust/crates/truapi-platform/|rust/crates/truapi-server/|rust/crates/truapi-provider/)'; then
echo "ios=true" >> "$GITHUB_OUTPUT"
else
echo "ios=false" >> "$GITHUB_OUTPUT"
fi

ios-swift:
name: iOS package (swift compile)
needs: ios-changes
needs: [ios-changes, codegen]
if: needs.ios-changes.outputs.ios == 'true'
runs-on: macos-15
timeout-minutes: 30
Expand All @@ -224,6 +241,10 @@ jobs:
with:
persist-credentials: false

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22

- uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # stable
with:
toolchain: stable
Expand All @@ -233,31 +254,75 @@ jobs:
with:
shared-key: ios-swift-gate

- name: Download codegen output
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: codegen-output

# Simulator slice only, debug profile. This gate compiles Swift and ships
# no binary, so the device slice and release codegen are waste. The
# published binary is older than the current Rust surface, so
# TRUAPI_USE_LOCAL_BINARY points the manifest at this build instead.
- name: Build the simulator XCFramework
run: make xcframework XCFRAMEWORK_TARGETS=aarch64-apple-ios-sim XCFRAMEWORK_PROFILE=debug

# make xcframework leaves the bindings in target/uniffi-swift-out; the
# package's Swift targets are gitignored, so they only exist once this
# copies them in.
- name: Sync the generated Swift bindings into the package
run: ./ios/truapi-host/scripts/sync-bindings.sh

- name: Stage it into the package
run: ./ios/truapi-host/scripts/stage-xcframework.sh

# TrUAPIHost declares Resources/truapi-container.js as a .copy resource,
# so SwiftPM refuses to resolve the package until this exists.
- name: Build the lockdown container bundle
run: |
npm --prefix js/container install --no-fund --no-audit
npm --prefix js/container run build

- name: Build the simulator XCFramework for TrUAPIProvider
run: PROFILE=debug ./ios/truapi-provider/scripts/rebuild.sh --sim-only

# Compiling the test target is the point: the hand-written conformers a
# generated-file diff cannot see live there and in TrUAPIHost.swift.
- name: Compile the package and its tests
# Build the tag a release would cut, then compile from a clean clone of
# it. Compiling in place would pass on generated files that the tag does
# not carry, which is exactly the failure this guards: a consumer only
# ever sees the tag.
- name: Build the SwiftPM consumer tag
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
./ios/truapi-host/scripts/tag-release.sh 0.0.0-ci

- name: Check the tag carries every generated file
run: |
set -euo pipefail
probe="$RUNNER_TEMP/tag-probe"
rm -rf "$probe"
git clone --quiet --branch 0.0.0-ci "file://$PWD" "$probe"
while read -r path; do
diff -u <(cd "$probe" && find "$path" -type f | sort) \
<(find "$path" -type f | sort)
done <<< "$(sed -n -E 's/^[[:space:]]*path: "([^"]+)".*/\1/p' Package.swift | grep -v '/Binaries/')"

# The xcframework ships as a release asset rather than in the tag, so the
# locally built one stands in for it here.
- name: Compile the package and its tests from the tag
run: |
set -euo pipefail
probe="$RUNNER_TEMP/tag-probe"
mkdir -p "$probe/ios/truapi-host/Binaries" "$probe/ios/truapi-provider/Binaries"
cp -R ios/truapi-host/Binaries/truapi_server.xcframework "$probe/ios/truapi-host/Binaries/"
cp -R ios/truapi-provider/Binaries/truapi_provider.xcframework "$probe/ios/truapi-provider/Binaries/"
cd "$probe"
xcodebuild build-for-testing \
-scheme TrUAPIHost \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath "$RUNNER_TEMP/TrUAPIHostDerivedData" \
CODE_SIGNING_ALLOWED=NO

- name: Compile TrUAPIProvider
run: swift build --target TrUAPIProvider
swift build --target TrUAPIProvider

ts-client:
name: "@parity/truapi"
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/release-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ jobs:
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false

# codegen.sh formats its generated Rust with `cargo +nightly fmt`.
- uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly
with:
toolchain: nightly
components: rustfmt
- uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # stable
with:
targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android
Expand All @@ -58,6 +63,15 @@ jobs:
with:
gradle-version: "8.9"

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
# truapi-server declares its generated modules unconditionally and they are
# gitignored, so the crate does not compile until codegen has run.
- name: Generate the Rust codegen output
run: |
npm ci --ignore-scripts
TRUAPI_SKIP_PACKAGE_BUILD=1 ./scripts/codegen.sh
- name: Generate UniFFI Kotlin bindings
run: make uniffi-kotlin

Expand Down
Loading