|
4 | 4 | # The following comment should be removed at some point in the future.
|
5 | 5 | # mypy: disallow-untyped-defs=False
|
6 | 6 |
|
7 |
| -import io |
| 7 | +import glob |
8 | 8 | import os
|
9 | 9 | import shutil
|
10 |
| -import subprocess |
| 10 | +import sys |
11 | 11 |
|
12 | 12 | import nox
|
13 | 13 |
|
| 14 | +sys.path.append(".") |
| 15 | +from tools.automation import release # isort:skip # noqa |
| 16 | +sys.path.pop() |
| 17 | + |
14 | 18 | nox.options.reuse_existing_virtualenvs = True
|
15 | 19 | nox.options.sessions = ["lint"]
|
16 | 20 |
|
|
27 | 31 | VERSION_FILE = "src/pip/__init__.py"
|
28 | 32 |
|
29 | 33 |
|
30 |
| -def get_author_list(): |
31 |
| - """Get the list of authors from Git commits. |
32 |
| - """ |
33 |
| - # subprocess because session.run doesn't give us stdout |
34 |
| - result = subprocess.run( |
35 |
| - ["git", "log", "--use-mailmap", "--format=%aN <%aE>"], |
36 |
| - capture_output=True, |
37 |
| - encoding="utf-8", |
38 |
| - ) |
39 |
| - |
40 |
| - # Create a unique list. |
41 |
| - authors = [] |
42 |
| - seen_authors = set() |
43 |
| - for author in result.stdout.splitlines(): |
44 |
| - author = author.strip() |
45 |
| - if author.lower() not in seen_authors: |
46 |
| - seen_authors.add(author.lower()) |
47 |
| - authors.append(author) |
48 |
| - |
49 |
| - # Sort our list of Authors by their case insensitive name |
50 |
| - return sorted(authors, key=lambda x: x.lower()) |
51 |
| - |
52 |
| - |
53 | 34 | def run_with_protected_pip(session, *arguments):
|
54 | 35 | """Do a session.run("pip", *arguments), using a "protected" pip.
|
55 | 36 |
|
@@ -81,11 +62,6 @@ def should_update_common_wheels():
|
81 | 62 | return need_to_repopulate
|
82 | 63 |
|
83 | 64 |
|
84 |
| -def update_version_file(new_version): |
85 |
| - with open(VERSION_FILE, "w", encoding="utf-8") as f: |
86 |
| - f.write('__version__ = "{}"\n'.format(new_version)) |
87 |
| - |
88 |
| - |
89 | 65 | # -----------------------------------------------------------------------------
|
90 | 66 | # Development Commands
|
91 | 67 | # These are currently prototypes to evaluate whether we want to switch over
|
@@ -174,70 +150,62 @@ def lint(session):
|
174 | 150 | # -----------------------------------------------------------------------------
|
175 | 151 | # Release Commands
|
176 | 152 | # -----------------------------------------------------------------------------
|
177 |
| -@nox.session(python=False) |
178 |
| -def generate_authors(session): |
179 |
| - # Get our list of authors |
180 |
| - session.log("Collecting author names") |
181 |
| - authors = get_author_list() |
| 153 | +@nox.session(name="prepare-release") |
| 154 | +def prepare_release(session): |
| 155 | + version = release.get_version_from_arguments(session.posargs) |
| 156 | + if not version: |
| 157 | + session.error("Usage: nox -s prepare-release -- YY.N[.P]") |
| 158 | + |
| 159 | + session.log("# Ensure nothing is staged") |
| 160 | + if release.modified_files_in_git("--staged"): |
| 161 | + session.error("There are files staged in git") |
| 162 | + |
| 163 | + session.log(f"# Updating {AUTHORS_FILE}") |
| 164 | + release.generate_authors(AUTHORS_FILE) |
| 165 | + if release.modified_files_in_git(): |
| 166 | + release.commit_file( |
| 167 | + session, AUTHORS_FILE, message=f"Update {AUTHORS_FILE}", |
| 168 | + ) |
| 169 | + else: |
| 170 | + session.log(f"# No changes to {AUTHORS_FILE}") |
182 | 171 |
|
183 |
| - # Write our authors to the AUTHORS file |
184 |
| - session.log("Writing AUTHORS") |
185 |
| - with io.open(AUTHORS_FILE, "w", encoding="utf-8") as fp: |
186 |
| - fp.write(u"\n".join(authors)) |
187 |
| - fp.write(u"\n") |
| 172 | + session.log("# Generating NEWS") |
| 173 | + release.generate_news(session, version) |
188 | 174 |
|
| 175 | + session.log(f"# Bumping for release {version}") |
| 176 | + release.update_version_file(version, VERSION_FILE) |
| 177 | + release.commit_file(session, VERSION_FILE, message="Bump for release") |
189 | 178 |
|
190 |
| -@nox.session |
191 |
| -def generate_news(session): |
192 |
| - session.log("Generating NEWS") |
193 |
| - session.install("towncrier") |
| 179 | + session.log("# Tagging release") |
| 180 | + release.create_git_tag(session, version, message=f"Release {version}") |
194 | 181 |
|
195 |
| - # You can pass 2 possible arguments: --draft, --yes |
196 |
| - session.run("towncrier", *session.posargs) |
| 182 | + session.log("# Bumping for development") |
| 183 | + next_dev_version = release.get_next_development_version(version) |
| 184 | + release.update_version_file(next_dev_version, VERSION_FILE) |
| 185 | + release.commit_file(session, VERSION_FILE, message="Bump for development") |
197 | 186 |
|
198 | 187 |
|
199 |
| -@nox.session |
200 |
| -def release(session): |
201 |
| - assert len(session.posargs) == 1, "A version number is expected" |
202 |
| - new_version = session.posargs[0] |
203 |
| - parts = new_version.split('.') |
204 |
| - # Expect YY.N or YY.N.P |
205 |
| - assert 2 <= len(parts) <= 3, parts |
206 |
| - # Only integers |
207 |
| - parts = list(map(int, parts)) |
208 |
| - session.log("Generating commits for version {}".format(new_version)) |
209 |
| - |
210 |
| - session.log("Checking that nothing is staged") |
211 |
| - # Non-zero exit code means that something is already staged |
212 |
| - session.run("git", "diff", "--staged", "--exit-code", external=True) |
213 |
| - |
214 |
| - session.log(f"Updating {AUTHORS_FILE}") |
215 |
| - generate_authors(session) |
216 |
| - if subprocess.run(["git", "diff", "--exit-code"]).returncode: |
217 |
| - session.run("git", "add", AUTHORS_FILE, external=True) |
218 |
| - session.run( |
219 |
| - "git", "commit", "-m", f"Updating {AUTHORS_FILE}", |
220 |
| - external=True, |
221 |
| - ) |
222 |
| - else: |
223 |
| - session.log(f"No update needed for {AUTHORS_FILE}") |
| 188 | +@nox.session(name="build-release") |
| 189 | +def build_release(session): |
| 190 | + version = release.get_version_from_arguments(session.posargs) |
| 191 | + if not version: |
| 192 | + session.error("Usage: nox -s upload-release -- YY.N[.P]") |
224 | 193 |
|
225 |
| - session.log("Generating NEWS") |
226 |
| - session.install("towncrier") |
227 |
| - session.run("towncrier", "--yes", "--version", new_version) |
| 194 | + session.log("# Ensure no files in dist/") |
| 195 | + if release.have_files_in_folder("dist"): |
| 196 | + session.error("There are files in dist/. Remove them and try again") |
228 | 197 |
|
229 |
| - session.log("Updating version") |
230 |
| - update_version_file(new_version) |
231 |
| - session.run("git", "add", VERSION_FILE, external=True) |
232 |
| - session.run("git", "commit", "-m", f"Release {new_version}", external=True) |
| 198 | + session.log("# Install dependencies") |
| 199 | + session.install("setuptools", "wheel", "twine") |
233 | 200 |
|
234 |
| - session.log("Tagging release") |
235 |
| - session.run( |
236 |
| - "git", "tag", "-m", f"Release {new_version}", new_version, |
237 |
| - external=True, |
238 |
| - ) |
| 201 | + session.log("# Checkout the tag") |
| 202 | + session.run("git", "checkout", version, external=True, silent=True) |
| 203 | + |
| 204 | + session.log("# Build distributions") |
| 205 | + session.run("python", "setup.py", "sdist", "bdist_wheel", silent=True) |
| 206 | + |
| 207 | + session.log("# Verify distributions") |
| 208 | + session.run("twine", "check", *glob.glob("dist/*"), silent=True) |
239 | 209 |
|
240 |
| - next_dev_version = f"{parts[0]}.{parts[1] + 1}.dev0" |
241 |
| - update_version_file(next_dev_version) |
242 |
| - session.run("git", "add", VERSION_FILE, external=True) |
243 |
| - session.run("git", "commit", "-m", "Back to development", external=True) |
| 210 | + session.log("# Checkout the master branch") |
| 211 | + session.run("git", "checkout", "master", external=True, silent=True) |
0 commit comments