@@ -67,20 +67,37 @@ def history(tmp_path: Path, git_env: dict[str, str]):
6767 return runner , old_base , upstream
6868
6969
70+ def expression (value : str , context : dict [str , str ]) -> str :
71+ """Evaluate the workflow's `${{ a || b }}` env expressions over one event."""
72+ inner = value .removeprefix ("${{" ).removesuffix ("}}" )
73+ assert value != inner , value
74+ return next ((context [name ] for name in (part .strip () for part in inner .split ("||" ))
75+ if context .get (name )), "" )
76+
77+
7078def check_dco (
7179 repo : Path , env : dict [str , str ], old_base : str , head : str ,
72- * , base_ref : str = "release/next" ,
80+ * , base_ref : str = "release/next" , event : str = "pull_request" ,
7381) -> subprocess .CompletedProcess [str ]:
7482 workflow = yaml .safe_load ((ROOT / ".github/workflows/dco.yml" ).read_text (encoding = "utf-8" ))
75- event_values = {
76- "${{ github.event.pull_request.base.sha }}" : old_base ,
77- "${{ github.event.pull_request.base.ref }}" : base_ref ,
78- "${{ github.event.pull_request.head.sha }}" : head ,
79- "${{ github.token }}" : "synthetic-read-only-token" ,
80- }
83+ assert event in workflow [True ]
84+ if event == "pull_request" :
85+ context = {
86+ "github.event.pull_request.base.sha" : old_base ,
87+ "github.event.pull_request.base.ref" : base_ref ,
88+ "github.event.pull_request.head.sha" : head ,
89+ }
90+ else :
91+ # A merge-queue event carries a full base ref and no pull_request.
92+ context = {
93+ "github.event.merge_group.base_sha" : old_base ,
94+ "github.event.merge_group.base_ref" : f"refs/heads/{ base_ref } " ,
95+ "github.event.merge_group.head_sha" : head ,
96+ }
97+ context ["github.token" ] = "synthetic-read-only-token"
8198 steps = [step for step in workflow ["jobs" ]["signoff" ]["steps" ] if "run" in step ]
8299 for step in steps :
83- step_env = {key : event_values [ value ] for key , value in step .get ("env" , {}).items ()}
100+ step_env = {key : expression ( value , context ) for key , value in step .get ("env" , {}).items ()}
84101 result = subprocess .run (
85102 ["bash" , "--noprofile" , "--norc" , "-e" , "-o" , "pipefail" , "-c" , step ["run" ]],
86103 cwd = repo , env = {** env , ** step_env }, check = False ,
@@ -270,3 +287,33 @@ def test_signed_pr_with_current_event_base_passes(history, git_env):
270287 head = commit (runner , git_env , "Signed contribution" )
271288 result = check_dco (runner , git_env , upstream , head )
272289 assert result .returncode == 0 , result .stdout + result .stderr
290+
291+
292+ @pytest .mark .parametrize ("signed" , [False , True ])
293+ def test_merge_queue_candidate_checks_the_same_contribution_range (history , git_env , signed ):
294+ runner , old_base , upstream = history
295+ head = commit (runner , git_env , "Queued contribution" , signed = signed )
296+ result = check_dco (runner , git_env , old_base , head , event = "merge_group" )
297+ assert (result .returncode == 0 ) == signed , result .stdout + result .stderr
298+ assert (f"Commit { head } is missing" in result .stdout ) == (not signed )
299+ assert f"Commit { upstream } is missing" not in result .stdout
300+
301+
302+ def test_merge_queue_platform_merge_is_exempt_only_with_verified_provenance (history , github_api ):
303+ runner , old_base , _ = history
304+ env , calls = github_api
305+ head = github_merge (runner , env )
306+ metadata = verified_merge_record (runner , env , head )
307+ result = check_dco (runner , {** env , "DCO_TEST_METADATA" : json .dumps (metadata )}, old_base , head ,
308+ event = "merge_group" )
309+ assert result .returncode == 0 , result .stdout + result .stderr
310+ assert f"Verified GitHub-generated merge { head } " in result .stdout
311+ assert calls .read_text ().strip () == f"api repos/qualification/dco/commits/{ head } "
312+
313+
314+ def test_missing_event_coordinates_fail_closed (history , git_env ):
315+ runner , old_base , _ = history
316+ head = commit (runner , git_env , "Signed contribution" )
317+ for base_ref , head_sha in (("" , head ), ("release/next" , "" )):
318+ result = check_dco (runner , git_env , old_base , head_sha , base_ref = base_ref )
319+ assert result .returncode != 0 , (base_ref , head_sha )
0 commit comments