@@ -44,9 +44,25 @@ def testParsesSupportedCommentCommands(self):
4444 self .assertEqual (command ["headSHA" ], headSHA )
4545 self .assertEqual (command ["nonce" ], nonce )
4646
47+ def testParsesUnboundCommentCommands (self ):
48+ cases = {
49+ "/test e2e" : ("dispatch" , [], False ),
50+ "/test e2e core" : ("dispatch" , ["core" ], False ),
51+ "/test e2e-all" : ("dispatch" , [], True ),
52+ "/retest e2e-failed" : ("rerun-failed" , [], False ),
53+ }
54+ for body , expected in cases .items ():
55+ with self .subTest (body = body ):
56+ command = e2eControl .parseCommand (body )
57+ self .assertEqual (
58+ (command ["action" ], command ["requestedGroups" ], command ["full" ]),
59+ expected ,
60+ )
61+ self .assertEqual (command ["headSHA" ], "" )
62+ self .assertEqual (command ["nonce" ], "" )
63+
4764 def testRejectsMalformedOrInjectedCommands (self ):
4865 for body in [
49- "/test e2e" ,
5066 "/test e2e policy bogus" ,
5167 "/test e2e policy;echo-owned" ,
5268 "/test e2e policy\n /test e2e-all" ,
@@ -69,14 +85,15 @@ def dispatchDecision(
6985 state = "open" ,
7086 baseRef = "master" ,
7187 controlledLabels = (),
88+ bindHead = True ,
7289 ):
7390 catalog = json .loads ((repoRoot / ".github/e2e-selection.json" ).read_text ())
7491 catalogRevision = e2eSelector .catalogRevision (catalog )
7592 baseSHA = "b" * 40
7693 if body is None :
7794 nonce = e2eControl .requestNonce (7231 , observedHeadSHA , baseSHA , catalogRevision )
7895 body = f"/test e2e policy --head { observedHeadSHA } --nonce { nonce } "
79- elif " --head " not in body :
96+ elif bindHead and " --head " not in body :
8097 nonce = e2eControl .requestNonce (7231 , observedHeadSHA , baseSHA , catalogRevision )
8198 body = f"{ body } --head { observedHeadSHA } --nonce { nonce } "
8299 event = {
@@ -102,6 +119,16 @@ def dispatchDecision(
102119 controlledLabels = controlledLabels ,
103120 )
104121
122+ def testUnboundCommandBindsToLiveHead (self ):
123+ decision = self .dispatchDecision (body = "/test e2e core" , bindHead = False )
124+
125+ self .assertTrue (decision ["accepted" ])
126+ self .assertEqual (decision ["action" ], "dispatch" )
127+ self .assertEqual (decision ["requestedGroups" ], ["core" ])
128+ self .assertEqual (decision ["headSHA" ], "a" * 40 )
129+ self .assertEqual (decision ["baseSHA" ], "b" * 40 )
130+ self .assertRegex (decision ["nonce" ], r"^[0-9a-f]{16}$" )
131+
105132 def testAuthorizedCommandIsBoundToCurrentHead (self ):
106133 decision = self .dispatchDecision ()
107134
@@ -842,6 +869,7 @@ def testDispatcherWorkflowUsesOnlyTrustedWritePermissions(self):
842869 self .assertIn ("checks: read" , workflow )
843870 self .assertNotIn ("checks: write" , workflow )
844871 self .assertIn ("pull-requests: read" , workflow )
872+ self .assertIn ("pull-requests: write" , workflow )
845873 self .assertIn ("issues: write" , workflow )
846874 self .assertIn ("--catalog trusted-catalog.json" , workflow )
847875 self .assertIn ("--live-comment-file live-comment.json" , workflow )
0 commit comments