Skip to content

Commit ad71d73

Browse files
feat: [CG-10557] Codegen update command (#353)
# Motivation <!-- Why is this change necessary? --> Add a way for users to update their codegen CLI, list versions, and specify versions to update. # Content <!-- Please include a summary of the change --> Added a update command. Added ability to list versions and to install a specific version. # Testing <!-- How was the change tested? --> Added unit tests. Ran update locally. ```bash [clee-cg-10557-codegen-update-command] codegen-sdk/$ uv run codegen update --list Built codegen @ file:///home/chris/codegen/codegen-sdk Uninstalled 2 packages in 17ms Installed 3 packages in 26ms 1.0 1.19.0 1.20.0 (current) 1.21.0 1.22.0 1.22.1 1.22.2 1.23.0 1.24.0 1.24.1 ``` # Please check the following before marking your PR as ready for review - [x] I have added tests for my changes - [x] I have updated the documentation or added new documentation as needed --------- Co-authored-by: clee-codegen <[email protected]> Co-authored-by: Jay Hack <[email protected]>
1 parent 10b66cf commit ad71d73

File tree

7 files changed

+3617
-0
lines changed

7 files changed

+3617
-0
lines changed

docs/cli/update.mdx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: "Update Command"
3+
sidebarTitle: "update"
4+
icon: "sync"
5+
iconType: "solid"
6+
---
7+
8+
The `update` command is designed to help you manage the version of Codegen installed on your system. Whether you want to update to the latest version or switch to a specific version, this command offers a streamlined way to do so. Additionally, you can list all supported versions available on PyPI.
9+
10+
```bash
11+
codegen update [OPTIONS]
12+
```
13+
14+
## Usage
15+
16+
```bash
17+
codegen update [OPTIONS]
18+
```
19+
20+
## Options
21+
22+
- `--list, -l`: List all supported versions of Codegen.
23+
When used, the command fetches the available releases from PyPI, filters them to display a range of versions (typically including the current version and a few preceding minor versions), and highlights the current version in the output.
24+
25+
- `--version, -v`: Update to a specific version of Codegen (e.g., `2.1.0`).
26+
This option enables you to target a particular version rather than updating to the latest available release.
27+
28+
## Examples
29+
30+
Update Codegen to the latest version:
31+
```bash
32+
codegen update
33+
```
34+
35+
List all supported versions of Codegen:
36+
```bash
37+
codegen update --list
38+
```
39+
40+
Update Codegen to a specific version:
41+
```bash
42+
codegen update --version 2.1.0
43+
```
44+
45+
## Execution Flow
46+
47+
When you run the `update` command, the following steps occur:
48+
49+
1. **Retrieve Current Version:**
50+
The command retrieves the current version of Codegen by accessing package metadata.
51+
52+
2. **Option Handling:**
53+
- **Listing Versions:**
54+
If you use the `--list` flag, the command fetches all available releases from PyPI, filters them based on a defined range (typically covering future versions and a couple of previous minor versions), and prints the list with the current version highlighted.
55+
56+
- **Specific Version Update:**
57+
If the `--version` option is provided, the command installs the specified version by invoking `pip install` with the exact version (e.g., `pip install codegen==2.1.0`).
58+
59+
- **Default Update:**
60+
If no options are provided, the command updates Codegen to the latest version using `pip install --upgrade`.
61+
62+
3. **Error Handling:**
63+
The command checks for mutually exclusive options. If both `--list` and `--version` are specified simultaneously, an error is raised.
64+
65+
<Note>
66+
Ensure you use either `--list` or `--version` when running the update command, not both.
67+
</Note>

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ dependencies = [
6363
"tomlkit>=0.13.2",
6464
"python-semantic-release",
6565
"uvicorn[standard]>=0.30.0",
66+
"packaging>=24.2",
6667
"langchain[openai]",
6768
"langchain_core",
6869
"langchain_openai",

src/codegen/cli/cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from codegen.cli.commands.run.main import run_command
1616
from codegen.cli.commands.run_on_pr.main import run_on_pr_command
1717
from codegen.cli.commands.style_debug.main import style_debug_command
18+
from codegen.cli.commands.update.main import update_command
1819

1920
click.rich_click.USE_RICH_MARKUP = True
2021
install(show_locals=True)
@@ -40,6 +41,7 @@ def main():
4041
main.add_command(run_on_pr_command)
4142
main.add_command(notebook_command)
4243
main.add_command(reset_command)
44+
main.add_command(update_command)
4345
main.add_command(config_command)
4446

4547

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import subprocess
2+
import sys
3+
from importlib.metadata import distribution
4+
5+
import requests
6+
import rich
7+
import rich_click as click
8+
from packaging.version import Version
9+
10+
import codegen
11+
12+
13+
def fetch_pypi_releases(package: str) -> list[str]:
14+
response = requests.get(f"https://pypi.org/pypi/{package}/json")
15+
response.raise_for_status()
16+
return response.json()["releases"].keys()
17+
18+
19+
def filter_versions(versions: list[Version], current_version: Version, num_prev_minor_version: int = 1) -> list[Version]:
20+
descending_minor_versions = [v_tuple for v_tuple in sorted(set(v.release[:2] for v in versions), reverse=True) if v_tuple < current_version.release[:2]]
21+
try:
22+
compare_tuple = descending_minor_versions[:num_prev_minor_version][-1] + (0,)
23+
except IndexError:
24+
compare_tuple = (current_version.major, current_version.minor, 0)
25+
26+
return [v for v in versions if (v.major, v.minor, v.micro) >= compare_tuple] # v.release will only show major,minor if micro doesn't exist.
27+
28+
29+
def install_package(package: str, *args: str) -> None:
30+
subprocess.check_call([sys.executable, "-m", "pip", "install", package, *args])
31+
32+
33+
@click.command(name="update")
34+
@click.option(
35+
"--list",
36+
"-l",
37+
"list_",
38+
is_flag=True,
39+
help="List all supported versions of the codegen",
40+
)
41+
@click.option("--version", "-v", type=str, help="Update to a specific version of the codegen")
42+
def update_command(list_: bool = False, version: str | None = None):
43+
"""Update Codegen to the latest or specified version
44+
45+
--list: List all supported versions of the codegen
46+
--version: Update to a specific version of the codegen
47+
"""
48+
if list_ and version:
49+
msg = "Cannot specify both --list and --version"
50+
raise click.ClickException(msg)
51+
52+
package_info = distribution(codegen.__package__)
53+
current_version = Version(package_info.version)
54+
55+
if list_:
56+
releases = fetch_pypi_releases(package_info.name)
57+
filtered_releases = filter_versions([Version(r) for r in releases], current_version, num_prev_minor_version=2)
58+
for release in filtered_releases:
59+
if release.release == current_version.release:
60+
rich.print(f"[bold]{release}[/bold] (current)")
61+
else:
62+
rich.print(release)
63+
elif version:
64+
install_package(f"{package_info.name}=={version}")
65+
else:
66+
# Update to latest version
67+
install_package(package_info.name, "--upgrade")

0 commit comments

Comments
 (0)