@ondeinference / ed / commits / 37da62b

Patch sysctl for watchOS and fix the release publish steps

The 0.1.0 run died 2h20m in, on the eighth of nine targets: aarch64-apple-watchos failed with `cannot find module or crate sys`. gemm-common (via candle, via onde) depends on sysctl for every `target_vendor = "apple"`, and stock sysctl 0.6.0 gates its sys module on macOS/iOS/tvOS/visionOS/freeBSD only. onde already patches this, but cargo honours [patch] only from the manifest of the workspace being built, so consuming onde from crates.io inherits nothing. Repeat the patch here. Two more faults sat behind that one, both after the expensive build had already been paid for: The Swift package repo is ondeinference/ed-swift. onde-ed-swift is only the name of the local checkout, so that step would have 404'd after the release assets were uploaded. The tag check compared v0.1.0 against version.txt's 0.1.0. Preflight strips the v prefix and this step did not, because it was copied from onde, whose tags carry no prefix. Also name each target in the build script. Cargo never prints the target it is compiling, so working out which slice failed meant counting `Finished` lines across a 5000 line log. Co-Authored-By: siGit Code <noreply@sigit.si>

Seto Elkahfi committed Sep 11, 2026 at 04:31 UTC 37da62b2c6be3f0bfe7c1c7f0ab07c5e4a3f43e0
4 files changed +57 -18
.github/scripts/build-swift-xcframework.sh
+27 -9
@@ -26,15 +26,33 @@ mkdir -p "$PACKAGE_DIR/Sources/Ed" "$HEADERS_DIR"
26
27 cargo build --manifest-path uniffi-bindgen/Cargo.toml --release
28
29 -IPHONEOS_DEPLOYMENT_TARGET="$IOS_DEPLOYMENT_TARGET" cargo rustc --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-ios --release --lib --crate-type staticlib
30 -IPHONEOS_DEPLOYMENT_TARGET="$IOS_DEPLOYMENT_TARGET" cargo rustc --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-ios-sim --release --lib --crate-type staticlib
31 -MACOSX_DEPLOYMENT_TARGET="$MACOS_DEPLOYMENT_TARGET" cargo rustc --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-darwin --release --lib --crate-type staticlib
32 -TVOS_DEPLOYMENT_TARGET="$TVOS_DEPLOYMENT_TARGET" cargo +nightly rustc -Z build-std --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-tvos --release --lib --crate-type staticlib
33 -TVOS_DEPLOYMENT_TARGET="$TVOS_DEPLOYMENT_TARGET" cargo +nightly rustc -Z build-std --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-tvos-sim --release --lib --crate-type staticlib
34 -XROS_DEPLOYMENT_TARGET="$VISIONOS_DEPLOYMENT_TARGET" cargo +nightly rustc -Z build-std --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-visionos --release --lib --crate-type staticlib
35 -XROS_DEPLOYMENT_TARGET="$VISIONOS_DEPLOYMENT_TARGET" cargo +nightly rustc -Z build-std --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-visionos-sim --release --lib --crate-type staticlib
36 -WATCHOS_DEPLOYMENT_TARGET="$WATCHOS_DEPLOYMENT_TARGET" cargo +nightly rustc -Z build-std --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-watchos --release --lib --crate-type staticlib
37 -WATCHOS_DEPLOYMENT_TARGET="$WATCHOS_DEPLOYMENT_TARGET" cargo +nightly rustc -Z build-std --target-dir "$APPLE_TARGET_DIR" --manifest-path "$MANIFEST" --target aarch64-apple-watchos-sim --release --lib --crate-type staticlib
29 +# Each slice takes 15-20 minutes and cargo never prints the target it is
30 +# building, so a bare `error: could not compile` an hour into the log cannot be
31 +# attributed without counting `Finished` lines. Announce every target.
32 +#
33 +# The tvOS, visionOS and watchOS targets are tier 3: no prebuilt std ships for
34 +# them, hence nightly and -Z build-std.
35 +build_target() {
36 + local target="$1" deployment="$2"
37 + shift 2
38 + echo "::group::cargo rustc --target $target"
39 + env "$deployment" cargo "$@" rustc \
40 + --target-dir "$APPLE_TARGET_DIR" \
41 + --manifest-path "$MANIFEST" \
42 + --target "$target" \
43 + --release --lib --crate-type staticlib
44 + echo "::endgroup::"
45 +}
46 +
47 +build_target aarch64-apple-ios "IPHONEOS_DEPLOYMENT_TARGET=$IOS_DEPLOYMENT_TARGET"
48 +build_target aarch64-apple-ios-sim "IPHONEOS_DEPLOYMENT_TARGET=$IOS_DEPLOYMENT_TARGET"
49 +build_target aarch64-apple-darwin "MACOSX_DEPLOYMENT_TARGET=$MACOS_DEPLOYMENT_TARGET"
50 +build_target aarch64-apple-tvos "TVOS_DEPLOYMENT_TARGET=$TVOS_DEPLOYMENT_TARGET" +nightly -Z build-std
51 +build_target aarch64-apple-tvos-sim "TVOS_DEPLOYMENT_TARGET=$TVOS_DEPLOYMENT_TARGET" +nightly -Z build-std
52 +build_target aarch64-apple-visionos "XROS_DEPLOYMENT_TARGET=$VISIONOS_DEPLOYMENT_TARGET" +nightly -Z build-std
53 +build_target aarch64-apple-visionos-sim "XROS_DEPLOYMENT_TARGET=$VISIONOS_DEPLOYMENT_TARGET" +nightly -Z build-std
54 +build_target aarch64-apple-watchos "WATCHOS_DEPLOYMENT_TARGET=$WATCHOS_DEPLOYMENT_TARGET" +nightly -Z build-std
55 +build_target aarch64-apple-watchos-sim "WATCHOS_DEPLOYMENT_TARGET=$WATCHOS_DEPLOYMENT_TARGET" +nightly -Z build-std
56
57 "$BINDGEN" generate "$APPLE_TARGET_DIR/aarch64-apple-ios/release/libed_agent_ffi.a" --crate ed_agent_ffi --language swift --out-dir "$PACKAGE_DIR/Sources/Ed"
58 cp "$PACKAGE_DIR/Sources/Ed/ed_agent_ffiFFI.h" "$HEADERS_DIR/ed_agent_ffiFFI.h"
.github/workflows/release-sdk-swift.yml
+18 -7
@@ -114,7 +114,18 @@ jobs:
114 env:
115 VERSION: ${{ steps.meta.outputs.version }}
116 RELEASE_TAG: ${{ steps.release.outputs.release_tag }}
117 - run: test -n "$RELEASE_TAG" && test "$RELEASE_TAG" = "$VERSION"
117 + run: |
118 + if [ -z "$RELEASE_TAG" ]; then
119 + echo "::error::release_tag is required when publish=true on workflow_dispatch runs."
120 + exit 1
121 + fi
122 + # Ed tags carry a `v` prefix, version.txt does not, so compare the
123 + # semver rather than the spelling -- the same normalisation preflight
124 + # does on GITHUB_REF_NAME.
125 + if [ "${RELEASE_TAG#v}" != "$VERSION" ]; then
126 + echo "::error::Release tag '$RELEASE_TAG' does not match workspace version '$VERSION'."
127 + exit 1
128 + fi
129 - name: Upload build artifact
130 if: github.event_name == 'workflow_dispatch'
131 uses: actions/upload-artifact@v7
@@ -135,13 +146,13 @@ jobs:
146 files: |
147 ed/dist/swift/EdFramework.xcframework.zip
148 ed/dist/swift/EdFramework.checksum.txt
138 - - name: Checkout onde-ed-swift
149 + - name: Checkout ed-swift
150 if: startsWith(github.ref, 'refs/tags/') || inputs.publish
151 uses: actions/checkout@v6
152 with:
142 - repository: ondeinference/onde-ed-swift
153 + repository: ondeinference/ed-swift
154 token: ${{ secrets.ED_SWIFT_PAT }}
144 - path: onde-ed-swift
155 + path: ed-swift
156 - name: Update Swift package
157 if: startsWith(github.ref, 'refs/tags/') || inputs.publish
158 working-directory: ${{ github.workspace }}
@@ -151,7 +162,7 @@ jobs:
162 run: |
163 python3 - <<'PY'
164 import os, pathlib, re
154 - package = pathlib.Path("onde-ed-swift/Package.swift")
165 + package = pathlib.Path("ed-swift/Package.swift")
166 source = package.read_text()
167 source, urls = re.subn(r'(let releaseFrameworkURL =\s*\n\s*")([^"]+)(")', rf'\g<1>{os.environ["RELEASE_URL"]}\g<3>', source, count=1)
168 source, sums = re.subn(r'(let releaseFrameworkChecksum =\s*\n\s*")([^"]+)(")', rf'\g<1>{os.environ["CHECKSUM"]}\g<3>', source, count=1)
@@ -159,10 +170,10 @@ jobs:
170 raise RuntimeError("Package.swift release constants were not found")
171 package.write_text(source)
172 PY
162 - cp ed/dist/swift/Package/Sources/Ed/ed_agent_ffi.swift onde-ed-swift/Sources/Ed/ed_agent_ffi.swift
173 + cp ed/dist/swift/Package/Sources/Ed/ed_agent_ffi.swift ed-swift/Sources/Ed/ed_agent_ffi.swift
174 - name: Commit and tag Swift package
175 if: startsWith(github.ref, 'refs/tags/') || inputs.publish
165 - working-directory: ${{ github.workspace }}/onde-ed-swift
176 + working-directory: ${{ github.workspace }}/ed-swift
177 env:
178 VERSION: ${{ steps.release.outputs.release_tag }}
179 run: |
Cargo.lock
+1 -2
@@ -7216,8 +7216,7 @@ dependencies = [
7216 [[package]]
7217 name = "sysctl"
7218 version = "0.6.0"
7219 -source = "registry+https://github.com/rust-lang/crates.io-index"
7220 -checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc"
7219 +source = "git+https://github.com/setoelkahfi/sysctl-rs.git?branch=feature%2Fwatchos-0.6#e4036230bbde48ec1cc425803c8fda41012b73e2"
7220 dependencies = [
7221 "bitflags 2.13.2",
7222 "byteorder",
Cargo.toml
+11
@@ -30,3 +30,14 @@ smbcloud-gresiq-sdk = "0.4.7"
30
31 # Internal
32 ed-agent = { version = "1.0.0", path = "crates/ed-agent" }
33 +
34 +# gemm-common (via candle, via onde) depends on sysctl for every
35 +# `target_vendor = "apple"`, but sysctl 0.6.0 only has a `sys` module behind
36 +# macOS/iOS/tvOS/visionOS/freeBSD — the watchOS build fails to resolve it. onde
37 +# carries this same patch, but `[patch]` is only honoured from the manifest of
38 +# the workspace being built, so depending on onde does not inherit it: Ed has to
39 +# repeat it. The branch is cut from sysctl 0.6.0 rather than the fork's master
40 +# (0.7.1) because a patch that is semver-incompatible with the requirement in
41 +# the graph is silently ignored.
42 +[patch.crates-io]
43 +sysctl = { git = "https://github.com/setoelkahfi/sysctl-rs.git", branch = "feature/watchos-0.6" }