Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions .github/update_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import pathlib
import re
import click
from packaging.version import Version

PACKAGES = {
"livekit": "livekit-rtc/livekit/rtc/version.py",
"livekit-api": "livekit-api/livekit/api/version.py",
"livekit-protocol": "livekit-protocol/livekit/protocol/version.py",
}


def _esc(*codes: int) -> str:
return "\033[" + ";".join(str(c) for c in codes) + "m"


def read_version(f: pathlib.Path) -> str:
text = f.read_text()
m = re.search(r'__version__\s*=\s*[\'"]([^\'"]+)[\'"]', text)
if not m:
raise ValueError(f"could not find __version__ in {f}")
return m.group(1)


def write_new_version(f: pathlib.Path, new_version: str) -> None:
text = f.read_text()
new_text = re.sub(
r'__version__\s*=\s*[\'"][^\'"]*[\'"]',
f'__version__ = "{new_version}"',
text,
count=1,
)
f.write_text(new_text)


def bump_version(cur: str, bump_type: str) -> str:
v = Version(cur)
if bump_type == "release":
return v.base_version
if bump_type == "patch":
return f"{v.major}.{v.minor}.{v.micro + 1}"
if bump_type == "minor":
return f"{v.major}.{v.minor + 1}.0"
if bump_type == "major":
return f"{v.major + 1}.0.0"
raise ValueError(f"unknown bump type: {bump_type}")


def bump_prerelease(cur: str, bump_type: str) -> str:
v = Version(cur)
base = v.base_version
if bump_type == "rc":
if v.pre and v.pre[0] == "rc":
next_rc = v.pre[1] + 1
else:
next_rc = 1
return f"{base}.rc{next_rc}"
raise ValueError(f"unknown prerelease bump type: {bump_type}")


def update_api_protocol_dependency(new_protocol_version: str) -> None:
"""Update livekit-api's dependency on livekit-protocol."""
pyproject = pathlib.Path("livekit-api/pyproject.toml")
if not pyproject.exists():
return
old_text = pyproject.read_text()
new_text = re.sub(
r'"livekit-protocol>=[\w.\-]+,',
f'"livekit-protocol>={new_protocol_version},',
old_text,
Comment on lines +67 to +70
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.

🟡 Major version bump of livekit-protocol creates unsatisfiable dependency constraint in livekit-api

update_api_protocol_dependency only updates the lower bound of the version constraint in livekit-api/pyproject.toml but leaves the upper bound untouched. When doing a major bump (e.g., 1.1.42.0.0), the existing dependency "livekit-protocol>=1.1.1,<2.0.0" at livekit-api/pyproject.toml:33 becomes "livekit-protocol>=2.0.0,<2.0.0" — an impossible constraint that no version can satisfy. This would produce a broken release PR for livekit-api.

Trace through the code

The regex r'"livekit-protocol>=[\w.\-]+,' matches "livekit-protocol>=1.1.1, (up to and including the first comma). The replacement inserts the new version >=2.0.0,, but <2.0.0 remains from the original text, yielding >=2.0.0,<2.0.0.

Prompt for agents
The update_api_protocol_dependency function in .github/update_versions.py only updates the lower bound (>=) of the livekit-protocol dependency in livekit-api/pyproject.toml but does not update the upper bound (<). When the new protocol version crosses a major boundary (e.g., 2.0.0), the constraint becomes >=2.0.0,<2.0.0 which is unsatisfiable.

The fix should also update the upper bound to the next major version. For example, if new_protocol_version is 2.0.0, the upper bound should become <3.0.0. One approach: parse the new version with packaging.version.Version, compute the next major (major+1), and use a regex that replaces both the lower and upper bounds. Alternatively, expand the regex to capture the full constraint and rebuild it.

Relevant code: update_api_protocol_dependency function at .github/update_versions.py:61-74, and the current pyproject.toml constraint at livekit-api/pyproject.toml:33.
Open in Devin Review

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

)
if new_text != old_text:
pyproject.write_text(new_text)
print(f"Updated livekit-api dependency on livekit-protocol to >={new_protocol_version}")


def do_bump(package: str, bump_type: str) -> None:
version_path = PACKAGES[package]
vf = pathlib.Path(version_path)
cur = read_version(vf)
new = bump_version(cur, bump_type)
print(f"{package}: {_esc(31)}{cur}{_esc(0)} -> {_esc(32)}{new}{_esc(0)}")
write_new_version(vf, new)

if package == "livekit-protocol":
update_api_protocol_dependency(new)


def do_prerelease(package: str, prerelease_type: str) -> None:
version_path = PACKAGES[package]
vf = pathlib.Path(version_path)
cur = read_version(vf)
new = bump_prerelease(cur, prerelease_type)
print(f"{package}: {_esc(31)}{cur}{_esc(0)} -> {_esc(32)}{new}{_esc(0)}")
write_new_version(vf, new)

if package == "livekit-protocol":
update_api_protocol_dependency(new)


@click.command("bump")
@click.option(
"--package",
type=click.Choice(list(PACKAGES.keys())),
required=True,
help="Package to bump.",
)
@click.option(
"--pre",
type=click.Choice(["rc", "none"]),
default="none",
help="Pre-release type.",
)
@click.option(
"--bump-type",
type=click.Choice(["patch", "minor", "major", "release"]),
default="patch",
help="Type of version bump.",
)
def bump(package: str, pre: str, bump_type: str) -> None:
if pre == "none":
do_bump(package, bump_type)
else:
do_prerelease(package, pre)


if __name__ == "__main__":
bump()
25 changes: 12 additions & 13 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Build Docs

on:
Expand Down Expand Up @@ -50,24 +42,31 @@ jobs:
submodules: recursive

- name: Install Package to Document
run: python -m pip install ${{ inputs.package_dir }}/
env:
PACKAGE_DIR: ${{ inputs.package_dir }}
run: python -m pip install "$PACKAGE_DIR/"

- name: Download ffi
env:
PACKAGE_NAME: ${{ inputs.package_name }}
run: |
if [[ '${{ inputs.package_name }}' = 'livekit.rtc' ]]; then
if [[ "$PACKAGE_NAME" = 'livekit.rtc' ]]; then
pip install requests
python livekit-rtc/rust-sdks/download_ffi.py --output $(python -m site --user-site)/livekit/rtc/resources
python livekit-rtc/rust-sdks/download_ffi.py --output "$(python -m site --user-site)/livekit/rtc/resources"
fi

- name: Install pdoc
run: pip install --upgrade pdoc

- name: Build Docs
run: python -m pdoc ${{ inputs.package_name }} --docformat=google --output-dir docs
env:
PACKAGE_NAME: ${{ inputs.package_name }}
run: python -m pdoc "$PACKAGE_NAME" --docformat=google --output-dir docs

- name: S3 Upload
run: aws s3 cp docs/ s3://livekit-docs/${{ inputs.package_dir }} --recursive
env:
PACKAGE_DIR: ${{ inputs.package_dir }}
AWS_ACCESS_KEY_ID: ${{ secrets.DOCS_DEPLOY_AWS_ACCESS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.DOCS_DEPLOY_AWS_API_SECRET }}
AWS_DEFAULT_REGION: "us-east-1"
run: aws s3 cp docs/ "s3://livekit-docs/$PACKAGE_DIR" --recursive
Loading
Loading