diff --git a/client-sdk-rust b/client-sdk-rust index 1a477bc4..2d9f01ab 160000 --- a/client-sdk-rust +++ b/client-sdk-rust @@ -1 +1 @@ -Subproject commit 1a477bc422c6890537b3bcdb017f0ac094d49661 +Subproject commit 2d9f01ab1e933a86a8a5c53805ee29ee58b9be1b diff --git a/docs/tools.md b/docs/tools.md index 1961742a..a4176b0f 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -140,23 +140,48 @@ For details on the Doxygen configuration and CI pipeline, see the ### Bump the pinned Rust submodule +Update to the commit from the most recent published Rust SDK release: + ```bash -cd client-sdk-cpp -git fetch origin -git switch -c try-rust-main origin/main +./scripts/update-rust-sdk.sh +``` + +The script requires the GitHub CLI (`gh`). To select a specific commit, pass +its full or abbreviated hash: -# Sync submodule URLs and check out what origin/main pins (recursively): -git submodule sync --recursive -git submodule update --init --recursive --checkout +```bash +./scripts/update-rust-sdk.sh --hash 1a477bc +``` -# If the nested submodule under yuv-sys didn't materialize, force it: -git -C client-sdk-rust/yuv-sys submodule sync --recursive -git -C client-sdk-rust/yuv-sys submodule update --init --recursive --checkout +The script updates the `client-sdk-rust` gitlink and synchronizes its nested +submodules. It stops without changing the checkout if the Rust submodule has +tracked changes. -# Sanity check: +Review the selected commits before committing the gitlink update: + +```bash git submodule status --recursive ``` +### Bump the pinned C++ example collection + +Update to the most recent commit on the `main` branch of the examples +repository: + +```bash +./scripts/update-cpp-example-collection.sh +``` + +To select a specific commit, pass its full or abbreviated hash: + +```bash +./scripts/update-cpp-example-collection.sh --hash 7e76bea +``` + +The script updates the `cpp-example-collection` gitlink and synchronizes its +nested submodules. It stops without changing the checkout if the examples +submodule has tracked changes. + ### If `yuv-sys` fails to build ```bash diff --git a/scripts/update-cpp-example-collection.sh b/scripts/update-cpp-example-collection.sh new file mode 100755 index 00000000..a3c231df --- /dev/null +++ b/scripts/update-cpp-example-collection.sh @@ -0,0 +1,148 @@ +#!/usr/bin/env bash +# +# Copyright 2026 LiveKit +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +repo_root="$(cd "${script_dir}/.." && pwd -P)" +examples_dir="${repo_root}/cpp-example-collection" +examples_repo="livekit-examples/cpp-example-collection" +examples_remote="https://github.com/${examples_repo}.git" +default_branch="main" + +usage() { + cat <<'EOF' +Usage: ./scripts/update-cpp-example-collection.sh [--hash HASH] + +Update the cpp-example-collection submodule used by the C++ SDK. + +Options: + --hash HASH + Use the specified examples commit. You can use a short or full SHA-1 + hash. + -h, --help + Show this help and exit. + +When --hash is omitted, the script uses the most recent commit on the main +branch of livekit-examples/cpp-example-collection. +EOF +} + +requested_hash="" +hash_provided=false + +while (($#)); do + case "$1" in + --hash) + shift + if (($# == 0)); then + echo "ERROR: --hash requires a value" >&2 + exit 2 + fi + requested_hash="$1" + hash_provided=true + shift + ;; + --hash=*) + requested_hash="${1#--hash=}" + hash_provided=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "ERROR: unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +if [[ "$hash_provided" == true && ! "$requested_hash" =~ ^[0-9a-fA-F]{7,40}$ ]]; then + echo "ERROR: --hash must be a 7- to 40-character hexadecimal Git SHA-1 hash" >&2 + exit 2 +fi + +if ! command -v git >/dev/null 2>&1; then + echo "ERROR: git not found in PATH" >&2 + exit 1 +fi + +if ! git -C "$repo_root" rev-parse --show-toplevel >/dev/null 2>&1; then + echo "ERROR: ${repo_root} is not a Git worktree" >&2 + exit 1 +fi + +if [[ ! -e "${examples_dir}/.git" ]]; then + echo "==> Initializing cpp-example-collection" + git -C "$repo_root" submodule update --init cpp-example-collection +fi + +if ! git -C "$examples_dir" diff --quiet || + ! git -C "$examples_dir" diff --cached --quiet; then + echo "ERROR: cpp-example-collection has tracked changes; commit or stash them first" >&2 + exit 1 +fi + +fetch_ref="$requested_hash" + +if [[ "$hash_provided" == false ]]; then + echo "==> Finding the most recent cpp-example-collection commit" + branch_ref="refs/heads/${default_branch}" + remote_ref="$(git ls-remote "$examples_remote" "$branch_ref")" + read -r requested_hash resolved_ref <<<"$remote_ref" + if [[ -z "$requested_hash" || "$resolved_ref" != "$branch_ref" ]]; then + echo "ERROR: branch '${default_branch}' was not found in ${examples_repo}" >&2 + exit 1 + fi + fetch_ref="$branch_ref" + echo "==> Latest ${default_branch} commit: ${requested_hash}" +else + requested_hash="$(printf '%s' "$requested_hash" | tr '[:upper:]' '[:lower:]')" + echo "==> Requested examples commit: ${requested_hash}" +fi + +echo "==> Fetching cpp-example-collection" +if [[ "$hash_provided" == false ]]; then + git -C "$examples_dir" fetch --quiet origin "$fetch_ref" +elif [[ ${#requested_hash} -eq 40 ]]; then + if ! git -C "$examples_dir" fetch --quiet origin "$fetch_ref"; then + git -C "$examples_dir" fetch --quiet origin + fi +else + git -C "$examples_dir" fetch --quiet origin +fi + +if ! resolved_hash="$(git -C "$examples_dir" rev-parse --verify "${requested_hash}^{commit}" 2>/dev/null)"; then + echo "ERROR: '${requested_hash}' does not resolve to a cpp-example-collection commit" >&2 + exit 1 +fi + +current_hash="$(git -C "$examples_dir" rev-parse HEAD)" +if [[ "$current_hash" == "$resolved_hash" ]]; then + echo "==> cpp-example-collection is already at ${resolved_hash}" +else + git -C "$examples_dir" checkout --quiet --detach "$resolved_hash" + echo "==> Updated cpp-example-collection: ${current_hash} -> ${resolved_hash}" +fi + +echo "==> Synchronizing nested example submodules" +git -C "$examples_dir" submodule sync --recursive +git -C "$examples_dir" submodule update --init --recursive + +echo "==> Done. Review and commit the cpp-example-collection gitlink change." diff --git a/scripts/update-rust-sdk.sh b/scripts/update-rust-sdk.sh new file mode 100755 index 00000000..de520376 --- /dev/null +++ b/scripts/update-rust-sdk.sh @@ -0,0 +1,174 @@ +#!/usr/bin/env bash +# +# Copyright 2026 LiveKit +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +repo_root="$(cd "${script_dir}/.." && pwd -P)" +rust_dir="${repo_root}/client-sdk-rust" +rust_repo="livekit/client-sdk-rust" +rust_remote="https://github.com/${rust_repo}.git" + +usage() { + cat <<'EOF' +Usage: ./scripts/update-rust-sdk.sh [--hash HASH] + +Update the client-sdk-rust submodule used by the C++ SDK. + +Options: + --hash HASH + Use the specified Rust SDK commit. You can use a short or full SHA-1 + hash. + -h, --help + Show this help and exit. + +When --hash is omitted, the script uses the commit tagged by the most recent +published, non-draft GitHub release in livekit/client-sdk-rust. +EOF +} + +requested_hash="" +hash_provided=false + +while (($#)); do + case "$1" in + --hash) + shift + if (($# == 0)); then + echo "ERROR: --hash requires a value" >&2 + exit 2 + fi + requested_hash="$1" + hash_provided=true + shift + ;; + --hash=*) + requested_hash="${1#--hash=}" + hash_provided=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "ERROR: unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +if [[ "$hash_provided" == true && ! "$requested_hash" =~ ^[0-9a-fA-F]{7,40}$ ]]; then + echo "ERROR: --hash must be a 7- to 40-character hexadecimal Git SHA-1 hash" >&2 + exit 2 +fi + +if ! command -v git >/dev/null 2>&1; then + echo "ERROR: git not found in PATH" >&2 + exit 1 +fi + +if ! git -C "$repo_root" rev-parse --show-toplevel >/dev/null 2>&1; then + echo "ERROR: ${repo_root} is not a Git worktree" >&2 + exit 1 +fi + +if [[ ! -e "${rust_dir}/.git" ]]; then + echo "==> Initializing client-sdk-rust" + git -C "$repo_root" submodule update --init client-sdk-rust +fi + +if ! git -C "$rust_dir" diff --quiet || + ! git -C "$rust_dir" diff --cached --quiet; then + echo "ERROR: client-sdk-rust has tracked changes; commit or stash them first" >&2 + exit 1 +fi + +fetch_ref="$requested_hash" +release_tag="" + +if [[ "$hash_provided" == false ]]; then + if ! command -v gh >/dev/null 2>&1; then + echo "ERROR: gh not found in PATH; install GitHub CLI or provide --hash" >&2 + exit 1 + fi + + echo "==> Finding the most recent published Rust SDK release" + release_tags="$( + gh api --paginate "repos/${rust_repo}/releases?per_page=100" \ + --jq '.[] | select(.draft == false) | .tag_name' + )" + release_tag="${release_tags%%$'\n'*}" + if [[ -z "$release_tag" ]]; then + echo "ERROR: no published release found for ${rust_repo}" >&2 + exit 1 + fi + + tag_refs="$( + git ls-remote "$rust_remote" \ + "refs/tags/${release_tag}" "refs/tags/${release_tag}^{}" + )" + while read -r tag_hash tag_ref; do + if [[ "$tag_ref" == "refs/tags/${release_tag}^{}" ]]; then + requested_hash="$tag_hash" + break + fi + if [[ "$tag_ref" == "refs/tags/${release_tag}" ]]; then + requested_hash="$tag_hash" + fi + done <<<"$tag_refs" + + if [[ -z "$requested_hash" ]]; then + echo "ERROR: release tag '${release_tag}' was not found in ${rust_repo}" >&2 + exit 1 + fi + fetch_ref="refs/tags/${release_tag}" + echo "==> Latest release: ${release_tag} (${requested_hash})" +else + requested_hash="$(printf '%s' "$requested_hash" | tr '[:upper:]' '[:lower:]')" + echo "==> Requested Rust SDK commit: ${requested_hash}" +fi + +echo "==> Fetching client-sdk-rust" +if [[ "$hash_provided" == false ]]; then + git -C "$rust_dir" fetch --quiet origin "$fetch_ref" +elif [[ ${#requested_hash} -eq 40 ]]; then + if ! git -C "$rust_dir" fetch --quiet origin "$fetch_ref"; then + git -C "$rust_dir" fetch --quiet origin + fi +else + git -C "$rust_dir" fetch --quiet origin +fi + +if ! resolved_hash="$(git -C "$rust_dir" rev-parse --verify "${requested_hash}^{commit}" 2>/dev/null)"; then + echo "ERROR: '${requested_hash}' does not resolve to a client-sdk-rust commit" >&2 + exit 1 +fi + +current_hash="$(git -C "$rust_dir" rev-parse HEAD)" +if [[ "$current_hash" == "$resolved_hash" ]]; then + echo "==> client-sdk-rust is already at ${resolved_hash}" +else + git -C "$rust_dir" checkout --quiet --detach "$resolved_hash" + echo "==> Updated client-sdk-rust: ${current_hash} -> ${resolved_hash}" +fi + +echo "==> Synchronizing nested Rust SDK submodules" +git -C "$rust_dir" submodule sync --recursive +git -C "$rust_dir" submodule update --init --recursive + +echo "==> Done. Review and commit the client-sdk-rust gitlink change."