Skip to content

Commit 6c3d19e

Browse files
committed
Merge remote-tracking branch 'origin/dev' into claude/thirsty-cannon-63c134
# Conflicts: # Cargo.lock # js/watch/src/audio/source.ts # js/watch/src/backend.ts # js/watch/src/element.ts # js/watch/src/sync.ts # js/watch/src/ui/components/buffer-control.ts # js/watch/src/video/source.ts # kt/moq/build.gradle.kts
2 parents 2b7a419 + cae75ac commit 6c3d19e

325 files changed

Lines changed: 19373 additions & 5414 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/scripts/release.sh

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# release.sh parse-version <prefix> — extract SemVer from GITHUB_REF given a tag prefix
66
# release.sh prev-tag <prefix> — find the tag immediately before the current one
77
# release.sh create <artifacts_dir> — create or update a GitHub release with artifacts
8+
# release.sh git-tag-exists <repo> <tag> — check whether a tag exists on a remote repo
89
# release.sh read-version <pyproject.toml> — read `version = "x.y.z"` from a manifest
910
# release.sh pypi-exists <dist> <version> — check whether <dist>==<version> is already on PyPI
1011
#
@@ -79,6 +80,32 @@ create_release() {
7980
fi
8081
}
8182

83+
# Check whether a bare-semver tag already exists on a remote repo. This is the
84+
# release gate for the independently-versioned Swift wrapper (like release-plz
85+
# checking the registry): the mirror's git tag is the source of truth, so a
86+
# version that's already published is a no-op. Writes exists=true|false to
87+
# $GITHUB_OUTPUT. A connection failure is fatal rather than silently
88+
# re-publishing.
89+
git_tag_exists() {
90+
local repo="$1"
91+
local tag="$2"
92+
local url="https://github.com/${repo}"
93+
94+
local out
95+
out=$(git ls-remote --tags "$url" "refs/tags/${tag}") || {
96+
echo "Failed to query tags on $url" >&2
97+
exit 1
98+
}
99+
100+
local exists
101+
if [[ -n "$out" ]]; then exists=true; else exists=false; fi
102+
103+
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
104+
echo "exists=${exists}" >>"$GITHUB_OUTPUT"
105+
fi
106+
echo "Tag ${repo}@${tag}: exists=${exists}"
107+
}
108+
82109
# Read the static `version = "x.y.z"` from the [project] table of a
83110
# pyproject.toml. Scoped to [project] so a `version` key in another table
84111
# (e.g. a [tool.*] section) can't be picked up by mistake. Writes
@@ -134,10 +161,11 @@ case "${1:-}" in
134161
parse-version) parse_version "$2" ;;
135162
prev-tag) prev_tag "$2" ;;
136163
create) create_release "$2" ;;
164+
git-tag-exists) git_tag_exists "$2" "$3" ;;
137165
read-version) read_version "$2" ;;
138166
pypi-exists) pypi_exists "$2" "$3" ;;
139167
*)
140-
echo "Usage: $0 {parse-version|prev-tag|create|read-version|pypi-exists} <args>" >&2
168+
echo "Usage: $0 {parse-version|prev-tag|create|git-tag-exists|read-version|pypi-exists} <args>" >&2
141169
exit 1
142170
;;
143171
esac

.github/workflows/release-brew.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ name: release-brew
1010
# download them.
1111
#
1212
# Authenticates as the moq-bot GitHub App. The APP_ID and APP_PRIVATE_KEY
13-
# repo secrets are already wired (see release-swift.yml). The minted
13+
# repo secrets are already wired (see release-swift-lib.yml). The minted
1414
# installation token is scoped to moq-dev/homebrew-tap and expires in 1
1515
# hour.
1616

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
name: Release Go FFI
2+
3+
# Publishes the raw moq-go-ffi bindings module (uniffi-bindgen-go output +
4+
# prebuilt native libs) to the moq-dev/moq-go-ffi mirror, lockstep with the
5+
# moq-ffi crate. The ergonomic moq-go wrapper is released separately
6+
# (release-go.yml), which also auto-bumps its require to each new ffi here.
7+
8+
on:
9+
push:
10+
tags:
11+
- "moq-ffi-v*"
12+
pull_request:
13+
paths:
14+
- ".github/workflows/release-go-ffi.yml"
15+
- ".github/scripts/release.sh"
16+
- "go/ffi/**"
17+
- "go/scripts/package-ffi.sh"
18+
- "go/scripts/publish-ffi.sh"
19+
- "rs/moq-ffi/build.sh"
20+
21+
permissions:
22+
contents: read
23+
24+
concurrency:
25+
group: release-go-ffi
26+
cancel-in-progress: false
27+
28+
env:
29+
UNIFFI_BINDGEN_GO_TAG: v0.7.1+v0.31.0
30+
31+
jobs:
32+
parse-version:
33+
name: Parse version
34+
runs-on: ubuntu-latest
35+
outputs:
36+
version: ${{ steps.parse.outputs.version }}
37+
38+
steps:
39+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
40+
with:
41+
persist-credentials: false
42+
43+
- name: Parse version
44+
id: parse
45+
env:
46+
EVENT_NAME: ${{ github.event_name }}
47+
run: |
48+
if [[ "$EVENT_NAME" == "pull_request" ]]; then
49+
CARGO_VERSION=$(grep '^version' rs/moq-ffi/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
50+
echo "version=$CARGO_VERSION" >> "$GITHUB_OUTPUT"
51+
echo "Using version from Cargo.toml (PR dry-run): $CARGO_VERSION"
52+
else
53+
.github/scripts/release.sh parse-version moq-ffi
54+
fi
55+
56+
build:
57+
name: Build moq-ffi (${{ matrix.target }})
58+
needs: [parse-version]
59+
runs-on: ${{ matrix.os }}
60+
61+
strategy:
62+
fail-fast: false
63+
matrix:
64+
include:
65+
- target: x86_64-unknown-linux-gnu
66+
os: ubuntu-latest
67+
- target: aarch64-unknown-linux-gnu
68+
os: ubuntu-latest
69+
- target: x86_64-apple-darwin
70+
# macos-latest is arm64; the Intel target needs an Intel runner or
71+
# the .a is mis-built for the wrong arch.
72+
os: macos-15-intel
73+
- target: aarch64-apple-darwin
74+
os: macos-latest
75+
- target: x86_64-pc-windows-msvc
76+
os: windows-latest
77+
78+
steps:
79+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
80+
with:
81+
persist-credentials: false
82+
83+
- name: Install Rust
84+
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
85+
with:
86+
targets: ${{ matrix.target }}
87+
88+
- name: Rust cache
89+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
90+
with:
91+
# Don't let untrusted PR builds populate caches reused by trusted runs.
92+
save-if: ${{ github.event_name != 'pull_request' }}
93+
94+
- name: Install cross-compilation tools (Linux ARM64)
95+
if: matrix.target == 'aarch64-unknown-linux-gnu'
96+
run: |
97+
sudo apt-get update
98+
sudo apt-get install -y gcc-aarch64-linux-gnu
99+
100+
- name: Build
101+
shell: bash
102+
env:
103+
BUILD_TARGET: ${{ matrix.target }}
104+
BUILD_VERSION: ${{ needs.parse-version.outputs.version }}
105+
run: |
106+
./rs/moq-ffi/build.sh \
107+
--target "$BUILD_TARGET" \
108+
--version "$BUILD_VERSION" \
109+
--output dist
110+
111+
- name: Upload lib
112+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
113+
with:
114+
name: go-lib-${{ matrix.target }}
115+
# package.sh expects <target>/<libname>; upload just lib/ contents.
116+
path: dist/moq-ffi-${{ needs.parse-version.outputs.version }}-${{ matrix.target }}/lib/
117+
118+
bindings:
119+
name: Generate bindings
120+
needs: [parse-version]
121+
runs-on: ubuntu-latest
122+
123+
steps:
124+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
125+
with:
126+
persist-credentials: false
127+
128+
- name: Install Rust
129+
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
130+
131+
- name: Rust cache
132+
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
133+
with:
134+
# Don't let untrusted PR builds populate caches reused by trusted runs.
135+
save-if: ${{ github.event_name != 'pull_request' }}
136+
137+
- name: Install uniffi-bindgen-go
138+
run: |
139+
cargo install uniffi-bindgen-go \
140+
--git https://github.com/NordSecurity/uniffi-bindgen-go \
141+
--tag "$UNIFFI_BINDGEN_GO_TAG"
142+
143+
- name: Generate bindings
144+
env:
145+
BUILD_VERSION: ${{ needs.parse-version.outputs.version }}
146+
run: |
147+
./rs/moq-ffi/build.sh \
148+
--bindings-only \
149+
--version "$BUILD_VERSION" \
150+
--output dist
151+
152+
- name: Upload bindings
153+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
154+
with:
155+
name: go-bindings
156+
path: dist/bindings/go/
157+
158+
package:
159+
name: Package
160+
needs: [parse-version, build, bindings]
161+
runs-on: ubuntu-latest
162+
163+
steps:
164+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
165+
with:
166+
persist-credentials: false
167+
168+
- name: Download per-target libs
169+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
170+
with:
171+
path: libs-raw
172+
pattern: go-lib-*
173+
174+
- name: Flatten lib layout
175+
run: |
176+
mkdir -p libs
177+
for dir in libs-raw/go-lib-*; do
178+
target="${dir#libs-raw/go-lib-}"
179+
mv "$dir" "libs/$target"
180+
done
181+
ls -la libs
182+
183+
- name: Download bindings
184+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
185+
with:
186+
name: go-bindings
187+
path: bindings-raw
188+
189+
- name: Flatten bindings layout
190+
# uniffi-bindgen-go emits moq/{moq.go,moq.h} (some versions nest it
191+
# under uniffi/). package-ffi.sh expects bindings/moq/. Copy the whole
192+
# dir so the generated C header (moq.h, #include'd by moq.go's cgo
193+
# preamble) travels with it.
194+
run: |
195+
if [[ -d bindings-raw/uniffi/moq ]]; then
196+
cp -R bindings-raw/uniffi/moq bindings-moq
197+
elif [[ -d bindings-raw/moq ]]; then
198+
cp -R bindings-raw/moq bindings-moq
199+
else
200+
echo "Error: could not locate moq bindings dir under bindings-raw/" >&2
201+
find bindings-raw -type f
202+
exit 1
203+
fi
204+
mkdir -p bindings
205+
mv bindings-moq bindings/moq
206+
207+
- name: Package
208+
env:
209+
BUILD_VERSION: ${{ needs.parse-version.outputs.version }}
210+
run: |
211+
./go/scripts/package-ffi.sh \
212+
--version "$BUILD_VERSION" \
213+
--source-dir go/ffi \
214+
--lib-dir libs \
215+
--bindings-dir bindings \
216+
--output release-out
217+
218+
- name: Upload Go module
219+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
220+
with:
221+
name: go-package
222+
path: release-out/*
223+
224+
publish:
225+
name: Publish to Go module mirror
226+
needs: [package, parse-version]
227+
runs-on: ubuntu-latest
228+
if: github.event_name == 'push'
229+
230+
steps:
231+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
232+
with:
233+
persist-credentials: false
234+
235+
- name: Generate moq-bot token
236+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
237+
id: token
238+
with:
239+
app-id: ${{ secrets.APP_ID }}
240+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
241+
owner: moq-dev
242+
repositories: moq-go-ffi
243+
# Narrow the minted token to only what publish-ffi.sh needs.
244+
permission-contents: write
245+
246+
- name: Download package
247+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
248+
with:
249+
name: go-package
250+
path: go-out
251+
252+
- name: Publish to moq-dev/moq-go-ffi mirror
253+
env:
254+
BUILD_VERSION: ${{ needs.parse-version.outputs.version }}
255+
# Token is minted fresh per run, expires in 1 hour, never at rest.
256+
GO_FFI_MIRROR_TOKEN: ${{ steps.token.outputs.token }}
257+
GIT_AUTHOR_NAME: moq-bot
258+
GIT_AUTHOR_EMAIL: moq-bot[bot]@users.noreply.github.com
259+
run: ./go/scripts/publish-ffi.sh
260+
261+
publish-dry-run:
262+
name: Publish dry-run
263+
needs: [package, parse-version]
264+
runs-on: ubuntu-latest
265+
if: github.event_name == 'pull_request'
266+
267+
steps:
268+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
269+
with:
270+
persist-credentials: false
271+
272+
- name: Download package
273+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
274+
with:
275+
name: go-package
276+
path: go-out
277+
278+
- name: Dry-run publish to mirror
279+
env:
280+
BUILD_VERSION: ${{ needs.parse-version.outputs.version }}
281+
run: ./go/scripts/publish-ffi.sh --dry-run

0 commit comments

Comments
 (0)