Skip to content

UniFFI: Publish Swift packages#1078

Merged
pblazej merged 8 commits into
mainfrom
blaze/publish-xcframework
May 14, 2026
Merged

UniFFI: Publish Swift packages#1078
pblazej merged 8 commits into
mainfrom
blaze/publish-xcframework

Conversation

@pblazej
Copy link
Copy Markdown
Contributor

@pblazej pblazej commented May 11, 2026

- Add uniffi-packages.yml mirroring ffi-builds.yml's draft-release lookup
  pattern; matrix-keyed on `package` (swift today, kotlin/python later)
- Move podspec generation into the Makefile via tera template at
  support/swift/LiveKitUniFFI.podspec.tera; rendered alongside Package.swift
- Add swift-zip-xcframework task (release profile only) that zips the
  xcframework and stashes the checksum; swift-generate-manifest now derives
  SPM_URL/SPM_CHECKSUM internally so callers only set SPM_VERSION
- After `cargo make --profile release swift-package`, the output dir is
  publish-ready: Package.swift, Package@swift-6.2.swift, podspec, LICENSE,
  zipped xcframework, and Sources/<name>/livekit_uniffi.swift

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pblazej pblazej marked this pull request as ready for review May 11, 2026 10:16
@pblazej pblazej requested review from 1egoman and ladvoc May 11, 2026 10:16
Comment thread .github/workflows/uniffi-packages.yml Outdated
with:
submodules: recursive

- uses: maxim-lobanov/setup-xcode@v1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Just FYI, before merging this, you should be sure to pin all third party action uses to specific hashes to prevent some flavors of supply chain attacks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, I think it should be applied elsewhere (sdk et al)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most livekit repos (at least in the web sphere) are doing this already, but yes if there are repos which are not pinning actions, definitely update those!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: a37c961. Also pinned livekit/publish-xcframework-action to the fix commit from livekit/publish-xcframework-action#3 — will repin to the main-merged SHA once that lands.

Comment on lines +19 to +22
tag_name:
description: "Release tag (e.g., livekit-uniffi/v0.0.7). Required if no draft release exists."
required: false
type: string
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: I'm a bit confused why this is set up to work with draft releases - would it be better to use a similar kick off mechanism as the release.yml and tie into knope PR merges somehow?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same pattern as ffi-builds.yml — knope creates the draft on the release-PR merge, this workflow watches main pushes and picks it up. wiring it into release.yml directly would mean baking swift-specific build/publish logic into the release orchestrator, which feels out of place.

Comment thread .github/workflows/uniffi-packages.yml Outdated
Comment on lines +68 to +73
include:
- package: swift
runner: macos-26
hosting-repo: livekit/livekit-uniffi-xcframework
# NOTE: spm-name must match SPM_NAME in livekit-uniffi/Makefile.toml.
spm-name: LiveKitUniFFI
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: Realistically, I'm not sure that it's worth trying to parameterize this job for all platforms. In the ai-coustics plugin project, I found it worked a lot better to treat each platform as its own independent pipeline which handles its own builds / packaging concerns / etc. So I think my vote would be to rename this swift-build and get rid of the matrix here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looked into it: GH Actions can't pick uses: based on matrix.* dynamically, so "separate workflow + matrix" collapses to N hardcoded uses: jobs (basically your suggestion). matrix-of-one stays simpler for now; if kotlin/python end up with very divergent steps we revisit and split.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reconsidered — extracted to a reusable workflow (uniffi-swift.yml) called from a thin parent that handles tag resolution. No matrix; each future lang would be a hardcoded uses: job. Done: ac8941a

Comment thread .github/workflows/uniffi-packages.yml Outdated
# knope has produced a draft release for the livekit-uniffi package; if so the
# matching package job runs. Manual runs go through workflow_dispatch.
#
# NOTE: livekit-uniffi must be added to knope.toml with `assets = "marker"`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: I don't see that added here. Did you want to add in a separate PR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: 753b26d

Comment thread .github/workflows/uniffi-packages.yml Outdated
matrix:
include:
- package: swift
runner: macos-26
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: How about using a large runner here to speed things up (e.g. macos-26-large)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-large is x86, -xlarge is arm (and paid), I don't have any exact numbers yet, may be worth trying.

Comment thread .github/workflows/uniffi-packages.yml Outdated
aarch64-apple-tvos \
aarch64-apple-tvos-sim

- name: Install nightly + rust-src (visionOS tier-3 target)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: visionOS has been upgrade to tier II now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: a37c961

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction: tvOS is still tier-3 and cargo-swift falls back to nightly+-Zbuild-std for any tier-3 arch, so I dropped tier-3 entries from the stable rustup target add list and put the nightly + rust-src install back. Verified end-to-end locally. Done: 6ff5f79

Comment thread .github/workflows/uniffi-packages.yml Outdated
- uses: cargo-bins/cargo-binstall@v1
- run: cargo binstall cargo-make --no-confirm

- name: Install Protoc
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Did you get an error without protoc installed? It shouldn't be needed here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you were right, no error without protoc. Done: a37c961

Comment thread .github/workflows/uniffi-packages.yml Outdated
xcframework-zip: ${{ env.OUTPUT_DIR }}/Rust${{ matrix.spm-name }}.xcframework.zip
version: ${{ needs.resolve-tag.outputs.version }}
hosting-repo: ${{ matrix.hosting-repo }}
files: |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Does this fail if any of the specified files are missing? To avoid similar incomplete release issues to what we've seen with libwebrtc in this repo, it probably should.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in livekit/publish-xcframework-action#3 — explicit test -f per source file + set -euo pipefail, no more silent partials. workflow pinned to that commit. Done: a37c961

@pblazej
Copy link
Copy Markdown
Contributor Author

pblazej commented May 13, 2026

Thanks for constructive fb, I'll revisit that in the meantime.

@ladvoc are we still fine with creating some "draft" releases of the crate for e2e test?

pblazej added 2 commits May 14, 2026 11:25
Adds a [packages.livekit-uniffi] entry so a normal knope release PR
merge produces a draft release tagged 'livekit-uniffi/v<X.Y.Z>'.
uniffi-packages.yml picks that draft up on the post-merge push to main
and runs the Swift publish job.
- Remove nightly + rust-src install: visionOS is rustc Tier 2 now, no
  need for -Zbuild-std anymore. Add the visionos targets to the stable
  rustup target list instead.
- Remove arduino/setup-protoc: the uniffi build doesn't invoke protoc.
- Pin all third-party actions to immutable commit SHAs (incl.
  livekit/publish-xcframework-action at the fix commit from PR #3 in
  that repo). Repin to the main-merged SHA after PR #3 lands.

Addresses #1078 comments on lines 84, 106, 115.
@github-actions
Copy link
Copy Markdown
Contributor

No changeset found

This PR modifies the following packages but doesn't include a changeset:

Directly changed:

  • livekit-uniffi

Click here to create a changeset

The link pre-populates a changeset file with patch bumps for all affected packages.
Edit the description and bump types as needed before committing.

If this change doesn't require a version bump, add the internal label to this PR.

Splits the per-language pipeline out of uniffi-packages.yml: the parent
keeps the trigger + tag-resolution and delegates to uniffi-swift.yml
via workflow_call. Each language wrapper gets its own focused file
(kotlin/python will slot in as new reusable workflows + new jobs in
the parent) without conditional 'if: matrix.lang == …' gates.

Note: GH Actions can't pick 'uses:' by matrix expression, so each
language is a hardcoded job in the parent rather than a matrix entry.

Addresses #1078 comment on uniffi-packages.yml:73.
Comment thread .github/workflows/uniffi-packages.yml Fixed
pblazej added a commit to livekit/publish-xcframework-action that referenced this pull request May 14, 2026
Previous behavior used 'echo | while' which put the loop body in a
subshell — a cp failure there could be swallowed by the pipe's exit
semantics, producing a partial release. Switch to a heredoc-fed loop
in the parent shell, add 'set -euo pipefail', and check each source
file exists before copy so a typo or missing artifact fails the step
loudly instead of half-publishing.

Reported on livekit/rust-sdks#1078.
pblazej and others added 4 commits May 14, 2026 11:37
…ntain permissions'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
cargo-make's `[tasks.X.env]` block overrides caller env unless gated
with a `condition`. Without the guard, SPM_VERSION=0.0.0-test from
the environment was being clobbered by the makefile's 0.0.0-dev
default during `cargo make swift-package`. Mark both SPM_VERSION and
SPM_HOSTING_REPO with `env_not_set` so they only apply when the
caller hasn't set the variable.
ladvoc's comment that visionOS reached tier-2 is accurate, but tvOS
remains tier-3 — and cargo-swift's fork falls back to
`cargo +nightly -Zbuild-std` for any tier-3 arch in the build. Drop
the tier-3 entries from the stable `rustup target add` list (they
error on stable) and put the nightly + rust-src install back so the
build doesn't fail on the tvOS slice.

Verified locally: `SPM_VERSION=0.0.0-test cargo make --profile release
swift-package` succeeds end-to-end (incl. xros-arm64 + tvos-arm64
slices in the produced xcframework).
@pblazej pblazej merged commit 186a122 into main May 14, 2026
22 of 23 checks passed
@pblazej pblazej deleted the blaze/publish-xcframework branch May 14, 2026 10:55
pblazej added a commit that referenced this pull request May 14, 2026
The CodeQL autofix landed in #1078 added `permissions: contents: read`
at the top level of uniffi-packages.yml, which then forbids any
nested job (including the called workflow uniffi-swift.yml) from
requesting higher permissions — workflow validation fails with:

  Error calling workflow ... The nested job 'build-and-publish' is
  requesting 'contents: write', but is only allowed 'contents: read'.

Neither job actually needs write: `gh release list` in resolve-tag is
read-only, and the publish step authenticates to the hosting repo
with UNIFFI_XCFRAMEWORK_PAT (not GITHUB_TOKEN). Drop the elevation
on both so the workflow can start.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants