-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathrelease.py
More file actions
136 lines (108 loc) · 3.76 KB
/
Copy pathrelease.py
File metadata and controls
136 lines (108 loc) · 3.76 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
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
# /// script
# dependencies = [
# "click",
# "packaging",
# ]
# ///
import pathlib
import re
import subprocess
import sys
import click
from packaging.version import Version
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
def run(*args: str) -> None:
print(f"[running] {list(args)}")
subprocess.check_call(list(args))
@click.group()
def cli():
pass
@cli.command()
def release() -> None:
base_dir = pathlib.Path(__file__).parent
with (base_dir / "pyproject.toml").open("rb") as f:
pyproject = tomllib.load(f)
version = pyproject["project"]["version"]
if Version(version).is_prerelease:
raise RuntimeError(
f"Can't release, pyproject.toml version is pre-release: {version}"
)
# Tag and push the tag (this will trigger the wheel builder in Actions)
run("git", "tag", "-s", version, "-m", f"{version} release")
run("git", "push", "--tags", "git@github.com:pyca/cryptography.git")
def replace_pattern(p: pathlib.Path, pattern: str, replacement: str) -> None:
content = p.read_text()
match = re.search(pattern, content, re.MULTILINE)
assert match is not None
start, end = match.span()
new_content = content[:start] + replacement + content[end:]
p.write_text(new_content)
def replace_version(
p: pathlib.Path, variable_name: str, new_version: str
) -> None:
replace_pattern(
p, rf"^{variable_name}\s*=\s*.*$", f'{variable_name} = "{new_version}"'
)
def rust_version(version: Version) -> str:
# The Rust crates use a version that maps to the cryptography version,
# but pre-1.0: cryptography X.0.Z is version 0.X.Z of the crates, and
# pre-releases map to semver pre-releases (49.0.0.dev1 is 0.49.0-dev1).
if version.minor != 0:
raise ValueError(
f"Can't map {version} to a crate version, minor must be 0"
)
crate_version = f"0.{version.major}.{version.micro}"
pre_parts = []
if version.pre is not None:
pre_parts.append(f"{version.pre[0]}{version.pre[1]}")
if version.dev is not None:
pre_parts.append(f"dev{version.dev}")
if pre_parts:
crate_version += "-" + ".".join(pre_parts)
return crate_version
def bump_rust_versions(base_dir: pathlib.Path, new_version: str) -> None:
# All crates in the workspace inherit the workspace version, so we only
# need to update it in one place, then sync Cargo.lock.
replace_version(
base_dir / "Cargo.toml", "version", rust_version(Version(new_version))
)
run("cargo", "update", "--workspace")
@cli.command()
@click.argument("new_version")
def bump_version(new_version: str) -> None:
base_dir = pathlib.Path(__file__).parent
replace_version(base_dir / "pyproject.toml", "version", new_version)
replace_version(
base_dir / "src/cryptography/__about__.py", "__version__", new_version
)
replace_version(
base_dir / "vectors/pyproject.toml",
"version",
new_version,
)
replace_version(
base_dir / "vectors/cryptography_vectors/__about__.py",
"__version__",
new_version,
)
if Version(new_version).is_prerelease:
replace_pattern(
base_dir / "pyproject.toml",
r'"cryptography_vectors(==.*?)?"',
'"cryptography_vectors"',
)
else:
replace_pattern(
base_dir / "pyproject.toml",
r'"cryptography_vectors(==.*?)?"',
f'"cryptography_vectors=={new_version}"',
)
bump_rust_versions(base_dir, new_version)
if __name__ == "__main__":
cli()