@@ -183,15 +183,22 @@ def render_ci_plan(pr: int, checks: list[dict[str, Any]]) -> str:
183183 return "\n " .join (lines )
184184
185185
186- def maybe_apply_deterministic_fix (bundle_dir : Path , plan_path : Path , summary : Summary ) -> str | None :
186+ def maybe_apply_deterministic_fixes (bundle_dir : Path , plan_path : Path , summary : Summary ) -> list [ str ] :
187187 text = plan_path .read_text (encoding = "utf-8" )
188188 for snippet in (bundle_dir / "snippets" ).glob ("*.txt" ):
189189 text += "\n " + snippet .read_text (encoding = "utf-8" , errors = "replace" )
190- if "spotless" not in text .lower ():
191- return None
192- run (gradlew_cmd ("spotless" ), summary )
193- summary .notes .append ("Applied deterministic spotless fix based on CI logs" )
194- return "spotless"
190+
191+ text = text .lower ()
192+ fix_kinds = []
193+ if "spotless" in text :
194+ run (gradlew_cmd ("spotless" ), summary )
195+ summary .notes .append ("Applied deterministic spotless fix based on CI logs" )
196+ fix_kinds .append ("spotless" )
197+ if "fossa" in text or "generatefossaconfiguration" in text or ".fossa.yml" in text :
198+ run (gradlew_cmd ("generateFossaConfiguration" ), summary )
199+ summary .notes .append ("Applied deterministic FOSSA configuration fix based on CI logs" )
200+ fix_kinds .append ("fossa" )
201+ return fix_kinds
195202
196203
197204def ci_fix_commit_message (checks : list [dict [str , Any ]], changed_paths : list [str ]) -> list [str ]:
@@ -212,23 +219,47 @@ def ci_fix_commit_message(checks: list[dict[str, Any]], changed_paths: list[str]
212219 return [subject , "\n " .join (body_lines )]
213220
214221
215- def deterministic_ci_fix_commit_message (fix_kind : str , checks : list [dict [str , Any ]], changed_paths : list [str ]) -> list [str ]:
216- if fix_kind == "spotless" :
222+ def append_deterministic_commit_details (body_lines : list [str ], checks : list [dict [str , Any ]], changed_paths : list [str ], file_heading : str ) -> None :
223+ body_lines .extend (["" , "Failed jobs:" ])
224+ body_lines .extend (f"- { family } " for family in sorted ({job_family (check .get ("name" ) or "unknown" ) for check in checks })[:8 ])
225+ body_lines .append ("" )
226+ body_lines .append (file_heading )
227+ body_lines .extend (f"- { path } " for path in changed_paths [:12 ])
228+ if len (changed_paths ) > 12 :
229+ body_lines .append (f"- ... and { len (changed_paths ) - 12 } more" )
230+
231+
232+ def deterministic_ci_fix_commit_message (fix_kinds : list [str ], checks : list [dict [str , Any ]], changed_paths : list [str ]) -> list [str ]:
233+ if fix_kinds == ["spotless" ]:
217234 subject = "Apply spotless formatting"
218235 body_lines = [
219236 "CI reported Spotless formatting violations." ,
220237 "" ,
221238 "Ran:" ,
222239 "- ./gradlew spotless" ,
240+ ]
241+ append_deterministic_commit_details (body_lines , checks , changed_paths , "Formatted files:" )
242+ return [subject , "\n " .join (body_lines )]
243+ if fix_kinds == ["fossa" ]:
244+ subject = "Regenerate FOSSA configuration"
245+ body_lines = [
246+ "CI reported that the FOSSA configuration was out of date." ,
223247 "" ,
224- "Failed jobs:" ,
248+ "Ran:" ,
249+ "- ./gradlew generateFossaConfiguration" ,
250+ ]
251+ append_deterministic_commit_details (body_lines , checks , changed_paths , "Updated files:" )
252+ return [subject , "\n " .join (body_lines )]
253+ if set (fix_kinds ) == {"spotless" , "fossa" }:
254+ subject = "Apply deterministic CI fixes"
255+ body_lines = [
256+ "CI reported deterministic Spotless and FOSSA configuration failures." ,
257+ "" ,
258+ "Ran:" ,
259+ "- ./gradlew spotless" ,
260+ "- ./gradlew generateFossaConfiguration" ,
225261 ]
226- body_lines .extend (f"- { family } " for family in sorted ({job_family (check .get ("name" ) or "unknown" ) for check in checks })[:8 ])
227- body_lines .append ("" )
228- body_lines .append ("Formatted files:" )
229- body_lines .extend (f"- { path } " for path in changed_paths [:12 ])
230- if len (changed_paths ) > 12 :
231- body_lines .append (f"- ... and { len (changed_paths ) - 12 } more" )
262+ append_deterministic_commit_details (body_lines , checks , changed_paths , "Updated files:" )
232263 return [subject , "\n " .join (body_lines )]
233264 return ci_fix_commit_message (checks , changed_paths )
234265
@@ -319,8 +350,8 @@ def main() -> int:
319350 bundle_dir = make_temp_dir ("otel-ci-fix" , args .pr , args .keep_temp )
320351 plan_path = write_ci_bundle (args .pr , checks , bundle_dir , summary )
321352
322- deterministic_fix = maybe_apply_deterministic_fix (bundle_dir , plan_path , summary )
323- if deterministic_fix is None and not args .skip_copilot :
353+ deterministic_fixes = maybe_apply_deterministic_fixes (bundle_dir , plan_path , summary )
354+ if not deterministic_fixes and not args .skip_copilot :
324355 commit_message_path = bundle_dir / "commit-message.txt"
325356 prompt_improvement_path = bundle_dir / "prompt-improvement.md"
326357 response = invoke_copilot (copilot_prompt (plan_path , commit_message_path , prompt_improvement_path ), summary )
@@ -339,8 +370,8 @@ def main() -> int:
339370 return 0
340371
341372 commit_message = (
342- deterministic_ci_fix_commit_message (deterministic_fix , checks , summary .changed_files )
343- if deterministic_fix is not None
373+ deterministic_ci_fix_commit_message (deterministic_fixes , checks , summary .changed_files )
374+ if deterministic_fixes
344375 else read_copilot_commit_message (bundle_dir / "commit-message.txt" , summary )
345376 )
346377 if commit_message is None :
0 commit comments