@@ -87,6 +87,7 @@ def create_preprod_status_check_task(preprod_artifact_id: int) -> None:
8787 client ,
8888 commit_comparison .provider ,
8989 preprod_artifact .project .organization_id ,
90+ preprod_artifact .project .organization .slug ,
9091 repository .integration_id ,
9192 )
9293 if not provider :
@@ -247,10 +248,16 @@ def _get_status_check_client(
247248
248249
249250def _get_status_check_provider (
250- client : StatusCheckClient , provider : str | None , organization_id : int , integration_id : int
251+ client : StatusCheckClient ,
252+ provider : str | None ,
253+ organization_id : int ,
254+ organization_slug : str ,
255+ integration_id : int ,
251256) -> _StatusCheckProvider | None :
252257 if provider == IntegrationProviderSlug .GITHUB :
253- return _GitHubStatusCheckProvider (client , provider , organization_id , integration_id )
258+ return _GitHubStatusCheckProvider (
259+ client , provider , organization_id , organization_slug , integration_id
260+ )
254261 else :
255262 return None
256263
@@ -266,11 +273,13 @@ def __init__(
266273 client : StatusCheckClient ,
267274 provider_key : str ,
268275 organization_id : int ,
276+ organization_slug : str ,
269277 integration_id : int ,
270278 ):
271279 self .client = client
272280 self .provider_key = provider_key
273281 self .organization_id = organization_id
282+ self .organization_slug = organization_slug
274283 self .integration_id = integration_id
275284
276285 def _create_scm_interaction_event (self ) -> SCMIntegrationInteractionEvent :
@@ -322,19 +331,44 @@ def create_status_check(
322331 )
323332 return None
324333
334+ truncated_text = _truncate_to_byte_limit (text , GITHUB_MAX_TEXT_FIELD_LENGTH )
335+ truncated_summary = _truncate_to_byte_limit (summary , GITHUB_MAX_SUMMARY_FIELD_LENGTH )
336+
337+ if text and truncated_text and len (truncated_text ) != len (text ):
338+ logger .warning (
339+ "preprod.status_checks.create.text_truncated" ,
340+ extra = {
341+ "original_bytes" : len (text .encode ("utf-8" )),
342+ "truncated_bytes" : len (truncated_text .encode ("utf-8" )),
343+ "organization_id" : self .organization_id ,
344+ "organization_slug" : self .organization_slug ,
345+ },
346+ )
347+
348+ if summary and truncated_summary and len (truncated_summary ) != len (summary ):
349+ logger .warning (
350+ "preprod.status_checks.create.summary_truncated" ,
351+ extra = {
352+ "original_bytes" : len (summary .encode ("utf-8" )),
353+ "truncated_bytes" : len (truncated_summary .encode ("utf-8" )),
354+ "organization_id" : self .organization_id ,
355+ "organization_slug" : self .organization_slug ,
356+ },
357+ )
358+
325359 check_data : dict [str , Any ] = {
326360 "name" : title ,
327361 "head_sha" : sha ,
328362 "external_id" : external_id ,
329363 "output" : {
330364 "title" : subtitle ,
331- "summary" : summary ,
365+ "summary" : truncated_summary ,
332366 },
333367 "status" : mapped_status .value ,
334368 }
335369
336- if text :
337- check_data ["output" ]["text" ] = text
370+ if truncated_text :
371+ check_data ["output" ]["text" ] = truncated_text
338372
339373 if mapped_conclusion :
340374 check_data ["conclusion" ] = mapped_conclusion .value
@@ -395,6 +429,35 @@ def create_status_check(
395429 raise
396430
397431
432+ # See: https://docs.github.com/en/rest/checks/runs?apiVersion=2022-11-28#create-a-check-run
433+ GITHUB_MAX_SUMMARY_FIELD_LENGTH = 65535
434+ GITHUB_MAX_TEXT_FIELD_LENGTH = 65535
435+
436+
437+ def _truncate_to_byte_limit (text : str | None , byte_limit : int ) -> str | None :
438+ """Truncate text to fit within byte limit while ensuring valid UTF-8."""
439+ if not text :
440+ return text
441+
442+ TRUNCATE_AMOUNT = 10
443+
444+ encoded = text .encode ("utf-8" )
445+ if len (encoded ) <= byte_limit :
446+ return text
447+
448+ if byte_limit <= TRUNCATE_AMOUNT :
449+ # This shouldn't happen, but just in case.
450+ truncated = encoded [:byte_limit ].decode ("utf-8" , errors = "ignore" )
451+ return truncated
452+
453+ # Truncate to byte_limit - 10 (a bit of wiggle room) to make room for "..."
454+ # Note: this can break formatting you have and is more of a catch-all,
455+ # broken formatting is better than silently erroring for the user.
456+ # Templating logic itself should try to more contextually trim the content if possible.
457+ truncated = encoded [: byte_limit - TRUNCATE_AMOUNT ].decode ("utf-8" , errors = "ignore" )
458+ return truncated + "..."
459+
460+
398461GITHUB_STATUS_CHECK_STATUS_MAPPING : dict [StatusCheckStatus , GitHubCheckStatus ] = {
399462 StatusCheckStatus .ACTION_REQUIRED : GitHubCheckStatus .COMPLETED ,
400463 StatusCheckStatus .IN_PROGRESS : GitHubCheckStatus .IN_PROGRESS ,
0 commit comments