6
6
import tomllib
7
7
import yaml
8
8
from pathlib import Path
9
- from tempfile import TemporaryDirectory
10
9
from packaging .version import Version
11
10
from git import Repo
12
11
@@ -25,6 +24,12 @@ def options():
25
24
"'supported'. Defaults to 'supported', see `supported_release_branches` in "
26
25
"`plugin_template.yml`." ,
27
26
)
27
+ parser .add_argument (
28
+ "--no-fetch" ,
29
+ default = False ,
30
+ action = "store_true" ,
31
+ help = "Don't fetch remote. Run faster at the expense of maybe being outdated." ,
32
+ )
28
33
return parser .parse_args ()
29
34
30
35
@@ -70,97 +75,100 @@ def check_pyproject_dependencies(repo, from_commit, to_commit):
70
75
71
76
72
77
def main (options , template_config ):
73
- with TemporaryDirectory () as d :
74
- # Clone from upstream to ensure we have updated branches & main
75
- GITHUB_ORG = template_config ["github_org" ]
76
- PLUGIN_NAME = template_config ["plugin_name" ]
77
- UPSTREAM_REMOTE = f"https://github.com/{ GITHUB_ORG } /{ PLUGIN_NAME } .git"
78
- DEFAULT_BRANCH = template_config ["plugin_default_branch" ]
79
-
80
- repo = Repo .clone_from (UPSTREAM_REMOTE , d , filter = "blob:none" )
81
- heads = [h .split ("/" )[- 1 ] for h in repo .git .ls_remote ("--heads" ).split ("\n " )]
82
- available_branches = [h for h in heads if re .search (RELEASE_BRANCH_REGEX , h )]
83
- available_branches .sort (key = lambda ver : Version (ver ))
84
- available_branches .append (DEFAULT_BRANCH )
85
-
86
- branches = options .branches
87
- if branches == "supported" :
88
- with open (f"{ d } /template_config.yml" , mode = "r" ) as f :
89
- tc = yaml .safe_load (f )
90
- branches = set (tc ["supported_release_branches" ])
91
- latest_release_branch = tc ["latest_release_branch" ]
92
- if latest_release_branch is not None :
93
- branches .add (latest_release_branch )
94
- branches .add (DEFAULT_BRANCH )
95
- else :
96
- branches = set (branches .split ("," ))
97
-
98
- if diff := branches - set (available_branches ):
99
- print (f"Supplied branches contains non-existent branches! { diff } " )
100
- exit (1 )
101
-
102
- print (f"Checking for releases on branches: { branches } " )
103
-
104
- releases = []
105
- for branch in branches :
106
- if branch != DEFAULT_BRANCH :
107
- # Check if a Z release is needed
108
- reasons = []
109
- changes = repo .git .ls_tree ("-r" , "--name-only" , f"origin/{ branch } " , "CHANGES/" )
110
- z_changelog = False
111
- for change in changes .split ("\n " ):
112
- # Check each changelog file to make sure everything checks out
113
- _ , ext = os .path .splitext (change )
114
- if ext in Y_CHANGELOG_EXTS :
115
- print (
116
- f"Warning: A non-backported changelog ({ change } ) is present in the "
117
- f"{ branch } release branch!"
118
- )
119
- elif ext in Z_CHANGELOG_EXTS :
120
- z_changelog = True
121
- if z_changelog :
122
- reasons .append ("Backports" )
123
-
124
- last_tag = repo .git .describe ("--tags" , "--abbrev=0" , f"origin/{ branch } " )
125
- req_txt_diff = repo .git .diff (
126
- f"{ last_tag } " , f"origin/{ branch } " , "--name-only" , "--" , "requirements.txt"
127
- )
128
- if req_txt_diff :
129
- reasons .append ("requirements.txt" )
130
- pyproject_diff = repo .git .diff (
131
- f"{ last_tag } " , f"origin/{ branch } " , "--name-only" , "--" , "pyproject.toml"
132
- )
133
- if pyproject_diff :
134
- reasons .extend (check_pyproject_dependencies (repo , last_tag , f"origin/{ branch } " ))
135
-
136
- if reasons :
137
- curr_version = Version (last_tag )
138
- assert curr_version .base_version .startswith (
139
- branch
140
- ), "Current-version has to belong to the current branch!"
141
- next_version = Version (f"{ branch } .{ curr_version .micro + 1 } " )
78
+ DEFAULT_BRANCH = template_config ["plugin_default_branch" ]
79
+
80
+ repo = Repo ()
81
+
82
+ upstream_default_branch = next (
83
+ (branch for branch in repo .branches if branch .name == DEFAULT_BRANCH )
84
+ ).tracking_branch ()
85
+ remote = upstream_default_branch .remote_name
86
+ if not options .no_fetch :
87
+ repo .remote (remote ).fetch ()
88
+
89
+ # Warning: This will not work if branch names contain "/" but we don't really care here.
90
+ heads = [h .split ("/" )[- 1 ] for h in repo .git .branch ("--remote" ).split ("\n " )]
91
+ available_branches = [h for h in heads if re .search (RELEASE_BRANCH_REGEX , h )]
92
+ available_branches .sort (key = lambda ver : Version (ver ))
93
+ available_branches .append (DEFAULT_BRANCH )
94
+
95
+ branches = options .branches
96
+ if branches == "supported" :
97
+ tc = yaml .safe_load (repo .git .show (f"{ upstream_default_branch } :template_config.yml" ))
98
+ branches = set (tc ["supported_release_branches" ])
99
+ latest_release_branch = tc ["latest_release_branch" ]
100
+ if latest_release_branch is not None :
101
+ branches .add (latest_release_branch )
102
+ branches .add (DEFAULT_BRANCH )
103
+ else :
104
+ branches = set (branches .split ("," ))
105
+
106
+ if diff := branches - set (available_branches ):
107
+ print (f"Supplied branches contains non-existent branches! { diff } " )
108
+ exit (1 )
109
+
110
+ print (f"Checking for releases on branches: { branches } " )
111
+
112
+ releases = []
113
+ for branch in branches :
114
+ if branch != DEFAULT_BRANCH :
115
+ # Check if a Z release is needed
116
+ reasons = []
117
+ changes = repo .git .ls_tree ("-r" , "--name-only" , f"{ remote } /{ branch } " , "CHANGES/" )
118
+ z_changelog = False
119
+ for change in changes .split ("\n " ):
120
+ # Check each changelog file to make sure everything checks out
121
+ _ , ext = os .path .splitext (change )
122
+ if ext in Y_CHANGELOG_EXTS :
142
123
print (
143
- f"A Z-release is needed for { branch } , "
144
- f"Prev: { last_tag } , "
145
- f"Next: { next_version .base_version } , "
146
- f"Reason: { ',' .join (reasons )} "
124
+ f"Warning: A non-backported changelog ({ change } ) is present in the "
125
+ f"{ branch } release branch!"
147
126
)
127
+ elif ext in Z_CHANGELOG_EXTS :
128
+ z_changelog = True
129
+ if z_changelog :
130
+ reasons .append ("Backports" )
131
+
132
+ last_tag = repo .git .describe ("--tags" , "--abbrev=0" , f"{ remote } /{ branch } " )
133
+ req_txt_diff = repo .git .diff (
134
+ f"{ last_tag } " , f"{ remote } /{ branch } " , "--name-only" , "--" , "requirements.txt"
135
+ )
136
+ if req_txt_diff :
137
+ reasons .append ("requirements.txt" )
138
+ pyproject_diff = repo .git .diff (
139
+ f"{ last_tag } " , f"{ remote } /{ branch } " , "--name-only" , "--" , "pyproject.toml"
140
+ )
141
+ if pyproject_diff :
142
+ reasons .extend (check_pyproject_dependencies (repo , last_tag , f"{ remote } /{ branch } " ))
143
+
144
+ if reasons :
145
+ curr_version = Version (last_tag )
146
+ assert curr_version .base_version .startswith (
147
+ branch
148
+ ), "Current-version has to belong to the current branch!"
149
+ next_version = Version (f"{ branch } .{ curr_version .micro + 1 } " )
150
+ print (
151
+ f"A Z-release is needed for { branch } , "
152
+ f"Prev: { last_tag } , "
153
+ f"Next: { next_version .base_version } , "
154
+ f"Reason: { ',' .join (reasons )} "
155
+ )
156
+ releases .append (next_version )
157
+ else :
158
+ # Check if a Y release is needed
159
+ changes = repo .git .ls_tree ("-r" , "--name-only" , DEFAULT_BRANCH , "CHANGES/" )
160
+ for change in changes .split ("\n " ):
161
+ _ , ext = os .path .splitext (change )
162
+ if ext in Y_CHANGELOG_EXTS :
163
+ # We don't put Y release bumps in the commit message, check file instead.
164
+ # The 'current_version' is always the dev of the next version to release.
165
+ next_version = current_version (repo , DEFAULT_BRANCH ).base_version
166
+ print (f"A new Y-release is needed! New Version: { next_version } " )
148
167
releases .append (next_version )
149
- else :
150
- # Check if a Y release is needed
151
- changes = repo .git .ls_tree ("-r" , "--name-only" , DEFAULT_BRANCH , "CHANGES/" )
152
- for change in changes .split ("\n " ):
153
- _ , ext = os .path .splitext (change )
154
- if ext in Y_CHANGELOG_EXTS :
155
- # We don't put Y release bumps in the commit message, check file instead.
156
- # The 'current_version' is always the dev of the next version to release.
157
- next_version = current_version (repo , DEFAULT_BRANCH ).base_version
158
- print (f"A new Y-release is needed! New Version: { next_version } " )
159
- releases .append (next_version )
160
- break
161
-
162
- if len (releases ) == 0 :
163
- print ("No new releases to perform." )
168
+ break
169
+
170
+ if len (releases ) == 0 :
171
+ print ("No new releases to perform." )
164
172
165
173
166
174
if __name__ == "__main__" :
0 commit comments