Skip to content

Commit 325a7c3

Browse files
feat: JS/TS bindings (agntcy#1146)
# Description - React Native bindings: -- generated with https://github.com/jhugman/uniffi-bindgen-react-native --p2p Alice and Bob example with IOS test application - Node js bindings: -- generated with https://github.com/livekit/uniffi-bindgen-node -- p2p Alice, Bob and server examples TBD: - testing - release process ## Type of Change - [ ] Bugfix - [ ] New Feature - [ ] Breaking Change - [ ] Refactor - [ ] Documentation - [ ] Other (please describe) ## Checklist - [ ] I have read the [contributing guidelines](/agntcy/repo-template/blob/main/CONTRIBUTING.md) - [ ] Existing issues have been referenced (where applicable) - [ ] I have verified this change is not present in other open pull requests - [ ] Functionality is documented - [ ] All code style checks pass - [ ] New code contribution is covered by automated tests - [ ] All new and existing tests pass --------- Signed-off-by: Janos Sarusi-Kis <janossk@cisco.com>
1 parent 1c15071 commit 325a7c3

79 files changed

Lines changed: 22167 additions & 59 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
# Copyright AGNTCY Contributors (https://github.com/agntcy)
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Outputs the bindings version from a tag or GITHUB_REF.
6+
# Tag format: slim-bindings-v1.0.0 or slim-bindings-1.0.0 → 1.0.0
7+
# Usage: get-binding-version.sh [ref]
8+
# If no arg, uses GITHUB_REF env var. Otherwise uses the first argument.
9+
10+
set -euo pipefail
11+
12+
ref="${1:-${GITHUB_REF:-}}"
13+
if [ -z "$ref" ]; then
14+
echo "Usage: $0 <ref> OR set GITHUB_REF" >&2
15+
exit 1
16+
fi
17+
18+
# Strip refs/tags/ if present
19+
tag="${ref#refs/tags/}"
20+
# Strip tag prefix (slim-bindings- or slim-node-test-bindings- for test tags)
21+
version="${tag#slim-bindings-}"
22+
version="${version#slim-node-test-bindings-}"
23+
version="${version#v}"
24+
echo "$version"

.github/workflows/release-bindings.yaml

Lines changed: 341 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ jobs:
107107
done
108108
109109
cd "$platform_dir"
110-
zip -r "../../release-artifacts/slim-bindings-${platform_name}.zip" *
110+
zip -r "../../release-artifacts/slim-bindings-${platform_name}.zip" .
111111
cd - > /dev/null
112112
113113
echo "✅ Created slim-bindings-${platform_name}.zip"
@@ -186,7 +186,346 @@ jobs:
186186
nuget-api-token: ${{ secrets.NUGET_API_TOKEN }}
187187

188188
# ==========================================================================
189-
# Job 6: Release Kotlin bindings to GitHub Packages
189+
# Job 6: Generate Node bindings once (x86_64 Linux) for use by all pack jobs.
190+
# uniffi-bindgen-node must load the .so on the host; we only have native lib for
191+
# the runner, so we generate once then pack per target with each target's lib.
192+
# ==========================================================================
193+
generate-node-bindings-once:
194+
name: Generate Node bindings (once)
195+
runs-on: ubuntu-latest
196+
needs:
197+
- build-and-test-bindings
198+
steps:
199+
- name: Checkout code
200+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
201+
with:
202+
persist-credentials: false
203+
204+
- name: Setup Rust
205+
uses: ./.github/actions/setup-rust
206+
with:
207+
workspace: ./data-plane
208+
209+
- name: Setup Node
210+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
211+
with:
212+
node-version: '20'
213+
# Release workflow: disable GHA npm cache (zizmor cache-poisoning / trusted tag builds only).
214+
package-manager-cache: false
215+
216+
- name: Setup Task
217+
uses: ./.github/actions/setup-task
218+
219+
- name: Download library artifact (x86_64 Linux)
220+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
221+
with:
222+
name: bindings-x86_64-unknown-linux-gnu
223+
path: .
224+
225+
- name: Place library for Node generate
226+
run: |
227+
RELEASE_DIR="data-plane/target/x86_64-unknown-linux-gnu/release"
228+
mkdir -p "$RELEASE_DIR"
229+
if [ -n "$(find "$RELEASE_DIR" -mindepth 1 -print -quit 2>/dev/null)" ]; then
230+
echo "Library files (from artifact path):"
231+
find "$RELEASE_DIR" -maxdepth 1 ! -path "$RELEASE_DIR" -ls
232+
exit 0
233+
fi
234+
find . -name '*slim_bindings*' -type f -exec cp -v {} "$RELEASE_DIR/" \; 2>/dev/null
235+
[ -n "$(find "$RELEASE_DIR" -mindepth 1 -print -quit 2>/dev/null)" ] || { echo "No library files found."; find . -maxdepth 4 -ls 2>/dev/null | head -80; exit 1; }
236+
echo "Library files (copied):"
237+
find "$RELEASE_DIR" -maxdepth 1 ! -path "$RELEASE_DIR" -ls
238+
239+
- name: Generate Node bindings
240+
working-directory: ./data-plane/bindings/node
241+
run: |
242+
npm install
243+
task generate TARGET=x86_64-unknown-linux-gnu
244+
245+
- name: Upload generated bindings
246+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
247+
with:
248+
name: node-generated-bindings
249+
path: ./data-plane/bindings/node/generated/
250+
251+
# ==========================================================================
252+
# Job 7: Build Node platform packages (matrix: one per target with .so/.dylib/.dll).
253+
# Uses pre-generated bindings + each target's library (no uniffi-bindgen-node on non-native libs).
254+
# musl excluded: Rust build produces only static .a for musl, no .so.
255+
# ==========================================================================
256+
build-node-packages:
257+
name: Node ${{ matrix.target }}
258+
runs-on: ubuntu-latest
259+
needs:
260+
- build-and-test-bindings
261+
- generate-node-bindings-once
262+
strategy:
263+
fail-fast: false
264+
matrix:
265+
target:
266+
- x86_64-unknown-linux-gnu
267+
- aarch64-apple-darwin
268+
- x86_64-apple-darwin
269+
- x86_64-pc-windows-msvc
270+
- aarch64-unknown-linux-gnu
271+
- aarch64-pc-windows-msvc
272+
steps:
273+
- name: Checkout code
274+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
275+
with:
276+
persist-credentials: false
277+
278+
- name: Get bindings version
279+
id: version
280+
run: echo "version=$(bash .github/scripts/get-binding-version.sh)" >> "$GITHUB_OUTPUT"
281+
282+
- name: Setup Node
283+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
284+
with:
285+
node-version: '20'
286+
package-manager-cache: false
287+
288+
- name: Setup Task
289+
uses: ./.github/actions/setup-task
290+
291+
- name: Download generated bindings
292+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
293+
with:
294+
name: node-generated-bindings
295+
path: ./data-plane/bindings/node/generated/
296+
297+
- name: Download library artifact
298+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
299+
with:
300+
name: bindings-${{ matrix.target }}
301+
path: .
302+
303+
- name: Place library for Node pack
304+
run: |
305+
RELEASE_DIR="data-plane/target/${{ matrix.target }}/release"
306+
mkdir -p "$RELEASE_DIR"
307+
if [ -n "$(find "$RELEASE_DIR" -mindepth 1 -print -quit 2>/dev/null)" ]; then
308+
echo "Library files (from artifact path):"
309+
find "$RELEASE_DIR" -maxdepth 1 ! -path "$RELEASE_DIR" -ls
310+
exit 0
311+
fi
312+
find . -name '*slim_bindings*' -type f -exec cp -v {} "$RELEASE_DIR/" \; 2>/dev/null
313+
if [ -n "$(find "$RELEASE_DIR" -mindepth 1 -print -quit 2>/dev/null)" ]; then
314+
echo "Library files (copied):"
315+
find "$RELEASE_DIR" -maxdepth 1 ! -path "$RELEASE_DIR" -ls
316+
exit 0
317+
fi
318+
echo "No library files found after download."
319+
find . -maxdepth 4 -ls 2>/dev/null | head -80
320+
exit 1
321+
322+
- name: Pack Node platform package
323+
working-directory: ./data-plane/bindings/node
324+
run: |
325+
npm install
326+
task pack:platform:from-artifacts TARGET=${{ matrix.target }} VERSION=${{ steps.version.outputs.version }}
327+
328+
- name: Upload Node platform package
329+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
330+
with:
331+
name: node-platform-${{ matrix.target }}
332+
path: ./data-plane/bindings/node/dist/node-*.tgz
333+
334+
# ==========================================================================
335+
# Job 8: Publish Node platform packages to npm
336+
# ==========================================================================
337+
publish-node-platform-packages:
338+
name: Publish Node platform packages
339+
runs-on: ubuntu-latest
340+
needs: build-node-packages
341+
permissions:
342+
contents: read
343+
steps:
344+
- name: Download all Node platform artifacts
345+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
346+
with:
347+
path: ./node-packages
348+
pattern: node-platform-*
349+
350+
- name: Configure npm auth
351+
run: echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc
352+
env:
353+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
354+
355+
- name: Publish to npm
356+
run: |
357+
for tgz in ./node-packages/node-platform-*/*.tgz; do
358+
[ -f "$tgz" ] || continue
359+
echo "Publishing $tgz..."
360+
npm publish "$tgz" --access public
361+
done
362+
env:
363+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
364+
365+
# ==========================================================================
366+
# Job 9: Publish Node main package to npm
367+
# Uses pre-generated bindings from generate-node-bindings-once; only emits types and publishes.
368+
# ==========================================================================
369+
publish-node-main:
370+
name: Publish Node main package
371+
runs-on: ubuntu-latest
372+
needs:
373+
- publish-node-platform-packages
374+
- generate-node-bindings-once
375+
permissions:
376+
contents: read
377+
steps:
378+
- name: Checkout code
379+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
380+
with:
381+
persist-credentials: false
382+
383+
- name: Get bindings version
384+
id: version
385+
run: echo "version=$(bash .github/scripts/get-binding-version.sh)" >> "$GITHUB_OUTPUT"
386+
387+
- name: Setup Node
388+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
389+
with:
390+
node-version: '20'
391+
package-manager-cache: false
392+
393+
- name: Setup Task
394+
uses: ./.github/actions/setup-task
395+
396+
- name: Download generated bindings
397+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
398+
with:
399+
name: node-generated-bindings
400+
path: ./data-plane/bindings/node/generated/
401+
402+
- name: Emit types and prepare package
403+
working-directory: ./data-plane/bindings/node
404+
run: |
405+
npm install
406+
task emit-types
407+
408+
- name: Set version in package.json
409+
working-directory: ./data-plane/bindings/node
410+
env:
411+
BINDINGS_VERSION: ${{ steps.version.outputs.version }}
412+
run: |
413+
npm pkg set version="${BINDINGS_VERSION}"
414+
node -e "
415+
const pkg = require('./package.json');
416+
const v = process.env.BINDINGS_VERSION;
417+
const opt = pkg.optionalDependencies || {};
418+
for (const k of Object.keys(opt)) opt[k] = v;
419+
pkg.optionalDependencies = opt;
420+
require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));
421+
"
422+
423+
- name: Configure npm auth
424+
working-directory: ./data-plane/bindings/node
425+
run: echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc
426+
env:
427+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
428+
429+
- name: Publish main package to npm
430+
working-directory: ./data-plane/bindings/node
431+
run: npm publish --access public
432+
env:
433+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
434+
435+
# ==========================================================================
436+
# Job 10: Build and publish React Native bindings to npm
437+
# Runs on mac to build iOS static lib; requires NPM_TOKEN.
438+
# ==========================================================================
439+
publish-react-native:
440+
name: Publish React Native to npm
441+
runs-on: macos-15
442+
needs:
443+
- build-and-test-bindings
444+
permissions:
445+
contents: read
446+
steps:
447+
- name: Checkout code
448+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
449+
with:
450+
persist-credentials: false
451+
452+
- name: Get bindings version
453+
id: version
454+
run: echo "version=$(bash .github/scripts/get-binding-version.sh)" >> "$GITHUB_OUTPUT"
455+
456+
- name: Setup Rust
457+
uses: ./.github/actions/setup-rust
458+
with:
459+
workspace: ./data-plane
460+
461+
- name: Setup Task
462+
uses: ./.github/actions/setup-task
463+
464+
- name: Setup Node
465+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
466+
with:
467+
node-version: '20'
468+
registry-url: 'https://registry.npmjs.org'
469+
package-manager-cache: false
470+
471+
- name: Build iOS static libs (device + simulator)
472+
id: build-ios
473+
working-directory: ./data-plane/bindings/react-native
474+
env:
475+
# Required for ___chkstk_darwin: aws-lc-sys and linker need iOS 13.4+
476+
IPHONEOS_DEPLOYMENT_TARGET: "13.4"
477+
# Force linker wrapper via absolute path (Task's TASKFILE_DIR can differ on CI)
478+
CARGO_TARGET_AARCH64_APPLE_IOS_LINKER: "${{ github.workspace }}/data-plane/.cargo/clang-ios-linker-wrapper.sh"
479+
CARGO_TARGET_AARCH64_APPLE_IOS_SIM_LINKER: "${{ github.workspace }}/data-plane/.cargo/clang-ios-linker-wrapper.sh"
480+
run: |
481+
chmod +x "${{ github.workspace }}/data-plane/.cargo/clang-ios-linker-wrapper.sh"
482+
rm -f /tmp/linker-args.log
483+
_sim_sdk="$(xcrun --sdk iphonesimulator --show-sdk-path)"
484+
BINDGEN_EXTRA_CLANG_ARGS="-isysroot ${_sim_sdk} -target arm64-apple-ios15.0-simulator"
485+
export BINDGEN_EXTRA_CLANG_ARGS
486+
task adapter:bindings:build:all TARGET=aarch64-apple-ios-sim PROFILE=release
487+
_ios_sdk="$(xcrun --sdk iphoneos --show-sdk-path)"
488+
BINDGEN_EXTRA_CLANG_ARGS="-isysroot ${_ios_sdk} -target arm64-apple-ios15.0"
489+
export BINDGEN_EXTRA_CLANG_ARGS
490+
task adapter:bindings:build:all TARGET=aarch64-apple-ios PROFILE=release
491+
492+
- name: Vendor iOS libs and create XCFramework
493+
working-directory: ./data-plane/bindings/react-native
494+
run: |
495+
task vendor:ios
496+
task xcframework:ios
497+
498+
- name: Generate bindings
499+
working-directory: ./data-plane/bindings/react-native
500+
env:
501+
CARGO_TARGET_AARCH64_APPLE_IOS_SIM_LINKER: "${{ github.workspace }}/data-plane/.cargo/clang-ios-linker-wrapper.sh"
502+
IPHONEOS_DEPLOYMENT_TARGET: "13.4"
503+
run: |
504+
_sim_sdk="$(xcrun --sdk iphonesimulator --show-sdk-path)"
505+
BINDGEN_EXTRA_CLANG_ARGS="-isysroot ${_sim_sdk} -target arm64-apple-ios15.0-simulator"
506+
export BINDGEN_EXTRA_CLANG_ARGS
507+
task generate TARGET=aarch64-apple-ios-sim
508+
509+
- name: Set version in package.json
510+
working-directory: ./data-plane/bindings/react-native
511+
env:
512+
BINDINGS_VERSION: ${{ steps.version.outputs.version }}
513+
run: npm pkg set version="${BINDINGS_VERSION}"
514+
515+
- name: Configure npm auth
516+
working-directory: ./data-plane/bindings/react-native
517+
run: echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc
518+
env:
519+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
520+
521+
- name: Publish to npm
522+
working-directory: ./data-plane/bindings/react-native
523+
run: npm publish --access public
524+
env:
525+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
526+
527+
# ==========================================================================
528+
# Job 6b: Release Kotlin bindings to GitHub Packages
190529
# ==========================================================================
191530
release-kotlin-bindings:
192531
name: "Release Kotlin Bindings"

0 commit comments

Comments
 (0)