|
1 | 1 | #!/usr/bin/env bash |
2 | 2 | # sync-litertlm-swift.sh |
3 | | -# Manual sync from helenkwok/LiteRTLM-Swift fork into vendored copies under |
4 | | -# expo-litert-lm/ios/. Pulls the source xcframework + Swift sources, runs the |
5 | | -# fork's scripts/rewrap-xcframework.sh, and copies the rewrapped outputs into |
6 | | -# place. Version bumps and CHANGELOG entries are manual per offlineaid D-16. |
| 3 | +# Fetches rewrapped LiteRTLM-Swift xcframeworks from the fork's GitHub Release |
| 4 | +# by tag, verifies SHA-256 against rewrap-manifest.json, places artifacts |
| 5 | +# under ios/Frameworks/, bumps package.json version, copies manifest. |
| 6 | +# |
| 7 | +# Manual sync only — this script does NOT auto-commit. Operator reviews and |
| 8 | +# commits explicitly: ios/Frameworks/rewrap-manifest.json + package.json + |
| 9 | +# CHANGELOG.md. Do NOT commit the .xcframework binaries (gitignored). |
| 10 | +# |
| 11 | +# Requires: gh CLI authenticated as a user with read access to helenkwok/LiteRTLM-Swift |
| 12 | +# Requires: jq, shasum (macOS), npm (for version bump), unzip |
7 | 13 | # |
8 | 14 | # Usage: |
9 | | -# scripts/sync-litertlm-swift.sh [REF] # clone fork at REF (default: main) |
10 | | -# LITERTLM_SWIFT_LOCAL_PATH=/path scripts/sync-litertlm-swift.sh # use local fork checkout |
| 15 | +# scripts/sync-litertlm-swift.sh <tag> |
| 16 | +# e.g. scripts/sync-litertlm-swift.sh v0.7.3+rewrap.1 |
| 17 | +# |
| 18 | +# Phase 14 D-34, D-35 |
11 | 19 |
|
12 | 20 | set -euo pipefail |
13 | 21 |
|
14 | | -REF="${1:-main}" |
| 22 | +TAG="${1:-}" |
| 23 | +[ -n "$TAG" ] || { echo "usage: $0 <tag> (e.g. v0.7.3+rewrap.1)" >&2; exit 1; } |
| 24 | + |
| 25 | +REPO="helenkwok/LiteRTLM-Swift" |
| 26 | +DEST="ios/Frameworks" |
15 | 27 | ROOT="$(cd "$(dirname "$0")/.." && pwd)" |
16 | | -PKG_VERSION="$(node -p "require('${ROOT}/package.json').version")" |
17 | | -export LITERTLM_VERSION="${PKG_VERSION%-*}" # strip any -dev.N suffix for the xcframework Info.plist |
18 | | -export LITERTLM_BUILD="1" |
| 28 | +cd "$ROOT" |
| 29 | + |
| 30 | +echo "==> Syncing LiteRTLM-Swift $TAG from $REPO into $DEST/" |
| 31 | + |
| 32 | +# 1. Fetch manifest FIRST — it is the trust anchor for ALL xcframeworks. |
| 33 | +# Paying manifest bandwidth before xcframework bandwidth allows SHA verification |
| 34 | +# before downloading the (large) xcframework zips. |
| 35 | +tmpdir=$(mktemp -d) |
| 36 | +trap "rm -rf $tmpdir" EXIT |
| 37 | + |
| 38 | +echo " Fetching rewrap-manifest.json..." |
| 39 | +gh release download "$TAG" --repo "$REPO" --pattern 'rewrap-manifest.json' --dir "$tmpdir" |
| 40 | +manifest="$tmpdir/rewrap-manifest.json" |
19 | 41 |
|
20 | | -echo "==> Sync helenkwok/LiteRTLM-Swift -> expo-litert-lm/ios/ (ref=${REF}, version=${LITERTLM_VERSION})" |
| 42 | +schema_version=$(jq -r .schema_version "$manifest") |
| 43 | +[ "$schema_version" = "1" ] || { |
| 44 | + echo "FAIL: unexpected manifest schema_version=$schema_version (expected 1)" >&2 |
| 45 | + exit 1 |
| 46 | +} |
21 | 47 |
|
22 | | -# 1. Resolve fork source (clone or local path) |
23 | | -if [ -n "${LITERTLM_SWIFT_LOCAL_PATH:-}" ]; then |
24 | | - FORK_DIR="$LITERTLM_SWIFT_LOCAL_PATH" |
25 | | - if [ ! -d "$FORK_DIR" ]; then |
26 | | - echo "ERROR: LITERTLM_SWIFT_LOCAL_PATH=$FORK_DIR does not exist" >&2 |
| 48 | +count=$(jq '.xcframeworks | length' "$manifest") |
| 49 | +[ "$count" -ge 2 ] || { |
| 50 | + echo "FAIL: manifest.xcframeworks has $count entries, expected >=2 (LiteRTLM-rewrapped + GemmaModelConstraintProvider)" >&2 |
| 51 | + exit 1 |
| 52 | +} |
| 53 | + |
| 54 | +echo " Manifest OK: schema_version=$schema_version, $count xcframeworks" |
| 55 | + |
| 56 | +# 2. For EACH xcframework entry: fetch zip, verify SHA-256, unzip into DEST. |
| 57 | +mkdir -p "$DEST" |
| 58 | + |
| 59 | +jq -c '.xcframeworks[]' "$manifest" | while read -r entry; do |
| 60 | + name=$(echo "$entry" | jq -r .name) |
| 61 | + zip_filename=$(echo "$entry" | jq -r .zip_filename) |
| 62 | + expected_sha=$(echo "$entry" | jq -r .zip_sha256) |
| 63 | + |
| 64 | + # Validate expected sha is 64-hex (guards against manifest with placeholder) |
| 65 | + if ! [[ "$expected_sha" =~ ^[0-9a-f]{64}$ ]]; then |
| 66 | + echo "FAIL: manifest entry '$name' has non-hex zip_sha256: '$expected_sha'" >&2 |
27 | 67 | exit 1 |
28 | 68 | fi |
29 | | - echo "==> Using local fork: $FORK_DIR" |
30 | | - CLEANUP="" |
31 | | -else |
32 | | - TMP="$(mktemp -d)" |
33 | | - FORK_DIR="$TMP/fork" |
34 | | - echo "==> Cloning helenkwok/LiteRTLM-Swift @ ${REF} into $FORK_DIR" |
35 | | - git clone --depth 1 --branch "$REF" \ |
36 | | - https://github.com/helenkwok/LiteRTLM-Swift.git "$FORK_DIR" |
37 | | - CLEANUP="$TMP" |
38 | | -fi |
39 | | - |
40 | | -# 2. Run the fork's rewrap script (idempotent — emits sibling -rewrapped + GMCP xcframeworks) |
41 | | -(cd "$FORK_DIR" && ./scripts/rewrap-xcframework.sh Frameworks/LiteRTLM.xcframework >/dev/null) |
42 | | - |
43 | | -REWRAPPED="$FORK_DIR/Frameworks/LiteRTLM-rewrapped.xcframework" |
44 | | -GMCP="$FORK_DIR/Frameworks/GemmaModelConstraintProvider.xcframework" |
45 | | - |
46 | | -[ -d "$REWRAPPED" ] || { echo "ERROR: rewrap did not produce $REWRAPPED" >&2; exit 1; } |
47 | | -[ -d "$GMCP" ] || { echo "ERROR: rewrap did not produce $GMCP" >&2; exit 1; } |
48 | | - |
49 | | -# 3. Stage vendored copies |
50 | | -DEST_FW="$ROOT/ios/Frameworks" |
51 | | -DEST_SRC="$ROOT/ios/Sources" |
52 | | -mkdir -p "$DEST_FW" "$DEST_SRC" |
53 | | - |
54 | | -# Drop the -rewrapped suffix so podspec references stay clean (D-15 — vendored |
55 | | -# copy is authoritative). |
56 | | -rm -rf "$DEST_FW/CLiteRTLM.xcframework" "$DEST_FW/GemmaModelConstraintProvider.xcframework" |
57 | | -cp -R "$REWRAPPED" "$DEST_FW/CLiteRTLM.xcframework" |
58 | | -cp -R "$GMCP" "$DEST_FW/GemmaModelConstraintProvider.xcframework" |
59 | | - |
60 | | -rm -rf "$DEST_SRC/LiteRTLMSwift" |
61 | | -cp -R "$FORK_DIR/Sources/LiteRTLMSwift" "$DEST_SRC/LiteRTLMSwift" |
62 | | - |
63 | | -# 4. Tree summary |
64 | | -echo "" |
65 | | -echo "==> Vendored copy summary:" |
66 | | -find "$DEST_FW" "$DEST_SRC" -maxdepth 3 -type d | sed "s|$ROOT/||" |
67 | | -echo "" |
68 | | -du -sh "$DEST_FW"/*.xcframework "$DEST_SRC/LiteRTLMSwift" 2>/dev/null |
69 | 69 |
|
70 | | -# 5. Cleanup temp clone |
71 | | -[ -n "$CLEANUP" ] && rm -rf "$CLEANUP" |
| 70 | + echo " Fetching $zip_filename..." |
| 71 | + gh release download "$TAG" --repo "$REPO" --pattern "$zip_filename" --dir "$tmpdir" |
| 72 | + |
| 73 | + actual_sha=$(shasum -a 256 "$tmpdir/$zip_filename" | awk '{print $1}') |
| 74 | + if [ "$actual_sha" != "$expected_sha" ]; then |
| 75 | + echo "FAIL: sha256 mismatch for $name" >&2 |
| 76 | + echo " expected: $expected_sha" >&2 |
| 77 | + echo " actual: $actual_sha" >&2 |
| 78 | + exit 1 |
| 79 | + fi |
| 80 | + |
| 81 | + echo " ✓ $name sha256 verified (${expected_sha:0:12}...)" |
| 82 | + |
| 83 | + # Remove existing xcframework if present, then unzip |
| 84 | + rm -rf "$DEST/$name" |
| 85 | + unzip -q "$tmpdir/$zip_filename" -d "$DEST" |
| 86 | + |
| 87 | + if [ ! -d "$DEST/$name" ]; then |
| 88 | + echo "FAIL: expected $DEST/$name after unzip of $zip_filename" >&2 |
| 89 | + echo " Contents of $DEST after unzip:" >&2 |
| 90 | + ls "$DEST/" >&2 |
| 91 | + exit 1 |
| 92 | + fi |
72 | 93 |
|
| 94 | + echo " ✓ $name installed at $DEST/$name" |
| 95 | +done |
| 96 | + |
| 97 | +# 3. Copy manifest into source-controlled location (single SoT on Pod side). |
| 98 | +# The manifest is the trust anchor and MUST be checked into source control. |
| 99 | +# The xcframework binaries are gitignored. |
| 100 | +cp "$manifest" "$DEST/rewrap-manifest.json" |
| 101 | +echo " ✓ rewrap-manifest.json written to $DEST/rewrap-manifest.json" |
| 102 | + |
| 103 | +# 4. Bump package.json version (per D-35, D-16). |
| 104 | +upstream_ver=$(jq -r .upstream_version "$manifest") |
| 105 | +rewrap_iter=$(jq -r .rewrap_iteration "$manifest") |
| 106 | +# e.g. 0.2.0-litertlm.0.7.3.r1 |
| 107 | +new_pkg_ver="0.2.0-litertlm.${upstream_ver#v}.r${rewrap_iter}" |
| 108 | +echo " Bumping package.json version to $new_pkg_ver..." |
| 109 | +npm version "$new_pkg_ver" --no-git-tag-version |
| 110 | + |
| 111 | +# 5. Append CHANGELOG entry |
| 112 | +first_sha=$(jq -r '.xcframeworks[0].zip_sha256' "$manifest") |
| 113 | +date_str=$(date -u +"%Y-%m-%d") |
| 114 | +echo "${date_str} — synced rewrapped LiteRTLM-Swift $TAG ($count xcframeworks, first sha256: ${first_sha:0:12}...)" >> CHANGELOG.md |
| 115 | +echo " ✓ CHANGELOG.md updated" |
| 116 | + |
| 117 | +echo "" |
| 118 | +echo "==> Sync complete." |
| 119 | +echo "" |
| 120 | +echo "Files to COMMIT (manual review first):" |
| 121 | +echo " $DEST/rewrap-manifest.json (trust anchor — MUST be committed)" |
| 122 | +echo " package.json (version bumped to $new_pkg_ver)" |
| 123 | +echo " CHANGELOG.md (sync entry added)" |
| 124 | +echo "" |
| 125 | +echo "Files to NOT COMMIT (gitignored binaries):" |
| 126 | +jq -r '.xcframeworks[].name' "$manifest" | while read -r xcf; do |
| 127 | + echo " $DEST/$xcf" |
| 128 | +done |
73 | 129 | echo "" |
74 | | -echo "REMINDER: bump package.json version + add CHANGELOG entry before publishing — see offlineaid CONTEXT D-16." |
| 130 | +echo "Suggested commit message:" |
| 131 | +echo " chore(sync): rewrapped LiteRTLM-Swift $TAG ($count xcframeworks)" |
0 commit comments