Skip to content

Fix uniffi release: run from release.yml and publish the draft#1256

Open
pblazej wants to merge 1 commit into
mainfrom
blaze/fix-uniffi-trigger
Open

Fix uniffi release: run from release.yml and publish the draft#1256
pblazej wants to merge 1 commit into
mainfrom
blaze/fix-uniffi-trigger

Conversation

@pblazej

@pblazej pblazej commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Problem

The livekit-uniffi/v0.1.5 release never got a git tag and the uniffi publish jobs "didn't run" for the last release (4724cbb1, #1237). Same for v0.1.4 before it — both drafts are stranded, unpublished.

Two independent defects in uniffi-packages.yml:

  1. Trigger race. It ran on push: main, which fires the instant the knope/release PR merges — concurrently with knope creating the draft release. resolve-tag's gh release list ran ~5s after the draft was created (createdAt 22:30:10 vs query 22:30:15) but GitHub's release-list API hadn't propagated it yet, so it resolved <none> and all jobs were skipped (the run shows "success" because skipped jobs don't fail).

  2. No publish step. Even when it does find the draft, nothing flips it to published. A GitHub draft release doesn't create the git tag until it's published (gh release edit --draft=false). uniffi-packages.yml had no such step — only resolve-tag → swift / android / cdylib (which just upload). The sibling ffi-builds.yml (the other assets = "marker" package, livekit-ffi) has it; uniffi didn't.

Fix

Mirror the working ffi-builds.yml / node-builds.yml pattern:

  • Invoke from release.yml as a reusable workflow (workflow_call) on the knope/release merge, instead of push: main — the same reliable trigger node-builds.yml uses, so it no longer races the draft creation. A short retry on the draft lookup absorbs any residual list-API lag.
  • Add a finalize job that publishes the draft (gh release edit --draft=false) once swift/android/cdylib succeed. This is what cuts the livekit-uniffi/v* tag.

assets = "marker" in knope.toml is kept intentionally — the draft cleanly signals "livekit-uniffi was released this cycle" (so non-uniffi releases skip) and lets us publish only after the cdylibs are attached (no assetless-release window for the Dart build-hook download). workflow_dispatch is retained for manual re-runs.

Validated with actionlint (clean).

Note on the stranded v0.1.5

This fixes future releases. To publish the existing v0.1.5 draft now, run uniffi-packages.yml via workflow_dispatch with tag_name: livekit-uniffi/v0.1.5 (and clean up the stale v0.1.4 draft).

🤖 Generated with Claude Code

uniffi-packages.yml triggered on push:main, which fired the moment the
knope/release PR merged and raced knope's draft-release creation. resolve-tag's
gh release list ran before the draft was visible, resolved <none>, and skipped
every job — so the draft was never published and the livekit-uniffi/v* tag was
never cut (v0.1.4 and v0.1.5 were both stranded this way).

Two fixes, mirroring the working ffi-builds.yml / node-builds.yml pattern:

- Invoke uniffi-packages.yml as a reusable workflow from release.yml on the
  knope/release merge (workflow_call), instead of push:main. Same reliable
  trigger node-builds uses. Add a short retry to the draft lookup to absorb the
  release-list API's propagation lag.
- Add a finalize job that flips the draft to a published release
  (gh release edit --draft=false) once the swift/android/cdylib jobs succeed.
  Publishing the draft is what creates the git tag; this step was missing
  entirely (ffi-builds.yml has it, uniffi-packages.yml did not).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pblazej pblazej requested a review from ladvoc as a code owner July 15, 2026 07:54

@devin-ai-integration devin-ai-integration Bot left a comment

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.

Devin Review found 1 potential issue.

Open in Devin Review

Comment on lines +120 to +123
- name: Publish release
env:
GH_TOKEN: ${{ github.token }}
run: gh release edit "${{ needs.resolve-tag.outputs.tag_name }}" --repo "${{ github.repository }}" --draft=false

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.

🟨 Unsanitized expression interpolation in shell command allows script injection

The finalize job interpolates needs.resolve-tag.outputs.tag_name directly into a run shell script (uniffi-packages.yml:123). This value originates from inputs.tag_name (line 51) when triggered via workflow_dispatch. A repository collaborator could craft a malicious tag name containing shell metacharacters (e.g. $(malicious_cmd)) that would be executed. The same pattern exists at line 51 (MANUAL_TAG="${{ inputs.tag_name }}"). While exploitation requires repo write access (limiting severity), using ${{ }} in run blocks is a known GitHub Actions anti-pattern.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

permissions:
contents: write
steps:
- name: Publish release

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.

This is now a manual step for other packages, right?

@pblazej

pblazej commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

@ladvoc feel free to close it, there must be some more elegant solution to both this and normal ffi

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.

1 participant