-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathcheck_release.py
More file actions
executable file
·133 lines (118 loc) · 5.5 KB
/
check_release.py
File metadata and controls
executable file
·133 lines (118 loc) · 5.5 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
#!/usr/bin/env python
# WARNING: DO NOT EDIT!
#
# This file was generated by plugin_template, and is managed by it. Please use
# './plugin-template --github pulp_python' to update this file.
#
# For more info visit https://github.com/pulp/plugin_template
import argparse
import re
import os
import yaml
from tempfile import TemporaryDirectory
from packaging.version import Version
from git import Repo
UPSTREAM_REMOTE = "https://github.com/pulp/pulp_python.git"
DEFAULT_BRANCH = "main"
RELEASE_BRANCH_REGEX = r"^([0-9]+)\.([0-9]+)$"
Y_CHANGELOG_EXTS = [".feature", ".removal", ".deprecation"]
Z_CHANGELOG_EXTS = [".bugfix", ".doc", ".misc"]
def main():
"""Check which branches need a release."""
parser = argparse.ArgumentParser()
parser.add_argument(
"--branches",
default="supported",
help="A comma separated list of branches to check for releases. Can also use keyword: "
"'supported'. Defaults to 'supported', see `supported_release_branches` in "
"`plugin_template.yml`.",
)
opts = parser.parse_args()
with TemporaryDirectory() as d:
# Clone from upstream to ensure we have updated branches & main
repo = Repo.clone_from(UPSTREAM_REMOTE, d, filter="blob:none")
heads = [h.split("/")[-1] for h in repo.git.ls_remote("--heads").split("\n")]
available_branches = [h for h in heads if re.search(RELEASE_BRANCH_REGEX, h)]
available_branches.sort(key=lambda ver: Version(ver))
available_branches.append(DEFAULT_BRANCH)
branches = opts.branches
if branches == "supported":
with open(f"{d}/template_config.yml", mode="r") as f:
tc = yaml.safe_load(f)
branches = set(tc["supported_release_branches"])
latest_release_branch = tc["latest_release_branch"]
if latest_release_branch is not None:
branches.add(latest_release_branch)
branches.add(DEFAULT_BRANCH)
else:
branches = set(branches.split(","))
if diff := branches - set(available_branches):
print(f"Supplied branches contains non-existent branches! {diff}")
exit(1)
print(f"Checking for releases on branches: {branches}")
releases = []
for branch in branches:
if branch != DEFAULT_BRANCH:
# Check if a Z release is needed
reasons = []
changes = repo.git.ls_tree("-r", "--name-only", f"origin/{branch}", "CHANGES/")
z_changelog = False
for change in changes.split("\n"):
# Check each changelog file to make sure everything checks out
_, ext = os.path.splitext(change)
if ext in Y_CHANGELOG_EXTS:
print(
f"Warning: A non-backported changelog ({change}) is present in the "
f"{branch} release branch!"
)
elif ext in Z_CHANGELOG_EXTS:
z_changelog = True
if z_changelog:
reasons.append("Backports")
last_tag = repo.git.describe("--tags", "--abbrev=0", f"origin/{branch}")
req_txt_diff = repo.git.diff(
f"{last_tag}", f"origin/{branch}", "--name-only", "--", "requirements.txt"
)
if req_txt_diff:
reasons.append("requirements.txt")
pyproject_diff = repo.git.diff(
f"{last_tag}", f"origin/{branch}", "--name-only", "--", "pyproject.toml"
)
if pyproject_diff:
reasons.append(
"pyproject.toml changed (PLEASE check if dependencies are affected."
)
if reasons:
curr_version = Version(last_tag)
assert curr_version.base_version.startswith(
branch
), "Current-version has to belong to the current branch!"
next_version = Version(f"{branch}.{curr_version.micro + 1}")
print(
f"A Z-release is needed for {branch}, "
f"Prev: {last_tag}, "
f"Next: {next_version.base_version}, "
f"Reason: {','.join(reasons)}"
)
releases.append(next_version)
else:
# Check if a Y release is needed
changes = repo.git.ls_tree("-r", "--name-only", DEFAULT_BRANCH, "CHANGES/")
for change in changes.split("\n"):
_, ext = os.path.splitext(change)
if ext in Y_CHANGELOG_EXTS:
# We don't put Y release bumps in the commit message, check file instead
# The 'current_version' is always the next version to release
next_version = repo.git.grep(
"current_version", DEFAULT_BRANCH, "--", ".bumpversion.cfg"
).split("=")[-1]
next_version = Version(next_version)
print(
f"A new Y-release is needed! New Version: {next_version.base_version}"
)
releases.append(next_version)
break
if len(releases) == 0:
print("No new releases to perform.")
if __name__ == "__main__":
main()