@@ -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
183178def 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
226219def 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
475468def 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
489485def 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