ReMe/scripts/bump_version.py
jinliyl ef3f99f019
refactor(packaging): reorganize published packages (#495)
* refactor(packaging): reorganize published packages

* fix(packaging): install AgentScope extra in wheel smoke

* docs: align package guides and documentation site

* ci(workflow): add core dependency verification step in Python package build

- Add a workflow step to verify released core dependencies by installing the wheel with core extras
- Assert the presence of the static index.html file to ensure proper package contents
- Create and use a temporary virtual environment for isolation during verification
- Keep existing artifacts upload step intact and conditional on inputs.upload_artifacts flag

* fix(ci): update package installation dependencies in Windows workflow

- Change pip install from editable reme_studio and core to only dev and as extras
- Remove installation of reme_studio and core to streamline dependency setup
- Ensure Windows CI uses the correct extras for testing environment

* fix(tests): add missing commas in toml file reads in package version tests

- Added trailing commas in the tomllib.loads calls for auto-fin and daily_paper configs
- Ensured consistent syntax to prevent potential tuple misinterpretation
- Improved readability and correctness of the test setup code

* fix(packaging): protect qwenpaw releases and test Studio health
2026-08-27 14:02:09 +08:00

123 lines
4.8 KiB
Python

"""Validate or update the ReMe release version."""
from __future__ import annotations
import argparse
import os
import re
import tempfile
from pathlib import Path
from packaging.version import InvalidVersion, Version
REPOSITORY_DIR = Path(__file__).resolve().parents[1]
_VERSION_PATTERN = re.compile(r'(?m)^__version__ = "(?P<version>[^"]+)"$')
def _version_file(repository: Path) -> Path:
return repository / "reme" / "__init__.py"
def _canonical_version(value: str) -> str:
"""Return one canonical PEP 440 version or explain how to correct it."""
try:
canonical = str(Version(value))
except InvalidVersion as error:
raise ValueError(
f"Invalid PEP 440 version {value!r}. Use a version such as 0.4.1.8, then rerun this command.",
) from error
if canonical != value:
raise ValueError(f"Version {value!r} is not canonical PEP 440; use {canonical!r} instead.")
return canonical
def _match_version(text: str, source: Path) -> str:
matches = list(_VERSION_PATTERN.finditer(text))
if len(matches) != 1:
raise ValueError(f"Expected exactly one version declaration in {source}, found {len(matches)}.")
return matches[0].group("version")
def _write_atomic(path: Path, content: str) -> None:
"""Replace one text file without exposing a partially written file."""
temporary_name: str | None = None
try:
with tempfile.NamedTemporaryFile("w", encoding="utf-8", dir=path.parent, delete=False) as temporary:
temporary.write(content)
temporary_name = temporary.name
os.chmod(temporary_name, path.stat().st_mode)
os.replace(temporary_name, path)
finally:
if temporary_name is not None and os.path.exists(temporary_name):
os.unlink(temporary_name)
def read_version(repository: Path = REPOSITORY_DIR) -> str:
"""Read and validate the ReMe distribution version."""
version_file = _version_file(repository)
version = _match_version(version_file.read_text(encoding="utf-8"), version_file)
try:
return _canonical_version(version)
except ValueError as error:
raise ValueError(f"{version_file}: {error} Fix the __version__ declaration and retry.") from error
def check_versions(repository: Path = REPOSITORY_DIR, expected_version: str | None = None) -> str:
"""Validate the ReMe version and an optional release tag."""
version = read_version(repository)
if expected_version is None:
return version
expected = _canonical_version(expected_version.removeprefix("v"))
if version != expected:
version_file = _version_file(repository)
raise ValueError(f"{version_file}: package version is {version!r}; release expects {expected!r}")
return version
def bump_version(version: str, repository: Path = REPOSITORY_DIR) -> str:
"""Update the ReMe version without coupling independently released packages."""
version = _canonical_version(version)
previous_version = read_version(repository)
version_file = _version_file(repository)
original = version_file.read_text(encoding="utf-8")
_match_version(original, version_file)
updated = _VERSION_PATTERN.sub(
lambda match: match.group(0).replace(match.group("version"), version),
original,
)
_write_atomic(version_file, updated)
try:
check_versions(repository, version)
except BaseException as error:
try:
_write_atomic(version_file, original)
except OSError as rollback_error:
raise RuntimeError(f"Version update failed and rollback was incomplete: {version_file}") from rollback_error
raise RuntimeError("Version update failed; the previous version was restored.") from error
return previous_version
def main() -> None:
"""Run the version validation or update command."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("version", nargs="?", help="New ReMe version, for example 0.4.1.8")
parser.add_argument("--check", action="store_true", help="Validate the version without changing files")
parser.add_argument("--expected-version", help="Also require this release/tag version; a leading v is accepted")
args = parser.parse_args()
if args.check:
if args.version:
parser.error("version cannot be used with --check; use --expected-version")
version = check_versions(expected_version=args.expected_version)
print(f"ReMe release version is valid: {version}")
return
if args.expected_version:
parser.error("--expected-version requires --check")
if not args.version:
parser.error("provide a version to update, or use --check")
previous_version = bump_version(args.version)
print(f"Updated ReMe from {previous_version} to {args.version}")
if __name__ == "__main__":
main()