Skip to content

Commit 551cd8b

Browse files
authored
Stop a build on the first failing command. (#104)
This avoid the following commands to fail too. This way the root cause is easier to spot, as it's the only error being logged.
1 parent 0fffa54 commit 551cd8b

File tree

1 file changed

+61
-65
lines changed

1 file changed

+61
-65
lines changed

build_docs.py

Lines changed: 61 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -150,34 +150,29 @@ def title(self):
150150
}
151151

152152

153-
def shell_out(cmd, shell=False):
154-
cmdstring = cmd if shell else shlex.join(cmd)
155-
logging.debug("Running command: %s", cmdstring)
156-
try:
157-
output = subprocess.check_output(
158-
cmd,
159-
shell=shell,
160-
stdin=subprocess.PIPE,
161-
stderr=subprocess.STDOUT,
162-
encoding="utf-8",
163-
errors="backslashreplace",
153+
def run(cmd) -> subprocess.CompletedProcess:
154+
"""Like subprocess.run, with logging before and after the command execution."""
155+
cmdstring = shlex.join(cmd)
156+
logging.debug("Run: %r", cmdstring)
157+
result = subprocess.run(
158+
cmd,
159+
stdin=subprocess.PIPE,
160+
stderr=subprocess.STDOUT,
161+
stdout=subprocess.PIPE,
162+
encoding="utf-8",
163+
errors="backslashreplace",
164+
)
165+
if result.returncode:
166+
# Log last 20 lines, those are likely the interesting ones.
167+
logging.error(
168+
"Run KO: %r:\n%s",
169+
cmdstring,
170+
indent("\n".join(result.stdout.split("\n")[-20:]), " "),
164171
)
165-
if output:
166-
logging.debug(
167-
"Command executed successfully: %s\n%s",
168-
cmdstring,
169-
indent(output, " "),
170-
)
171-
return output
172-
except subprocess.CalledProcessError as e:
173-
if sentry_sdk:
174-
with sentry_sdk.push_scope() as scope:
175-
scope.fingerprint = ["{{ default }}", str(cmd)]
176-
sentry_sdk.capture_exception(e)
177-
if e.output:
178-
logging.error("Command %s failed:\n%s", cmdstring, indent(e.output, " "))
179-
else:
180-
logging.error("Command %s failed.", cmdstring)
172+
else:
173+
logging.debug("Run OK: %r", cmdstring)
174+
result.check_returncode()
175+
return result
181176

182177

183178
def changed_files(left, right):
@@ -207,20 +202,18 @@ def git_clone(repository, directory, branch=None):
207202
try:
208203
if not os.path.isdir(os.path.join(directory, ".git")):
209204
raise AssertionError("Not a git repository.")
210-
shell_out(["git", "-C", directory, "fetch"])
205+
run(["git", "-C", directory, "fetch"])
211206
if branch:
212-
shell_out(["git", "-C", directory, "checkout", branch])
213-
shell_out(["git", "-C", directory, "reset", "--hard", "origin/" + branch])
207+
run(["git", "-C", directory, "checkout", branch])
208+
run(["git", "-C", directory, "reset", "--hard", "origin/" + branch])
214209
except (subprocess.CalledProcessError, AssertionError):
215210
if os.path.exists(directory):
216211
shutil.rmtree(directory)
217212
logging.info("Cloning %s into %s", repository, directory)
218213
os.makedirs(directory, mode=0o775)
219-
shell_out(
220-
["git", "clone", "--depth=1", "--no-single-branch", repository, directory]
221-
)
214+
run(["git", "clone", "--depth=1", "--no-single-branch", repository, directory])
222215
if branch:
223-
shell_out(["git", "-C", directory, "checkout", branch])
216+
run(["git", "-C", directory, "checkout", branch])
224217

225218

226219
def version_to_tuple(version):
@@ -271,7 +264,7 @@ def translation_branch(locale_repo, locale_clone_dir, needed_version):
271264
returns the name of the nearest existing branch.
272265
"""
273266
git_clone(locale_repo, locale_clone_dir)
274-
remote_branches = shell_out(["git", "-C", locale_clone_dir, "branch", "-r"])
267+
remote_branches = run(["git", "-C", locale_clone_dir, "branch", "-r"]).stdout
275268
branches = []
276269
for branch in remote_branches.split("\n"):
277270
if re.match(r".*/[0-9]+\.[0-9]+$", branch):
@@ -423,7 +416,7 @@ def build_one(
423416
sphinxbuild = os.path.join(venv, "bin/sphinx-build")
424417
blurb = os.path.join(venv, "bin/blurb")
425418
# Disable cpython switchers, we handle them now:
426-
shell_out(
419+
run(
427420
[
428421
"sed",
429422
"-i",
@@ -434,7 +427,7 @@ def build_one(
434427
setup_indexsidebar(
435428
os.path.join(checkout, "Doc", "tools", "templates", "indexsidebar.html")
436429
)
437-
shell_out(
430+
run(
438431
[
439432
"make",
440433
"-C",
@@ -448,7 +441,7 @@ def build_one(
448441
maketarget,
449442
]
450443
)
451-
shell_out(["chgrp", "-R", group, log_directory])
444+
run(["chgrp", "-R", group, log_directory])
452445
setup_switchers(os.path.join(checkout, "Doc", "build", "html"))
453446
logging.info("Build done for version: %s, language: %s", version.name, language.tag)
454447

@@ -464,15 +457,18 @@ def build_venv(build_root, version, theme):
464457
"sphinx=={}".format(version.sphinx_version),
465458
]
466459
venv_path = os.path.join(build_root, "venv-with-sphinx-" + version.sphinx_version)
467-
shell_out(["python3", "-m", "venv", venv_path])
468-
shell_out(
460+
run(["python3", "-m", "venv", venv_path])
461+
run(
469462
[os.path.join(venv_path, "bin", "python"), "-m", "pip", "install"]
470463
+ requirements
471464
)
472465
return venv_path
473466

474467

475468
def build_robots_txt(www_root, group, skip_cache_invalidation):
469+
if not Path(www_root).exists():
470+
logging.info("Skipping robots.txt generation (www root does not even exists).")
471+
return
476472
robots_file = os.path.join(www_root, "robots.txt")
477473
with open(HERE / "templates" / "robots.txt") as robots_txt_template_file:
478474
with open(robots_file, "w") as robots_txt_file:
@@ -481,12 +477,15 @@ def build_robots_txt(www_root, group, skip_cache_invalidation):
481477
template.render(languages=LANGUAGES, versions=VERSIONS) + "\n"
482478
)
483479
os.chmod(robots_file, 0o775)
484-
shell_out(["chgrp", group, robots_file])
480+
run(["chgrp", group, robots_file])
485481
if not skip_cache_invalidation:
486-
shell_out(["curl", "-XPURGE", "https://docs.python.org/robots.txt"])
482+
run(["curl", "-XPURGE", "https://docs.python.org/robots.txt"])
487483

488484

489485
def build_sitemap(www_root):
486+
if not Path(www_root).exists():
487+
logging.info("Skipping sitemap generation (www root does not even exists).")
488+
return
490489
with open(HERE / "templates" / "sitemap.xml") as sitemap_template_file:
491490
with open(os.path.join(www_root, "sitemap.xml"), "w") as sitemap_file:
492491
template = jinja2.Template(sitemap_template_file.read())
@@ -518,7 +517,7 @@ def copy_build_to_webroot(
518517
language_dir = os.path.join(www_root, language.tag)
519518
os.makedirs(language_dir, exist_ok=True)
520519
try:
521-
shell_out(["chgrp", "-R", group, language_dir])
520+
run(["chgrp", "-R", group, language_dir])
522521
except subprocess.CalledProcessError as err:
523522
logging.warning("Can't change group of %s: %s", language_dir, str(err))
524523
os.chmod(language_dir, 0o775)
@@ -530,15 +529,15 @@ def copy_build_to_webroot(
530529
except PermissionError as err:
531530
logging.warning("Can't change mod of %s: %s", target, str(err))
532531
try:
533-
shell_out(["chgrp", "-R", group, target])
532+
run(["chgrp", "-R", group, target])
534533
except subprocess.CalledProcessError as err:
535534
logging.warning("Can't change group of %s: %s", target, str(err))
536535

537536
changed = changed_files(os.path.join(checkout, "Doc/build/html"), target)
538537
logging.info("Copying HTML files to %s", target)
539-
shell_out(["chown", "-R", ":" + group, os.path.join(checkout, "Doc/build/html/")])
540-
shell_out(["chmod", "-R", "o+r", os.path.join(checkout, "Doc/build/html/")])
541-
shell_out(
538+
run(["chown", "-R", ":" + group, os.path.join(checkout, "Doc/build/html/")])
539+
run(["chmod", "-R", "o+r", os.path.join(checkout, "Doc/build/html/")])
540+
run(
542541
[
543542
"find",
544543
os.path.join(checkout, "Doc/build/html/"),
@@ -552,9 +551,9 @@ def copy_build_to_webroot(
552551
]
553552
)
554553
if quick:
555-
shell_out(["rsync", "-a", os.path.join(checkout, "Doc/build/html/"), target])
554+
run(["rsync", "-a", os.path.join(checkout, "Doc/build/html/"), target])
556555
else:
557-
shell_out(
556+
run(
558557
[
559558
"rsync",
560559
"-a",
@@ -567,18 +566,17 @@ def copy_build_to_webroot(
567566
)
568567
if not quick:
569568
logging.debug("Copying dist files")
570-
shell_out(["chown", "-R", ":" + group, os.path.join(checkout, "Doc/dist/")])
571-
shell_out(
572-
["chmod", "-R", "o+r", os.path.join(checkout, os.path.join("Doc/dist/"))]
573-
)
574-
shell_out(["mkdir", "-m", "o+rx", "-p", os.path.join(target, "archives")])
575-
shell_out(["chown", ":" + group, os.path.join(target, "archives")])
576-
shell_out(
577-
"cp -a {src} {dst}".format(
578-
src=os.path.join(checkout, "Doc/dist/*"),
579-
dst=os.path.join(target, "archives"),
580-
),
581-
shell=True,
569+
run(["chown", "-R", ":" + group, os.path.join(checkout, "Doc/dist/")])
570+
run(["chmod", "-R", "o+r", os.path.join(checkout, os.path.join("Doc/dist/"))])
571+
run(["mkdir", "-m", "o+rx", "-p", os.path.join(target, "archives")])
572+
run(["chown", ":" + group, os.path.join(target, "archives")])
573+
run(
574+
[
575+
"cp",
576+
"-a",
577+
*[str(dist) for dist in (Path(checkout) / "Doc" / "dist").glob("*")],
578+
os.path.join(target, "archives"),
579+
]
582580
)
583581
changed.append("archives/")
584582
for fn in os.listdir(os.path.join(target, "archives")):
@@ -587,16 +585,14 @@ def copy_build_to_webroot(
587585
logging.info("%s files changed", len(changed))
588586
if changed and not skip_cache_invalidation:
589587
targets_dir = www_root
590-
prefixes = shell_out(["find", "-L", targets_dir, "-samefile", target])
588+
prefixes = run(["find", "-L", targets_dir, "-samefile", target]).stdout
591589
prefixes = prefixes.replace(targets_dir + "/", "")
592590
prefixes = [prefix + "/" for prefix in prefixes.split("\n") if prefix]
593591
to_purge = prefixes[:]
594592
for prefix in prefixes:
595593
to_purge.extend(prefix + p for p in changed)
596594
logging.info("Running CDN purge")
597-
shell_out(
598-
["curl", "-XPURGE", "https://docs.python.org/{%s}" % ",".join(to_purge)]
599-
)
595+
run(["curl", "-XPURGE", "https://docs.python.org/{%s}" % ",".join(to_purge)])
600596
logging.info(
601597
"Publishing done for version: %s, language: %s", version.name, language.tag
602598
)

0 commit comments

Comments
 (0)