66import subprocess
77from argparse import Namespace
88from subprocess import CalledProcessError
9- from typing import Optional
109
1110
1211def resync_specs (directory : pathlib .Path , errored : dict [str , str ]) -> None :
@@ -32,14 +31,27 @@ def resync_specs(directory: pathlib.Path, errored: dict[str, str]) -> None:
3231
3332def apply_patches (errored ):
3433 print ("Beginning to apply patches" )
35- subprocess .run (["bash" , "./.evergreen/remove-unimplemented-tests.sh" ], check = True ) # noqa: S603, S607
34+ subprocess .run (
35+ ["bash" , "./.evergreen/remove-unimplemented-tests.sh" ], # noqa: S603, S607
36+ check = True ,
37+ )
3638 try :
37- subprocess .run (
38- ["git apply -R --allow-empty --whitespace=fix ./.evergreen/spec-patch/*" ], # noqa: S607
39- shell = True , # noqa: S602
40- check = True ,
41- stderr = subprocess .PIPE ,
42- )
39+ # Avoid shell=True by passing arguments as a list.
40+ # Note: glob expansion doesn't work in shell=False, so we use a list of files.
41+ patches = [str (p ) for p in pathlib .Path ("./.evergreen/spec-patch/" ).glob ("*" )]
42+ if patches :
43+ subprocess .run (
44+ [ # noqa: S603, S607
45+ "git" ,
46+ "apply" ,
47+ "-R" ,
48+ "--allow-empty" ,
49+ "--whitespace=fix" ,
50+ * patches ,
51+ ],
52+ check = True ,
53+ stderr = subprocess .PIPE ,
54+ )
4355 except CalledProcessError as exc :
4456 errored ["applying patches" ] = exc .stderr
4557
@@ -73,17 +85,24 @@ def check_new_spec_directories(directory: pathlib.Path) -> list[str]:
7385 return list (spec_set - test_set )
7486
7587
76- def write_summary (errored : dict [str , str ], new : list [str ], filename : Optional [ str ] ) -> None :
88+ def write_summary (errored : dict [str , str ], new : list [str ], filename : str | None ) -> None :
7789 """Generate the PR description"""
7890 pr_body = ""
91+ # Avoid shell=True and complex pipes by using Python to process git output
7992 process = subprocess .run (
80- ["git diff --name-only | awk -F'/' '{print $2}' | sort | uniq" ], # noqa: S607
81- shell = True , # noqa: S602
93+ ["git" , "diff" , "--name-only" ], # noqa: S603, S607
8294 capture_output = True ,
8395 text = True ,
8496 check = True ,
8597 )
86- succeeded = process .stdout .strip ().split ()
98+ changed_files = process .stdout .strip ().splitlines ()
99+ succeeded_set = set ()
100+ for f in changed_files :
101+ parts = f .split ("/" )
102+ if len (parts ) > 1 :
103+ succeeded_set .add (parts [1 ])
104+ succeeded = sorted (succeeded_set )
105+
87106 if len (succeeded ) > 0 :
88107 pr_body += "The following specs were changed:\n -"
89108 pr_body += "\n -" .join (succeeded )
@@ -120,7 +139,9 @@ def main(args: Namespace):
120139 description = "Python Script to resync all specs and generate summary for PR."
121140 )
122141 parser .add_argument (
123- "--filename" , help = "Name of file for the summary to be written into." , default = None
142+ "--filename" ,
143+ help = "Name of file for the summary to be written into." ,
144+ default = None ,
124145 )
125146 args = parser .parse_args ()
126147 main (args )
0 commit comments