forked from MPAS-Dev/MPAS-Tools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathupdate_version.py
More file actions
executable file
·149 lines (122 loc) · 3.86 KB
/
update_version.py
File metadata and controls
executable file
·149 lines (122 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#! /usr/bin/env python
import argparse
import re
import sys
from datetime import date
from pathlib import Path
def parse_args():
parser = argparse.ArgumentParser(
description=(
"Bump version across files (CITATION.cff, __init__.py, meta.yaml)."
)
)
parser.add_argument(
"-v",
"--version",
required=True,
help="New version in the form X.Y.Z (e.g., 1.3.0)",
)
return parser.parse_args()
def ensure_semver(version: str):
m = re.fullmatch(r"(\d+)\.(\d+)\.(\d+)", version)
if not m:
sys.exit("Error: version must be in the form X.Y.Z (e.g., 1.3.0).")
return tuple(int(p) for p in m.groups())
def read_text(path: Path):
try:
return path.read_text(encoding="utf-8")
except FileNotFoundError:
return None
def write_text_if_changed(path: Path, content: str) -> bool:
old = read_text(path)
if old is None:
return False
if old != content:
path.write_text(content, encoding="utf-8")
return True
return False
def bump_citation(root: Path, version: str, today: str) -> bool:
path = root / "CITATION.cff"
content = read_text(path)
if content is None:
print(f"Skip (not found): {path}")
return False
# version: 1.2.1 -> version: 1.2.2
content_new = re.sub(
r"(?m)^(version:\s*)(.+)\s*$", rf"\g<1>{version}", content, count=1
)
# date-released: '2025-06-12' -> date-released: 'YYYY-MM-DD'
content_new = re.sub(
r"""(?m)^(date-released:\s*)['"]?\d{4}-\d{2}-\d{2}['"]?\s*$""",
rf"\g<1>'{today}'",
content_new,
count=1,
)
# Ensure a final newline at EOF
if not content_new.endswith("\n"):
content_new += "\n"
changed = write_text_if_changed(path, content_new)
if changed:
print(f"Updated: {path}")
else:
print(f"No changes: {path}")
return changed
def bump_init(pkg_dir: Path, version_tuple) -> bool:
path = pkg_dir / "mpas_tools" / "__init__.py"
content = read_text(path)
if content is None:
print(f"Skip (not found): {path}")
return False
major, minor, patch = version_tuple
content_new = re.sub(
r"(?m)^__version_info__\s*=\s*\(.+\)\s*$",
f"__version_info__ = ({major}, {minor}, {patch})",
content,
count=1,
)
changed = write_text_if_changed(path, content_new)
if changed:
print(f"Updated: {path}")
else:
print(f"No changes: {path}")
return changed
def bump_meta(recipe_dir: Path, version: str) -> bool:
path = recipe_dir / "meta.yaml"
content = read_text(path)
if content is None:
print(f"Skip (not found): {path}")
return False
# {% set version = "1.2.1" %} -> {% set version = "1.2.2" %}
content_new = re.sub(
r'(?m)^\{\%\s*set\s+version\s*=\s*["\']([^"\']+)["\']\s*\%\}',
f'{{% set version = "{version}" %}}',
content,
count=1,
)
changed = write_text_if_changed(path, content_new)
if changed:
print(f"Updated: {path}")
else:
print(f"No changes: {path}")
return changed
def main():
args = parse_args()
version = args.version.strip()
version_tuple = ensure_semver(version)
today = date.today().isoformat()
# Resolve repo layout relative to this script
script_dir = Path(__file__).resolve().parent
repo_root = script_dir
pkg_dir = script_dir / "conda_package"
recipe_dir = pkg_dir / "recipe"
changed = []
changed.append(bump_citation(repo_root, version, today))
changed.append(bump_init(pkg_dir, version_tuple))
changed.append(bump_meta(recipe_dir, version))
if not any(changed):
print("No files modified.")
return 0
print(f"Done. Bumped to {version} (date-released: {today}).")
return 0
if __name__ == "__main__":
raise SystemExit(main())