diff --git a/.changeset/uniffi_dart_release_automation.md b/.changeset/uniffi_dart_release_automation.md new file mode 100644 index 000000000..f1f9d1e65 --- /dev/null +++ b/.changeset/uniffi_dart_release_automation.md @@ -0,0 +1,5 @@ +--- +livekit-uniffi: patch +--- + +Attach Dart/Flutter cdylib assets to releases and prepare livekit_uniffi for pub.dev publishing diff --git a/.github/actions/uniffi-deps/action.yml b/.github/actions/uniffi-deps/action.yml index 1dfc527de..1bb3d37ec 100644 --- a/.github/actions/uniffi-deps/action.yml +++ b/.github/actions/uniffi-deps/action.yml @@ -1,4 +1,5 @@ name: Install Common Deps for UniFFI Tasks +description: Installs the tooling shared by the UniFFI packaging workflows (cargo-make) runs: using: composite steps: diff --git a/.github/workflows/uniffi-cdylib.yml b/.github/workflows/uniffi-cdylib.yml index dc5c4ba08..f1cea9c24 100644 --- a/.github/workflows/uniffi-cdylib.yml +++ b/.github/workflows/uniffi-cdylib.yml @@ -5,8 +5,9 @@ name: UniFFI cdylib builds # `.sha256` sidecar). The Dart build hook (support/dart/hook/build.dart.tera) # downloads these at consumer build time. # -# Reusable workflow, invoked from uniffi-packages.yml once the release tag has -# been resolved. Mirrors the structure of ffi-builds.yml. Not triggered directly. +# Reusable workflow, invoked from uniffi-dart-publish.yml once the release tag +# has been resolved, so the Dart publish job can depend on the assets being +# attached. Mirrors the structure of ffi-builds.yml. Not triggered directly. on: workflow_call: @@ -53,9 +54,11 @@ jobs: - os: ubuntu-latest target: x86_64-unknown-linux-gnu platform: linux - - os: ubuntu-latest + build_image: quay.io/pypa/manylinux_2_28_x86_64 + - os: ubuntu-24.04-arm target: aarch64-unknown-linux-gnu platform: linux + build_image: quay.io/pypa/manylinux_2_28_aarch64 - os: windows-latest target: x86_64-pc-windows-msvc platform: windows @@ -75,9 +78,15 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: + # Build the tagged source, not the ref the workflow was dispatched + # from. A manual re-run for an older release would otherwise upload + # libraries built from main under that release's version. + ref: ${{ inputs.tag_name }} submodules: true - name: Setup Rust toolchain + # Linux builds run inside a container with their own toolchain. + if: ${{ matrix.platform != 'linux' }} uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1 with: target: ${{ matrix.target }} @@ -92,28 +101,45 @@ jobs: shell: bash run: cargo build --release --target ${{ matrix.target }} -p livekit-uniffi - # Linux: native build for x64; cross toolchain for aarch64. + # Linux: build inside a manylinux_2_28 container so the shared library + # links against glibc 2.28 and loads on the distributions the Dart package + # is used on (Debian 12, Ubuntu 22.04, Amazon Linux 2023 and newer). A + # native build on the runner would inherit its glibc 2.39 floor. Same + # approach as ffi-builds.yml. The arm64 entry runs on a native arm64 + # runner, so no cross toolchain is needed, and livekit-uniffi has no C + # dependencies, so the image's stock gcc is enough. The toolchain version + # comes from rust-toolchain.toml. - name: Build (Linux) if: ${{ matrix.platform == 'linux' }} + env: + TARGET: ${{ matrix.target }} + BUILD_IMAGE: ${{ matrix.build_image }} run: | - if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then - sudo apt-get update - sudo apt-get install -y gcc-aarch64-linux-gnu - export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc - # .cargo/config.toml forces -fuse-ld=lld for this target to link - # libwebrtc; livekit-uniffi doesn't use libwebrtc. A non-empty global - # RUSTFLAGS overrides that per-target config, selecting the GNU bfd - # linker the cross binutils provides. - export RUSTFLAGS="-C link-arg=-fuse-ld=bfd" - fi - cargo build --release --target ${{ matrix.target }} -p livekit-uniffi + docker run --rm -e TARGET -v "$PWD:/workspace" -w /workspace "$BUILD_IMAGE" bash -euo pipefail -c ' + curl --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain none + export PATH="/root/.cargo/bin:$PATH" + if [ "$TARGET" = "aarch64-unknown-linux-gnu" ]; then + # .cargo/config.toml forces -fuse-ld=lld for this target to link + # libwebrtc, which livekit-uniffi does not use. A non-empty global + # RUSTFLAGS overrides that per-target config, selecting the GNU + # bfd linker the image provides. + export RUSTFLAGS="-C link-arg=-fuse-ld=bfd" + fi + cargo build --release --target "$TARGET" -p livekit-uniffi + ' + # The container ran as root, so hand the outputs back to the runner user. + sudo chown -R "$USER:$USER" target + + # Android: build with cargo-ndk. Installed as a prebuilt binary; a + # source build costs 3-5 minutes per matrix job on the release path. + - name: Install cargo-ndk + if: ${{ matrix.platform == 'android' }} + uses: taiki-e/install-action@682e7d9e49c5e653d371fc6adbda67653461378a # v2.82.4 + with: { tool: cargo-ndk } - # Android: build with cargo-ndk. - name: Build (Android) if: ${{ matrix.platform == 'android' }} - run: | - cargo install cargo-ndk - cargo ndk --target ${{ matrix.target }} build --release -p livekit-uniffi + run: cargo ndk --target ${{ matrix.target }} build --release -p livekit-uniffi # macOS/Linux: zip + shasum are available. - name: Package artifact (Unix) @@ -167,6 +193,10 @@ jobs: path: cdylibs - name: Upload to release + # TAG_NAME is bound through env rather than template-expanded into the + # script: tag names may contain shell metacharacters (Actions script + # injection). GITHUB_REPOSITORY is provided by the runner already. env: GH_TOKEN: ${{ github.token }} - run: gh release upload "${{ inputs.tag_name }}" cdylibs/* --repo "${{ github.repository }}" --clobber + TAG_NAME: ${{ inputs.tag_name }} + run: gh release upload "$TAG_NAME" cdylibs/* --repo "$GITHUB_REPOSITORY" --clobber diff --git a/.github/workflows/uniffi-dart-publish.yml b/.github/workflows/uniffi-dart-publish.yml new file mode 100644 index 000000000..7bd09347d --- /dev/null +++ b/.github/workflows/uniffi-dart-publish.yml @@ -0,0 +1,201 @@ +name: UniFFI Dart package + +# Publishes the generated livekit_uniffi Dart package to pub.dev on a +# livekit-uniffi release, together with the native libraries it loads. +# +# This is a separate workflow from uniffi-packages.yml because pub.dev's +# automated publishing only accepts workflows triggered by a tag push matching +# the tag pattern configured on the package (livekit-uniffi/v{{version}}); +# a release-event-triggered workflow is rejected. knope-bot creates the tag via +# the API, and App-created events do trigger workflows here (see the note in +# uniffi-packages.yml / #1256). +# +# The package's hook/build.dart downloads build-.zip assets from the +# GitHub release at consumer build time, so a pub.dev version whose assets are +# missing would be broken on arrival, and pub.dev versions cannot be +# unpublished. The cdylib job below builds and attaches those assets in this +# same run, and the publish job depends on it, so the package can only be +# published once every asset is on the release. +# +# PUBLISHING IS NOT ENABLED YET. Until the steps below are done, every run +# stops after `dart pub publish --dry-run`. The first live tag confirms that +# knope-bot's API-created tag fires this push trigger at all (expected for App +# events, never exercised here; workflow_dispatch is the fallback). +# Enablement steps: +# 1. A first manual `dart pub publish` by a livekit.io publisher admin has +# created the package on pub.dev (pub.dev only automates existing packages). +# 2. Automated publishing from GitHub Actions is enabled in the package's +# pub.dev admin settings for livekit/rust-sdks with tag pattern +# `livekit-uniffi/v{{version}}`, and PUBLISH_ENABLED below is flipped. +# +# Recovery: if a run fails, fix the cause and re-run the failed jobs, or +# dispatch this workflow with the tag. A dispatch rebuilds and re-attaches the +# assets (with --clobber) and re-validates the package, but never publishes, +# since pub.dev rejects OIDC tokens from dispatch runs. Set dry_run to skip the +# asset upload when only exercising the workflow. + +on: + push: + tags: ["livekit-uniffi/v*"] + workflow_dispatch: + inputs: + tag_name: + description: "Release tag (e.g. livekit-uniffi/v0.1.9)" + required: true + type: string + dry_run: + description: "Build everything but skip the release asset upload." + type: boolean + default: false + +env: + # Flip to "true" once the enablement steps in the header are done. Real + # publishing additionally requires a tag-push trigger; workflow_dispatch + # runs always stop at the dry run (pub.dev rejects their OIDC tokens). + PUBLISH_ENABLED: "false" + +permissions: + contents: read + +jobs: + resolve-tag: + runs-on: ubuntu-latest + outputs: + tag_name: ${{ steps.tag.outputs.tag_name }} + version: ${{ steps.tag.outputs.version }} + steps: + - name: Resolve tag + id: tag + # Bound through env, never template-expanded into the script: tag names + # and dispatch inputs may contain shell metacharacters (Actions script + # injection), and the outputs feed jobs that write release assets and + # can mint the pub.dev publish token. + env: + PUSHED_TAG: ${{ github.ref_name }} + INPUT_TAG: ${{ inputs.tag_name }} + run: | + TAG="${INPUT_TAG:-$PUSHED_TAG}" + case "$TAG" in + livekit-uniffi/v*) ;; + *) echo "Unexpected tag: $TAG"; exit 1 ;; + esac + echo "tag_name=${TAG}" >> "$GITHUB_OUTPUT" + echo "version=${TAG#livekit-uniffi/v}" >> "$GITHUB_OUTPUT" + + # Fast fail on a mis-pointed tag before spending runner time on the + # cdylib matrix: the tag version must match the crate version the tag + # carries (it is also what the pubspec, and pub.dev's tag-pattern check, + # will see). Only the manifest is needed here. + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + ref: ${{ steps.tag.outputs.tag_name }} + sparse-checkout: livekit-uniffi/Cargo.toml + sparse-checkout-cone-mode: false + + - name: Check tag matches crate version + env: + VERSION: ${{ steps.tag.outputs.version }} + run: | + crate_version=$(grep -m1 '^version = ' livekit-uniffi/Cargo.toml | cut -d'"' -f2) + if [ "$crate_version" != "$VERSION" ]; then + echo "Tag version $VERSION does not match livekit-uniffi crate version $crate_version." >&2 + exit 1 + fi + + # Builds build-.zip (+ .sha256) for every target and attaches them to + # the release. Runs here rather than in uniffi-packages.yml so the publish + # job can depend on it directly instead of polling the release for assets. + cdylib: + needs: resolve-tag + permissions: + # The upload step attaches assets to the release with the workflow token. + contents: write + uses: ./.github/workflows/uniffi-cdylib.yml + with: + version: ${{ needs.resolve-tag.outputs.version }} + tag_name: ${{ needs.resolve-tag.outputs.tag_name }} + dry_run: ${{ inputs.dry_run || false }} + + build-and-publish: + name: Build & publish Dart package + needs: [resolve-tag, cdylib] + runs-on: ubuntu-latest + permissions: + contents: read + # Exchanged for a temporary pub.dev token by dart-lang/setup-dart. + id-token: write + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + # Build the tagged source, not the dispatch ref (which defaults to main). + ref: ${{ needs.resolve-tag.outputs.tag_name }} + submodules: true + + - name: Setup Rust toolchain + uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1 + with: + cache: false + rustflags: "" + + # Same keys as uniffi-dart-test.yml, so pushes to main keep them warm. + - name: Cache cargo registry + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-registry- + + - name: Cache cargo target + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: target/ + key: ${{ runner.os }}-cargo-target-dart-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo-target-dart- + + - name: Install Common Deps for UniFFI Tasks + uses: ./.github/actions/uniffi-deps + + - name: Setup Dart + uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2 + with: + # Pinned, and kept identical to uniffi-dart-test.yml, so PR CI + # validates the SDK the publish runs with. A floating channel could + # introduce a new lint that fails the dry run only on release day. + # Bump both together. + sdk: 3.13.1 + + - name: Build Dart package (release) + working-directory: livekit-uniffi + run: cargo make --profile release dart-package + + # pub builds the publish archive from git's file listing, and the + # generated packages/ tree is gitignored, so publishing from inside the + # work tree produces an empty archive. Stage a copy outside it. + # + # The guard is a backstop for the dart-clean task: a package that ships + # a local native library would shadow the hook's download mode for every + # consumer, and pub.dev versions cannot be unpublished. + - name: Stage package outside the work tree + run: | + rm -rf "$RUNNER_TEMP/livekit_uniffi" + cp -R livekit-uniffi/packages/dart "$RUNNER_TEMP/livekit_uniffi" + if find "$RUNNER_TEMP/livekit_uniffi" \( -name 'liblivekit_uniffi.*' -o -name 'livekit_uniffi.dll' \) | grep -q .; then + echo "Staged package contains a local native library; refusing to publish." >&2 + exit 1 + fi + + - name: Validate package + working-directory: ${{ runner.temp }}/livekit_uniffi + run: | + dart pub get + dart pub publish --dry-run + + - name: Publish to pub.dev + if: ${{ env.PUBLISH_ENABLED == 'true' && github.event_name == 'push' }} + working-directory: ${{ runner.temp }}/livekit_uniffi + run: dart pub publish --force diff --git a/.github/workflows/uniffi-dart-test.yml b/.github/workflows/uniffi-dart-test.yml index 1e694562b..84834c653 100644 --- a/.github/workflows/uniffi-dart-test.yml +++ b/.github/workflows/uniffi-dart-test.yml @@ -23,8 +23,6 @@ permissions: jobs: dart-test: - # TODO: Fix tests then re-enable. - if: false name: Dart package tests runs-on: ubuntu-latest steps: @@ -44,7 +42,11 @@ jobs: - name: Setup Dart uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260 # v1.7.2 with: - sdk: stable + # Pinned, and kept identical to uniffi-dart-publish.yml, so this job + # validates the SDK the publish will run with. A floating channel + # could introduce a new lint that fails the publish dry run only on + # release day. Bump both together. + sdk: 3.13.1 - name: Cache cargo registry uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 diff --git a/.github/workflows/uniffi-packages.yml b/.github/workflows/uniffi-packages.yml index 0ebab424c..862dd772e 100644 --- a/.github/workflows/uniffi-packages.yml +++ b/.github/workflows/uniffi-packages.yml @@ -9,8 +9,10 @@ name: UniFFI packages # release event, which fires only for genuine livekit-uniffi releases (the gate # is free). workflow_dispatch allows a manual re-run with an explicit tag. # -# The Dart/Flutter cdylib target is experimental and not published for now; add a -# `cdylib` job (uniffi-cdylib.yml) back when it ships. +# The Dart package, and the cdylib release assets its build hook downloads, are +# handled by uniffi-dart-publish.yml. That workflow is tag-push triggered, as +# pub.dev requires, and builds the assets itself so publishing can depend on +# them directly. on: release: @@ -40,8 +42,12 @@ jobs: version: ${{ steps.get-tag.outputs.version }} steps: - id: get-tag + # TAG is bound through env rather than template-expanded into the + # script: tag names may contain shell metacharacters (Actions script + # injection). + env: + TAG: ${{ github.event.release.tag_name || inputs.tag_name }} run: | - TAG="${{ github.event.release.tag_name || inputs.tag_name }}" echo "tag_name=${TAG}" >> "$GITHUB_OUTPUT" # Strip the "livekit-uniffi/v" prefix to get the package version (e.g. 0.1.6). echo "version=${TAG#livekit-uniffi/v}" >> "$GITHUB_OUTPUT" diff --git a/knope.toml b/knope.toml index 6bcd8edd9..3208e325a 100644 --- a/knope.toml +++ b/knope.toml @@ -157,8 +157,9 @@ versioned_files = [ changelog = "livekit-uniffi/CHANGELOG.md" # No `assets` marker: knope publishes the release + tag directly, and # uniffi-packages.yml reacts to the published release to build/publish the Swift -# and Android wrapper packages. (Re-add the marker if the release itself needs -# to host assets, e.g. the Dart/Flutter cdylibs.) +# and Android wrapper packages. The Dart/Flutter cdylibs are attached to the +# already-published release by its cdylib job (gh release upload --clobber), so +# the marker stays off; a draft-based flow stranded releases before (#1256). scopes = ["uniffi", "livekit-uniffi"] [packages.livekit-wakeword] diff --git a/livekit-uniffi/Makefile.toml b/livekit-uniffi/Makefile.toml index 2abd8c9a6..3a9d357dc 100644 --- a/livekit-uniffi/Makefile.toml +++ b/livekit-uniffi/Makefile.toml @@ -20,12 +20,20 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}" SPM_NAME = "LiveKitUniFFI" NPM_NAME = "@livekit/uniffi" DART_PACKAGE_NAME = "livekit_uniffi" +# Rendered into pubspec.yaml by dart-generate-manifest. Fail closed: every +# profile gets `publish_to: none` (dev packages embed a host dylib and must +# never reach pub.dev), and only an explicit release build clears it so +# `dart pub publish` accepts the package. +PUBSPEC_PUBLISH_TO = "none" # Per-release directory holding the cdylib archives published by # .github/workflows/uniffi-cdylib.yml. Downloaders append # `/v/build-.zip` (and a `.sha256` sidecar). CDYLIB_DOWNLOAD_BASE_URL = "https://github.com/livekit/rust-sdks/releases/download/livekit-uniffi" +[env.release] +PUBSPEC_PUBLISH_TO = "" + [config] skip_core_tasks = true @@ -689,14 +697,33 @@ exec cargo run --features dart-bindgen --bin uniffi-bindgen-dart -- \ """ # Assemble a consumable Dart package around the generated bindings: idiomatic -# lib/ layout, a pubspec, the Native Assets build hook, and (dev) the locally -# built dynamic library so a consumer can load it without a download step. +# lib/ layout, a pubspec, the Native Assets build hook, package metadata, and +# (dev only) the locally built dynamic library so a consumer can load it +# without a download step. Release builds omit the dylib, so consumers use the +# hook's download mode against the release assets. # # packages/dart/ # pubspec.yaml (from support/dart/pubspec.yaml.tera) # lib/livekit_uniffi.dart # hook/build.dart (from support/dart/hook/build.dart) -# liblivekit_uniffi. (dev: copied local build) +# LICENSE, README.md, CHANGELOG.md +# liblivekit_uniffi. (dev only: copied local build) +# +# Publishing note: pub builds its archive from git's file listing and this +# whole tree is gitignored, so `dart pub publish` must run from a copy of +# packages/dart placed outside the repository (uniffi-dart-publish.yml does +# this; do the same for a manual publish). + +# Start from a clean slate: leftovers from a previous build with a different +# profile would otherwise survive into this one. The dev-profile dylib is the +# dangerous case, a release package must never carry it (the build hook +# prefers a package-root library over download, on every platform). +[tasks.dart-clean] +private = true +script_runner = "@shell" +script = """ +rm -rf ${PACKAGES_DIR}/${LANG} +""" [tasks.dart-move-code-into-lib] private = true @@ -725,14 +752,31 @@ extend = "tera" args = ["--env-only", "-t", "${SUPPORT_DIR}/${LANG}/hook/build.dart.tera", "-o", "${PACKAGES_DIR}/${LANG}/hook/build.dart"] # Dev delivery: copy the locally built dylib into the package root, where the -# build hook resolves it. A release flow would replace this with a download. +# build hook resolves it. Development profile only. A published package must +# not contain the host dylib, its consumers get the right library per target +# from the hook's download mode instead. [tasks.dart-copy-lib] private = true +condition = { profiles = ["development"] } script_runner = "@shell" script = """ cp ${LIB_PATH} ${PACKAGES_DIR}/${LANG}/ """ +# Package metadata: pub.dev requires a LICENSE and scores README/CHANGELOG. +# The LICENSE comes from the repo root (same source as the Swift package), +# the changelog from the crate, and the README and analysis options from +# support/dart. +[tasks.dart-copy-meta] +private = true +script_runner = "@shell" +script = """ +cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/LICENSE ${PACKAGES_DIR}/${LANG}/ +cp ${SUPPORT_DIR}/${LANG}/README.md ${PACKAGES_DIR}/${LANG}/ +cp ${SUPPORT_DIR}/${LANG}/analysis_options.yaml ${PACKAGES_DIR}/${LANG}/ +cp CHANGELOG.md ${PACKAGES_DIR}/${LANG}/ +""" + [tasks.dart-copy-tests] private = true script_runner = "@shell" @@ -744,11 +788,13 @@ cp ${SUPPORT_DIR}/${LANG}/test/*.dart ${PACKAGES_DIR}/${LANG}/test/ [tasks.dart-package-flow] private = true dependencies = [ + "dart-clean", "bindgen-dart", "dart-move-code-into-lib", "dart-generate-manifest", "dart-copy-hook", "dart-copy-lib", + "dart-copy-meta", "dart-copy-tests" ] diff --git a/livekit-uniffi/support/dart/README.md b/livekit-uniffi/support/dart/README.md new file mode 100644 index 000000000..90fd7cb32 --- /dev/null +++ b/livekit-uniffi/support/dart/README.md @@ -0,0 +1,40 @@ +# livekit_uniffi + +Dart bindings for the LiveKit Rust SDK core, generated from the +[`livekit-uniffi`](https://github.com/livekit/rust-sdks/tree/main/livekit-uniffi) +crate with [UniFFI](https://mozilla.github.io/uniffi-rs/) and +[uniffi-dart](https://github.com/Uniffi-Dart/uniffi-dart). + +This is a low-level package. It is consumed by +[`livekit_client`](https://pub.dev/packages/livekit_client) and is not +intended to be used directly in applications. + +## How it works + +The bindings call into a prebuilt Rust dynamic library through Dart's +[Native Assets](https://dart.dev/tools/hooks). The package's `hook/build.dart` +resolves the library for your target platform at build time, downloading it +from the matching [`livekit-uniffi` release](https://github.com/livekit/rust-sdks/releases) +and verifying its SHA-256 checksum. No Rust toolchain is required to consume +this package. + +Requires Dart >= 3.10 (Flutter >= 3.38), where build hooks and code assets are +stable. There is no web support: guard usage behind a conditional import. + +## Supported platforms + +macOS (arm64, x64), iOS (device and simulator), Android (arm64, armv7, x64), +Linux (arm64, x64), and Windows (arm64, x64). + +## Development + +This package is generated; do not edit it directly. To build it from source: + +```sh +cd rust-sdks/livekit-uniffi +cargo make dart-package # generates packages/dart with a locally built library +``` + +See the [crate README](https://github.com/livekit/rust-sdks/tree/main/livekit-uniffi) +for details. Issues and pull requests go to +[livekit/rust-sdks](https://github.com/livekit/rust-sdks). diff --git a/livekit-uniffi/support/dart/analysis_options.yaml b/livekit-uniffi/support/dart/analysis_options.yaml new file mode 100644 index 000000000..03e3b5a1e --- /dev/null +++ b/livekit-uniffi/support/dart/analysis_options.yaml @@ -0,0 +1,10 @@ +# The package contents are generated by uniffi-dart, which emits imports, +# helpers, and locals that are not always used by the exported surface. +# Silence those lints so pub.dev validation stays clean; real analysis +# errors still fail. +analyzer: + errors: + unused_import: ignore + unnecessary_import: ignore + unused_element: ignore + unused_local_variable: ignore diff --git a/livekit-uniffi/support/dart/pubspec.yaml.tera b/livekit-uniffi/support/dart/pubspec.yaml.tera index bfd6a7ddb..443d7fea3 100644 --- a/livekit-uniffi/support/dart/pubspec.yaml.tera +++ b/livekit-uniffi/support/dart/pubspec.yaml.tera @@ -1,16 +1,30 @@ name: {{ DART_PACKAGE_NAME }} -description: Dart bindings for the LiveKit UniFFI interface. +description: Dart bindings for the LiveKit Rust SDK core, delivered as a prebuilt native library via Native Assets. version: {{ CARGO_MAKE_CRATE_VERSION }} -publish_to: none +repository: https://github.com/livekit/rust-sdks +issue_tracker: https://github.com/livekit/rust-sdks/issues +homepage: https://livekit.io/ +{#- Dev packages embed a host dylib and must never be published; release + packages omit publish_to so pub.dev accepts them. Fails closed: the base + [env] in Makefile.toml sets "none" for every profile and only + [env.release] clears it. #} +{%- if PUBSPEC_PUBLISH_TO %} +publish_to: {{ PUBSPEC_PUBLISH_TO }} +{%- endif %} environment: sdk: ">=3.10.0 <4.0.0" dependencies: ffi: ^2.1.0 - # Native Assets build-hook support. `any` tracks the SDK-bundled versions. - code_assets: any - hooks: any + # Native Assets build-hook support. pub.dev requires bounded constraints + # (`any` fails publish validation), but these must stay wide: the resolvable + # version is coupled to the consumer's Dart SDK via a shared `meta` pin + # (Flutter 3.44 back-solves to code_assets 1.0.0 / hooks 1.0.2, while a bare + # Dart 3.12 resolves 1.2.1 / 2.1.0). Carets here break `flutter pub get` + # for consumers on older stable channels. + code_assets: ">=1.0.0 <2.0.0" + hooks: ">=1.0.2 <3.0.0" # Used by hook/build.dart to download and verify prebuilt libraries. archive: ^4.0.0 crypto: ^3.0.0