| # 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() |