chore: release v1.0.3
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Update or verify ferro-ta version strings across release files.
|
||||
|
||||
Usage
|
||||
-----
|
||||
python3 scripts/bump_version.py 1.0.3
|
||||
python3 scripts/bump_version.py --check
|
||||
python3 scripts/bump_version.py --show
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
SEMVER_RE = re.compile(r"^\d+\.\d+\.\d+$")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class VersionCarrier:
|
||||
label: str
|
||||
path: Path
|
||||
pattern: str
|
||||
replacement: str
|
||||
|
||||
def read(self) -> str:
|
||||
text = self.path.read_text(encoding="utf-8")
|
||||
match = re.search(self.pattern, text, flags=re.MULTILINE)
|
||||
if not match:
|
||||
raise ValueError(f"Could not find version for {self.label} in {self.path}")
|
||||
return match.group(2)
|
||||
|
||||
def write(self, version: str) -> bool:
|
||||
text = self.path.read_text(encoding="utf-8")
|
||||
updated, count = re.subn(
|
||||
self.pattern,
|
||||
rf"\g<1>{version}\g<3>",
|
||||
text,
|
||||
count=1,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
if count != 1:
|
||||
raise ValueError(f"Could not update {self.label} in {self.path}")
|
||||
changed = updated != text
|
||||
if changed:
|
||||
self.path.write_text(updated, encoding="utf-8")
|
||||
return changed
|
||||
|
||||
|
||||
CARRIERS = [
|
||||
VersionCarrier(
|
||||
"cargo_root",
|
||||
ROOT / "Cargo.toml",
|
||||
r'(?m)^(version = ")([^"]+)(")$',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"cargo_core_dep",
|
||||
ROOT / "Cargo.toml",
|
||||
r'(ferro_ta_core = \{ path = "crates/ferro_ta_core", version = ")([^"]+)(" \})',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"cargo_core_crate",
|
||||
ROOT / "crates" / "ferro_ta_core" / "Cargo.toml",
|
||||
r'(?m)^(version = ")([^"]+)(")$',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"cargo_core_readme",
|
||||
ROOT / "crates" / "ferro_ta_core" / "README.md",
|
||||
r'(ferro_ta_core = ")([^"]+)(")',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"pyproject",
|
||||
ROOT / "pyproject.toml",
|
||||
r'(?m)^(version = ")([^"]+)(")$',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"wasm_cargo",
|
||||
ROOT / "wasm" / "Cargo.toml",
|
||||
r'(?m)^(version = ")([^"]+)(")$',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"wasm_package",
|
||||
ROOT / "wasm" / "package.json",
|
||||
r'("version": ")([^"]+)(")',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"conda",
|
||||
ROOT / "conda" / "meta.yaml",
|
||||
r'({% set version = ")([^"]+)(" %})',
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"docs_changelog",
|
||||
ROOT / "docs" / "changelog.rst",
|
||||
r"(These docs track package version ``)([^`]+)(``\.)",
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
VersionCarrier(
|
||||
"docs_support_matrix",
|
||||
ROOT / "docs" / "support_matrix.rst",
|
||||
r"(These docs track package version ``)([^`]+)(``\.)",
|
||||
r"\g<1>{version}\g<3>",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def _read_versions() -> dict[str, str]:
|
||||
return {carrier.label: carrier.read() for carrier in CARRIERS}
|
||||
|
||||
|
||||
def _print_versions(versions: dict[str, str]) -> None:
|
||||
for label, version in versions.items():
|
||||
print(f"{label:20} {version}")
|
||||
|
||||
|
||||
def _check_versions() -> int:
|
||||
versions = _read_versions()
|
||||
unique = sorted(set(versions.values()))
|
||||
_print_versions(versions)
|
||||
if len(unique) != 1:
|
||||
print()
|
||||
print(f"ERROR: version mismatch detected: {', '.join(unique)}")
|
||||
return 1
|
||||
print()
|
||||
print(f"OK: all tracked versions match {unique[0]}")
|
||||
return 0
|
||||
|
||||
|
||||
def _set_version(version: str) -> int:
|
||||
if not SEMVER_RE.match(version):
|
||||
print(f"ERROR: expected MAJOR.MINOR.PATCH, got {version!r}")
|
||||
return 1
|
||||
|
||||
changed_paths: list[Path] = []
|
||||
for carrier in CARRIERS:
|
||||
if carrier.write(version):
|
||||
changed_paths.append(carrier.path)
|
||||
|
||||
if changed_paths:
|
||||
print(f"Updated version to {version}:")
|
||||
for path in sorted(set(changed_paths)):
|
||||
print(f" - {path.relative_to(ROOT)}")
|
||||
else:
|
||||
print(f"No changes needed. All tracked files already use {version}.")
|
||||
return 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("version", nargs="?", help="New version to write")
|
||||
parser.add_argument(
|
||||
"--check",
|
||||
action="store_true",
|
||||
help="Fail if tracked version strings do not match",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--show",
|
||||
action="store_true",
|
||||
help="Print tracked version strings without modifying files",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.check:
|
||||
return _check_versions()
|
||||
if args.show:
|
||||
_print_versions(_read_versions())
|
||||
return 0
|
||||
if args.version:
|
||||
return _set_version(args.version)
|
||||
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user