fix: restore static runtime version

Fixes #8924
This commit is contained in:
Weilong Liao
2026-06-20 22:06:24 +08:00
committed by GitHub
parent 0a0c677404
commit d36987dd19
5 changed files with 47 additions and 161 deletions

View File

@@ -50,6 +50,7 @@ ruff check .
5. Use English for all new comments. 5. Use English for all new comments.
6. For path handling, use `pathlib.Path` instead of string paths, and use `astrbot.core.utils.path_utils` to get the AstrBot data and temp directory. 6. For path handling, use `pathlib.Path` instead of string paths, and use `astrbot.core.utils.path_utils` to get the AstrBot data and temp directory.
7. When backend API routes, request/response schemas, or OpenAPI definitions change, regenerate the frontend API client by running `cd dashboard && pnpm generate:api`. 7. When backend API routes, request/response schemas, or OpenAPI definitions change, regenerate the frontend API client by running `cd dashboard && pnpm generate:api`.
8. When updating the project version, keep `[project].version` in `pyproject.toml` and `VERSION` in `astrbot/core/config/default.py` in sync.
### KISS and First Principles ### KISS and First Principles
@@ -108,7 +109,7 @@ Prepare a release from a clean worktree with:
uv run python scripts/prepare_release.py 4.25.0 uv run python scripts/prepare_release.py 4.25.0
``` ```
The script updates `pyproject.toml`, creates `changelogs/v4.25.0.md`, runs the required Python checks, and prints the remaining steps. Use these flags when needed: The script updates `pyproject.toml` and `astrbot/core/config/default.py`, creates `changelogs/v4.25.0.md`, runs the required Python checks, and prints the remaining steps. Use these flags when needed:
```bash ```bash
uv run python scripts/prepare_release.py 4.25.0 --generate-api-client uv run python scripts/prepare_release.py 4.25.0 --generate-api-client

View File

@@ -1,39 +1,11 @@
"""如需修改配置,请在 `data/cmd_config.json` 中修改或者在管理面板中可视化修改。""" """如需修改配置,请在 `data/cmd_config.json` 中修改或者在管理面板中可视化修改。"""
import os import os
import re
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as package_version
from pathlib import Path
from astrbot.core.computer.booters.cua_defaults import CUA_DEFAULT_CONFIG from astrbot.core.computer.booters.cua_defaults import CUA_DEFAULT_CONFIG
from astrbot.core.utils.astrbot_path import get_astrbot_data_path from astrbot.core.utils.astrbot_path import get_astrbot_data_path
from astrbot.core.utils.toml_parser import read_pyproject_project_version
try:
import tomllib
except ModuleNotFoundError:
# <= Python 3.10 compatibility
tomllib = None
try:
pyproject_path = Path(__file__).resolve().parents[3] / "pyproject.toml"
if tomllib is None:
VERSION = read_pyproject_project_version(pyproject_path)
else:
with pyproject_path.open("rb") as f:
VERSION = tomllib.load(f)["project"]["version"]
except (FileNotFoundError, IndexError, KeyError, TypeError, ValueError):
try:
VERSION = package_version("astrbot") # PEP 440 version style, e.g. 1.2.3a4
match = re.match(r"^(\d+(?:\.\d+)*)(a|b|rc)(\d+)$", VERSION)
if match:
release, prerelease, number = match.groups()
prerelease = {"a": "alpha", "b": "beta", "rc": "rc"}[prerelease]
VERSION = f"{release}-{prerelease}.{number}"
except PackageNotFoundError:
VERSION = "0.0.0"
VERSION = "4.26.0-beta.10"
DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db") DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db")
PERSONAL_WECHAT_CONFIG_METADATA = { PERSONAL_WECHAT_CONFIG_METADATA = {
"weixin_oc_base_url": { "weixin_oc_base_url": {

View File

@@ -72,46 +72,6 @@ def _read_dependency_array(raw_value: str) -> list[str]:
raise ValueError("Unterminated project.dependencies array") raise ValueError("Unterminated project.dependencies array")
def read_pyproject_project_version(pyproject_path: Path) -> str:
"""Read the project version from a pyproject.toml file.
Args:
pyproject_path: Path to the pyproject.toml file.
Returns:
The value of the project.version field.
Raises:
FileNotFoundError: The pyproject.toml file does not exist.
ValueError: The project.version field is missing or unsupported.
"""
in_project_section = False
for raw_line in pyproject_path.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
if line.startswith("[") and line.endswith("]"):
in_project_section = line == "[project]"
continue
if not in_project_section:
continue
key, separator, raw_value = line.partition("=")
if key.strip() != "version":
continue
if not separator:
raise ValueError("Missing value separator for project.version")
version, tail = _read_quoted_value(raw_value, "project.version")
if tail and not tail.startswith("#"):
raise ValueError("Unsupported content after project.version")
return version
raise ValueError("Missing project.version")
def read_pyproject_project_dependencies(pyproject_path: Path) -> list[str]: def read_pyproject_project_dependencies(pyproject_path: Path) -> list[str]:
"""Read project dependencies from a pyproject.toml file. """Read project dependencies from a pyproject.toml file.

View File

@@ -193,6 +193,37 @@ def update_pyproject_version(version: str) -> Path:
raise ReleaseError("Missing [project].version in pyproject.toml") raise ReleaseError("Missing [project].version in pyproject.toml")
def update_default_config_version(version: str) -> Path:
"""Update the hard-coded runtime version in default.py.
Args:
version: Release version to write.
Returns:
Path to the modified default.py file.
Raises:
ReleaseError: The runtime version constant cannot be found or parsed.
"""
default_config_path = REPO_ROOT / "astrbot" / "core" / "config" / "default.py"
lines = default_config_path.read_text(encoding="utf-8").splitlines(keepends=True)
for index, line in enumerate(lines):
match = re.match(
r"^(\s*VERSION\s*=\s*)([\"'])(.*?)(\2)(\s*(?:#.*)?)(\n?)$",
line,
)
if not match:
continue
prefix, quote, _current, _closing_quote, suffix, newline = match.groups()
lines[index] = f"{prefix}{quote}{version}{quote}{suffix}{newline}"
default_config_path.write_text("".join(lines), encoding="utf-8")
return default_config_path
raise ReleaseError("Missing VERSION in astrbot/core/config/default.py")
def write_changelog(version: str, commits: list[str]) -> Path: def write_changelog(version: str, commits: list[str]) -> Path:
"""Write a changelog draft for the release. """Write a changelog draft for the release.
@@ -297,7 +328,14 @@ def commit_and_maybe_push(
Raises: Raises:
ReleaseError: Git add, commit, or push fails. ReleaseError: Git add, commit, or push fails.
""" """
git(["add", "pyproject.toml", str(changelog_path.relative_to(REPO_ROOT))]) git(
[
"add",
"pyproject.toml",
"astrbot/core/config/default.py",
str(changelog_path.relative_to(REPO_ROOT)),
]
)
if args.generate_api_client: if args.generate_api_client:
git(["add", "dashboard/src/api/generated"]) git(["add", "dashboard/src/api/generated"])
@@ -331,7 +369,9 @@ def print_next_steps(
else: else:
print("Next:") print("Next:")
print(f"1. Review and polish {changelog_rel}") print(f"1. Review and polish {changelog_rel}")
print(f"2. git add pyproject.toml {changelog_rel}") print(
f"2. git add pyproject.toml astrbot/core/config/default.py {changelog_rel}"
)
print(f'3. git commit -m "chore: bump version to {version}"') print(f'3. git commit -m "chore: bump version to {version}"')
print(f"4. git push -u {args.remote} {branch}") print(f"4. git push -u {args.remote} {branch}")
@@ -414,6 +454,7 @@ def main(argv: list[str] | None = None) -> int:
commits = release_commits(tag) commits = release_commits(tag)
update_pyproject_version(version) update_pyproject_version(version)
update_default_config_version(version)
changelog_path = write_changelog(version, commits) changelog_path = write_changelog(version, commits)
run_validation(args) run_validation(args)

View File

@@ -2,87 +2,7 @@ from pathlib import Path
import pytest import pytest
from astrbot.core.utils.toml_parser import ( from astrbot.core.utils.toml_parser import read_pyproject_project_dependencies
read_pyproject_project_dependencies,
read_pyproject_project_version,
)
def test_read_pyproject_project_version_reads_project_section(tmp_path: Path) -> None:
pyproject_path = tmp_path / "pyproject.toml"
pyproject_path.write_text(
"\n".join(
[
'version = "ignored"',
"[project]",
'name = "AstrBot"',
'version = "1.2.3-beta.4" # release version',
"[tool.example]",
'version = "ignored-again"',
]
),
encoding="utf-8",
)
assert read_pyproject_project_version(pyproject_path) == "1.2.3-beta.4"
@pytest.mark.parametrize(
("version_line", "expected"),
[
('version = "1.2.3"', "1.2.3"),
("version='1.2.3-beta.4'", "1.2.3-beta.4"),
(' version = "1.2.3-rc.1" ', "1.2.3-rc.1"),
],
)
def test_read_pyproject_project_version_accepts_simple_variants(
tmp_path: Path,
version_line: str,
expected: str,
) -> None:
pyproject_path = tmp_path / "pyproject.toml"
pyproject_path.write_text(
"\n".join(
[
"[project]",
'name = "AstrBot"',
version_line,
]
),
encoding="utf-8",
)
assert read_pyproject_project_version(pyproject_path) == expected
@pytest.mark.parametrize(
("version_line", "message"),
[
("version", "Missing value separator for project.version"),
('version = "1.2.3', "Unterminated project.version string"),
('version = "1.2.3" extra', "Unsupported content after project.version"),
('version = ""', "Empty project.version value"),
],
)
def test_read_pyproject_project_version_rejects_invalid_values(
tmp_path: Path,
version_line: str,
message: str,
) -> None:
pyproject_path = tmp_path / "pyproject.toml"
pyproject_path.write_text(
"\n".join(
[
"[project]",
'name = "AstrBot"',
version_line,
]
),
encoding="utf-8",
)
with pytest.raises(ValueError, match=message):
read_pyproject_project_version(pyproject_path)
def test_read_pyproject_project_dependencies_reads_multiline_array( def test_read_pyproject_project_dependencies_reads_multiline_array(
@@ -174,11 +94,3 @@ def test_read_pyproject_project_dependencies_rejects_invalid_values(
with pytest.raises(ValueError, match=message): with pytest.raises(ValueError, match=message):
read_pyproject_project_dependencies(pyproject_path) read_pyproject_project_dependencies(pyproject_path)
def test_read_pyproject_project_version_raises_when_missing(tmp_path: Path) -> None:
pyproject_path = tmp_path / "pyproject.toml"
pyproject_path.write_text('[project]\nname = "AstrBot"\n', encoding="utf-8")
with pytest.raises(ValueError, match="Missing project.version"):
read_pyproject_project_version(pyproject_path)