11#!/usr/bin/env python3
2- """
3- Standard-library regression fixtures, executed by GitHub's package-check job.
2+ """Standard-library regression fixtures, executed by GitHub's package-check job.
43
54These fixtures do not bootstrap WordPress or replace workflow-generated PHP tests.
65All mutation is confined to a temporary fixture repository on the runner.
76Processes use system tools in /usr/bin on the Ubuntu runner/WSL target; PATH
8- overrides select only the intentional curl/grep substitutes inside shell steps.
7+ overrides select only intentional command substitutes inside extracted shell steps.
98"""
109
1110from __future__ import annotations
@@ -47,6 +46,16 @@ def workflow_step(filename: str, name: str) -> str:
4746 return textwrap .dedent (section .split (" run: |\n " , 1 )[1 ])
4847
4948
49+ def successful_quality_jobs () -> list [dict [str , str ]]:
50+ """Build completed job fixtures from the compatibility workflow's names."""
51+ workflow = (WORKFLOWS / "wp-compatibility-test.yml" ).read_text ()
52+ names = [name for name in re .findall (r"^ name: (.+)$" , workflow , re .M ) if "${{" not in name ]
53+ names += [f"Test WordPress { wp } with PHP { php } (highest deps)"
54+ for php in ("8.2" , "8.3" , "8.4" , "8.5" ) for wp in ("6.8" , "latest" , "nightly" )]
55+ names .append ("Test WordPress latest with PHP 8.2 (lowest deps)" )
56+ return [{"name" : name , "status" : "completed" , "conclusion" : "success" } for name in names ]
57+
58+
5059class AutomationTests (unittest .TestCase ):
5160 def setUp (self ):
5261 self .temporary = tempfile .TemporaryDirectory (prefix = "es-optimizer-automation-" )
@@ -160,18 +169,16 @@ def accepts_run(runs):
160169 (self .root / "bin/jq" ).chmod (0o700 )
161170 with patch .dict (os .environ , PATH = f"{ self .root / 'bin' } :{ os .environ ['PATH' ]} " ):
162171 self .assertTrue (accepts_run ([run ]))
172+ self .assertTrue (accepts_run ([dict (run , event = "workflow_dispatch" )]))
163173 self .assertFalse (accepts_run ([]))
164174 for changes in ({"head_sha" : "other" }, {"event" : "pull_request" },
165175 {"head_branch" : "other" }, {"head_repository" : {"full_name" : "fork/repo" }},
166- {"conclusion" : "failure" }, {"conclusion" : "cancelled" }, {"status" : "in_progress" }):
176+ {"conclusion" : "failure" }, {"conclusion" : "cancelled" },
177+ {"status" : "queued" }, {"status" : "in_progress" }):
167178 self .assertFalse (accepts_run ([dict (run , ** changes )]))
168179 self .assertFalse (accepts_run ([run , dict (run , id = 2 , conclusion = "failure" )]))
169- workflow = (WORKFLOWS / "wp-compatibility-test.yml" ).read_text ()
170- names = [name for name in re .findall (r"^ name: (.+)$" , workflow , re .M ) if "${{" not in name ]
171- names += [f"Test WordPress { wp } with PHP { php } (highest deps)"
172- for php in ("8.2" , "8.3" , "8.4" , "8.5" ) for wp in ("6.8" , "latest" , "nightly" )]
173- names .append ("Test WordPress latest with PHP 8.2 (lowest deps)" )
174- jobs = [{"name" : name , "status" : "completed" , "conclusion" : "success" } for name in names ]
180+ self .assertFalse (accepts_run ([run , dict (run , id = 2 , status = "in_progress" , conclusion = None )]))
181+ jobs = successful_quality_jobs ()
175182
176183 def accepts_jobs (records ):
177184 # Repository-owned jq program; job records remain separate JSON data.
@@ -191,6 +198,66 @@ def accepts_jobs(records):
191198 self .assertFalse (accepts_jobs (changed ))
192199 self .assertFalse (accepts_jobs (jobs + [jobs [0 ]]))
193200
201+ def test_release_gate_uses_tested_commit_and_explains_rejections (self ):
202+ script = workflow_step ("release.yml" , "Require successful quality checks for this commit" )
203+ self .write ("bin/gh" , '#!/bin/sh\n printf "%s\\ n" "$@" >> "$FIXTURE_GH_ARGS"\n '
204+ 'case "$*" in\n '
205+ ' *actions/workflows/wp-compatibility-test.yml/runs*) cat "$FIXTURE_RUNS" ;;\n '
206+ ' *actions/runs/1/jobs*) cat "$FIXTURE_JOBS" ;;\n '
207+ ' *) exit 92 ;;\n esac\n ' )
208+ self .write ("bin/git" , '#!/bin/sh\n [ "$1" = rev-parse ] || exit 92\n '
209+ '[ -n "$FIXTURE_TAG_SHA" ] || exit 1\n printf "%s\\ n" "$FIXTURE_TAG_SHA"\n ' )
210+ for command in ("gh" , "git" ):
211+ (self .root / "bin" / command ).chmod (0o700 )
212+ run = {"id" : 1 , "head_sha" : "tested-commit" , "head_branch" : "main" ,
213+ "head_repository" : {"full_name" : "fixture/repo" },
214+ "event" : "push" , "status" : "completed" , "conclusion" : "success" }
215+ jobs = successful_quality_jobs ()
216+ cases = (
217+ ("ready" , [run ], jobs , "" , True ),
218+ ("missing" , [], jobs , "" , False ),
219+ ("queued" , [dict (run , status = "queued" , conclusion = None )], jobs , "" , False ),
220+ ("running" , [dict (run , status = "in_progress" , conclusion = None )], jobs , "" , False ),
221+ ("failed" , [dict (run , conclusion = "failure" )], jobs , "" , False ),
222+ ("missing-job" , [run ], jobs [:- 1 ], "" , False ),
223+ ("matching-tag" , [run ], jobs , "tested-commit" , True ),
224+ ("wrong-tag" , [run ], jobs , "untested-tip" , False ),
225+ )
226+ for label , runs , records , tag_sha , accepted in cases :
227+ with self .subTest (case = label ):
228+ self .write ("fixture-runs.json" , json .dumps ({"workflow_runs" : runs }))
229+ self .write ("fixture-jobs.json" , json .dumps ([{"jobs" : records }]))
230+ self .write ("gh-args" , "" )
231+ self .write ("step-summary" , "" )
232+ env = dict (os .environ , PATH = f"{ self .root / 'bin' } :{ os .environ ['PATH' ]} " ,
233+ GITHUB_REPOSITORY = "fixture/repo" , VERSION = "1.2.3" ,
234+ GITHUB_SHA = "untested-tip" , GITHUB_REF_NAME = "default-branch" ,
235+ RELEASE_SHA = "tested-commit" , RELEASE_BRANCH = "main" ,
236+ GITHUB_SERVER_URL = "https://github.invalid" , RUNNER_TEMP = str (self .root ),
237+ GITHUB_STEP_SUMMARY = str (self .root / "step-summary" ),
238+ FIXTURE_RUNS = str (self .root / "fixture-runs.json" ),
239+ FIXTURE_JOBS = str (self .root / "fixture-jobs.json" ),
240+ FIXTURE_GH_ARGS = str (self .root / "gh-args" ), FIXTURE_TAG_SHA = tag_sha )
241+ # Local command substitutes need no inherited GitHub credentials.
242+ env .pop ("GH_TOKEN" , None )
243+ env .pop ("GITHUB_TOKEN" , None )
244+ # Fixed repository-owned shell step; gh/git are local fixture substitutes.
245+ result = subprocess .run ( # nosec B603
246+ ["/usr/bin/bash" , "-e" , "-o" , "pipefail" , "-c" , script ],
247+ env = env , capture_output = True , text = True
248+ )
249+ self .assertEqual (accepted , result .returncode == 0 , result .stdout + result .stderr )
250+ arguments = (self .root / "gh-args" ).read_text ()
251+ self .assertIn ("head_sha=tested-commit\n " , arguments )
252+ self .assertIn ("branch=main\n " , arguments )
253+ self .assertNotIn ("untested-tip" , arguments )
254+ summary = (self .root / "step-summary" ).read_text ()
255+ if accepted :
256+ self .assertIn ("https://github.invalid/fixture/repo/actions/runs/1" , summary )
257+ else :
258+ self .assertIn ("::error::" , result .stdout )
259+ self .assertEqual ("" , summary )
260+
194261 def test_release_lookup_fails_closed_on_http_and_transport_errors (self ):
195262 script = workflow_step ("release.yml" , "Check if release exists" )
196263 self .write ("bin/curl" , '#!/bin/sh\n printf "%s" "$FIXTURE_HTTP_STATUS"\n exit "$FIXTURE_CURL_EXIT"\n ' )
0 commit comments