1616from pathlib import Path
1717from typing import Any
1818
19- from test_site import TEST_SITE , fixture_config
19+ from test_site import TEST_SITE , fixture_config , run_hugo_process
2020
2121
2222ROOT = Path (__file__ ).resolve ().parents [1 ]
@@ -201,7 +201,7 @@ def validate_external_mount_actions() -> None:
201201
202202 with tempfile .TemporaryDirectory (prefix = "oink-external-actions-" ) as temp :
203203 public = Path (temp ) / "public"
204- result = subprocess . run (
204+ result = run_hugo_process (
205205 [
206206 "hugo" ,
207207 "--source" ,
@@ -382,7 +382,15 @@ def validate_manifest(
382382 require (commands ["print_now" ]["title" ] == "立即打印" , "out-of-order ZH merge failed" )
383383
384384
385- def run_invalid_build (helper : Any , workspace : Path , name : str , command_yaml : str , expected : str ) -> None :
385+ def run_invalid_build (
386+ helper : Any ,
387+ workspace : Path ,
388+ name : str ,
389+ command_yaml : str ,
390+ expected : str ,
391+ * ,
392+ strict_canary : bool ,
393+ ) -> None :
386394 site = workspace / f"invalid-{ name } "
387395 output = workspace / f"invalid-public-{ name } "
388396 shutil .copytree (helper .SITE_FIXTURE_PATH , site )
@@ -396,7 +404,7 @@ def run_invalid_build(helper: Any, workspace: Path, name: str, command_yaml: str
396404 )
397405 config = config .replace (" weight: 1\n zh:\n " , " weight: 1\n " + addition + " zh:\n " )
398406 (site / "hugo.yaml" ).write_text (config , encoding = "utf-8" )
399- result = subprocess . run (
407+ result = run_hugo_process (
400408 [
401409 "hugo" ,
402410 "--source" ,
@@ -422,6 +430,10 @@ def run_invalid_build(helper: Any, workspace: Path, name: str, command_yaml: str
422430 require (expected in result .stdout , f"invalid { name } build missed { expected !r} :\n { result .stdout } " )
423431 require (result .returncode == 0 ,
424432 f"invalid { name } command stopped the build instead of warning:\n { result .stdout } " )
433+ require (
434+ (output / "en/docs/guides/tutorial/index.html" ).is_file (),
435+ f"invalid { name } command emitted no safe page output" ,
436+ )
425437 if "unsafe URL" in expected :
426438 # The dropped URL must not reach any rendered page -- that is the
427439 # whole point of refusing it.
@@ -431,22 +443,23 @@ def run_invalid_build(helper: Any, workspace: Path, name: str, command_yaml: str
431443 if path .is_file () and "javascript:alert" in path .read_text (errors = "ignore" )
432444 ]
433445 require (not leaked , f"invalid { name } command leaked its unsafe URL into { leaked [:3 ]} " )
434- strict = subprocess .run (
435- [
436- "hugo" , "--source" , str (site ), "--themesDir" , str (ROOT .parent ),
437- "--destination" , str (output ) + "-strict" ,
438- "--cacheDir" , str (workspace / "cache-invalid-strict" ),
439- "--panicOnWarning" ,
440- ],
441- cwd = site ,
442- env = {** os .environ , "HUGO_ENVIRONMENT" : "development" },
443- text = True , stdout = subprocess .PIPE , stderr = subprocess .STDOUT , check = False ,
444- )
445- require (strict .returncode != 0 , f"invalid { name } command survived --panicOnWarning" )
446+ if strict_canary :
447+ strict = run_hugo_process (
448+ [
449+ "hugo" , "--source" , str (site ), "--themesDir" , str (ROOT .parent ),
450+ "--destination" , str (output ) + "-strict" ,
451+ "--cacheDir" , str (workspace / "cache-invalid-strict" ),
452+ "--panicOnWarning" ,
453+ ],
454+ cwd = site ,
455+ env = {** os .environ , "HUGO_ENVIRONMENT" : "development" },
456+ text = True , stdout = subprocess .PIPE , stderr = subprocess .STDOUT , check = False ,
457+ )
458+ require (strict .returncode != 0 , f"invalid { name } command survived --panicOnWarning" )
446459
447460
448461def strict_fails (site : Path , workspace : Path , name : str ) -> bool :
449- strict = subprocess . run (
462+ strict = run_hugo_process (
450463 ["hugo" , "--source" , str (site ), "--themesDir" , str (ROOT .parent ),
451464 "--destination" , str (workspace / f"strict-{ name } " ),
452465 "--cacheDir" , str (workspace / f"cache-strict-{ name } " ), "--panicOnWarning" ],
@@ -818,8 +831,25 @@ def main() -> int:
818831 'field "keywords" must be an array of strings' ,
819832 ),
820833 }
834+ strict_canaries = {
835+ "unknown" , # built-in action lookup
836+ "both" , # action/URL exclusivity
837+ "callback" , # unsupported fields
838+ "javascript" , # URL policy
839+ "duplicate" , # command identity
840+ "reserved" , # built-in identity
841+ "numeric-title" , # scalar field types
842+ "scalar-keywords" , # list field types
843+ }
821844 for name , (yaml , expected ) in invalid_cases .items ():
822- run_invalid_build (helper , workspace , name , yaml , expected )
845+ run_invalid_build (
846+ helper ,
847+ workspace ,
848+ name ,
849+ yaml ,
850+ expected ,
851+ strict_canary = name in strict_canaries ,
852+ )
823853
824854 validate_custom_url_policy (helper , workspace )
825855
0 commit comments