Skip to content

Commit 84230a3

Browse files
authored
[CI]: Pre-release workflow (#19943)
* move bump utils to global module * add prepare() command * add pre-release workflow * trigger workflow * pull the whole history * accept type of release * simplify bump strategy * fix destructive typo
1 parent ffcfb27 commit 84230a3

File tree

5 files changed

+177
-49
lines changed

5 files changed

+177
-49
lines changed

.github/workflows/pre_release.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Pre-release for llama-index
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version-type:
7+
description: "The type of release to prepare"
8+
required: true
9+
type: choice
10+
options:
11+
- patch
12+
- minor
13+
- major
14+
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
19+
jobs:
20+
prepare-release:
21+
if: github.repository == 'run-llama/llama_index'
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v5
25+
with:
26+
fetch-depth: 0
27+
28+
- name: Install uv and set python version
29+
uses: astral-sh/setup-uv@v6
30+
with:
31+
python-version: "3.10"
32+
33+
- name: Prepare
34+
shell: bash
35+
working-directory: llama-dev
36+
run: |
37+
uv run -- llama-dev --repo-root .. release prepare --version-type ${{ github.event.inputs.version-type }}
38+
uv run -- llama-dev --repo-root .. release changelog
39+
40+
- name: Create Release PR
41+
id: rpr
42+
uses: peter-evans/create-pull-request@v7
43+
with:
44+
commit-message: Prepare release
45+
signoff: false
46+
branch: pre-release
47+
delete-branch: true
48+
title: "Prepare release"
49+
draft: false

llama-dev/llama_dev/pkg/bump.py

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,13 @@
1-
import re
2-
from enum import Enum
3-
from pathlib import Path
4-
51
import click
6-
from packaging.version import Version
7-
8-
from llama_dev.utils import find_all_packages, is_llama_index_package, load_pyproject
9-
10-
11-
class BumpType(str, Enum):
12-
MAJOR = "major"
13-
MINOR = "minor"
14-
PATCH = "patch"
15-
16-
17-
def bump_version(current_version: str, bump_type: BumpType) -> str:
18-
"""Bump a version string according to semver rules."""
19-
v = Version(current_version)
20-
21-
# Parse the version components
22-
release = v.release
23-
major = release[0] if len(release) > 0 else 0
24-
minor = release[1] if len(release) > 1 else 0
25-
micro = release[2] if len(release) > 2 else 0
262

27-
version_str = ""
28-
if bump_type == BumpType.MAJOR:
29-
version_str = f"{major + 1}.0.0"
30-
elif bump_type == BumpType.MINOR:
31-
version_str = f"{major}.{minor + 1}.0"
32-
elif bump_type == BumpType.PATCH:
33-
version_str = f"{major}.{minor}.{micro + 1}"
34-
35-
return version_str
36-
37-
38-
def update_pyproject_version(package_path: Path, new_version: str) -> None:
39-
"""Update the version in a pyproject.toml file."""
40-
pyproject_path = package_path / "pyproject.toml"
41-
42-
# Read the file content
43-
with open(pyproject_path, "r") as f:
44-
content = f.read()
45-
46-
pattern = r'(\[project\][^\[]*?version\s*=\s*["\'])([^"\']+)(["\'])'
47-
new_content = re.sub(pattern, rf"\g<1>{new_version}\g<3>", content, flags=re.DOTALL)
48-
49-
# Write the updated content back
50-
with open(pyproject_path, "w") as f:
51-
f.write(new_content)
3+
from llama_dev.utils import (
4+
BumpType,
5+
bump_version,
6+
find_all_packages,
7+
is_llama_index_package,
8+
load_pyproject,
9+
update_pyproject_version,
10+
)
5211

5312

5413
@click.command(short_help="Bump package version")

llama-dev/llama_dev/release/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from .changelog import changelog
44
from .check import check
5+
from .prepare import prepare
56

67

78
@click.group(short_help="Utilities for the release process in the monorepo")
@@ -11,3 +12,4 @@ def release():
1112

1213
release.add_command(check)
1314
release.add_command(changelog)
15+
release.add_command(prepare)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from pathlib import Path
2+
3+
import click
4+
5+
from llama_dev.utils import (
6+
BumpType,
7+
bump_version,
8+
load_pyproject,
9+
update_pyproject_version,
10+
)
11+
12+
13+
def _replace_core_dependency(project_path: Path, old_dep: str, new_dep: str):
14+
pyproject_path = project_path / "pyproject.toml"
15+
# Read the file content
16+
with open(pyproject_path, "r") as f:
17+
content = f.read()
18+
19+
# Replace the old dependency string
20+
new_content = content.replace(old_dep, new_dep)
21+
22+
# Write the updated content back
23+
with open(pyproject_path, "w") as f:
24+
f.write(new_content)
25+
26+
27+
@click.command(
28+
short_help="Bump the versions to begin a llama_index umbrella package release"
29+
)
30+
@click.option(
31+
"--version-type",
32+
type=click.Choice([t.value for t in BumpType], case_sensitive=False),
33+
default=BumpType.PATCH.value,
34+
help="Type of version bump to perform (default: patch)",
35+
)
36+
@click.option(
37+
"--dry-run",
38+
is_flag=True,
39+
help="Show what would be done without making changes",
40+
)
41+
@click.pass_obj
42+
def prepare(
43+
obj: dict,
44+
version_type: str,
45+
dry_run: bool,
46+
):
47+
"""Bump the version numbers to initiate the llama_index umbrella package release."""
48+
console = obj["console"]
49+
repo_root = obj["repo_root"]
50+
bump_enum = BumpType(version_type)
51+
52+
root_package_data = load_pyproject(repo_root)
53+
current_version = root_package_data["project"]["version"]
54+
new_version = bump_version(current_version, bump_enum)
55+
new_dep_string = (
56+
f"llama-index-core>={new_version},<{bump_version(new_version, BumpType.MINOR)}"
57+
)
58+
59+
if dry_run:
60+
console.print(f"Would bump llama_index from {current_version} to {new_version}")
61+
console.print(f"llama_index will depend on '{new_dep_string}'")
62+
else:
63+
# Update llama-index version number
64+
update_pyproject_version(repo_root, new_version)
65+
# Update llama-index-core version number
66+
update_pyproject_version(repo_root / "llama-index-core", new_version)
67+
# Update llama-index-core dependency version
68+
for dep in root_package_data["project"]["dependencies"]:
69+
if dep.startswith("llama-index-core"):
70+
_replace_core_dependency(repo_root, dep, new_dep_string)
71+
break

llama-dev/llama_dev/utils.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,61 @@
11
import re
22
import subprocess
33
import sys
4+
from enum import Enum
45
from pathlib import Path
56

67
import tomli
78
from packaging import specifiers, version
9+
from packaging.version import Version
810

911
DEP_NAME_REGEX = re.compile(r"([^<>=\[\];\s]+)")
1012

1113

14+
class BumpType(str, Enum):
15+
MAJOR = "major"
16+
MINOR = "minor"
17+
PATCH = "patch"
18+
19+
20+
def bump_version(current_version: str, bump_type: BumpType) -> str:
21+
"""Bump a version string according to semver rules."""
22+
v = Version(current_version)
23+
24+
# Parse the version components
25+
release = v.release
26+
major = release[0] if len(release) > 0 else 0
27+
minor = release[1] if len(release) > 1 else 0
28+
micro = release[2] if len(release) > 2 else 0
29+
30+
version_str = ""
31+
if bump_type == BumpType.MAJOR:
32+
version_str = f"{major + 1}.0.0"
33+
elif bump_type == BumpType.MINOR:
34+
version_str = f"{major}.{minor + 1}.0"
35+
elif bump_type == BumpType.PATCH:
36+
version_str = f"{major}.{minor}.{micro + 1}"
37+
38+
return version_str
39+
40+
41+
def update_pyproject_version(package_path: Path, new_version: str) -> None:
42+
"""Update the version in a pyproject.toml file."""
43+
pyproject_path = package_path / "pyproject.toml"
44+
45+
# Read the file content
46+
with open(pyproject_path, "r") as f:
47+
content = f.read()
48+
49+
pattern = r'^version = "[^"]+"'
50+
new_content = re.sub(
51+
pattern, f'version = "{new_version}"', content, flags=re.MULTILINE
52+
)
53+
54+
# Write the updated content back
55+
with open(pyproject_path, "w") as f:
56+
f.write(new_content)
57+
58+
1259
def package_has_tests(package_path: Path) -> bool:
1360
"""Returns whether a package folder contains a 'tests' subfolder."""
1461
tests_folder = package_path / "tests"

0 commit comments

Comments
 (0)