44import logging
55import os
66import time
7+ from collections .abc import Callable
78
89import plumbum
910
@@ -41,6 +42,22 @@ def read_local_tags_from_files(config: Config) -> tuple[list[str], set[str]]:
4142 return all_local_tags , merged_local_tags
4243
4344
45+ def run_with_retries (func : Callable [[], None ]) -> None :
46+ ATTEMPTS = 3
47+ SLEEP_BACKOFF = 2
48+
49+ for attempt in range (ATTEMPTS ):
50+ try :
51+ func ()
52+ break
53+ except Exception as e :
54+ LOGGER .warning (f"Attempt { attempt + 1 } failed: { e } " )
55+ if attempt + 1 == ATTEMPTS :
56+ LOGGER .error (f"Failed after { ATTEMPTS } attempts" )
57+ raise
58+ time .sleep (SLEEP_BACKOFF * (attempt + 1 ))
59+
60+
4461def pull_missing_tags (merged_tag : str , all_local_tags : list [str ]) -> list [str ]:
4562 existing_platform_tags = []
4663
@@ -55,7 +72,7 @@ def pull_missing_tags(merged_tag: str, all_local_tags: list[str]) -> list[str]:
5572
5673 LOGGER .warning (f"Trying to pull: { platform_tag } from registry" )
5774 try :
58- docker ["pull" , platform_tag ] & plumbum .FG
75+ run_with_retries ( lambda : docker ["pull" , platform_tag ] & plumbum .FG )
5976 existing_platform_tags .append (platform_tag )
6077 LOGGER .info (f"Tag { platform_tag } pulled successfully" )
6178 except plumbum .ProcessExecutionError :
@@ -64,22 +81,18 @@ def pull_missing_tags(merged_tag: str, all_local_tags: list[str]) -> list[str]:
6481 return existing_platform_tags
6582
6683
67- def push_manifest (merged_tag : str ) -> None :
68- ATTEMPTS = 3
69- SLEEP_TIME = 5
84+ def push_manifest (merged_tag : str , existing_platform_tags : list [str ]) -> None :
85+ LOGGER .info (f"Creating manifest for tag: { merged_tag } " )
86+ # Unforunately, `docker manifest create` requires images to have been already pushed to the registry
87+ # which is not true for new tags in PRs
88+ run_with_retries (
89+ lambda : docker ["manifest" , "create" , merged_tag ][existing_platform_tags ]
90+ & plumbum .FG
91+ )
92+ LOGGER .info (f"Successfully created manifest for tag: { merged_tag } " )
7093
7194 LOGGER .info (f"Pushing manifest for tag: { merged_tag } " )
72- # Retry pushing the manifest up to ATTEMPTS times in case of failure
73- for attempt in range (ATTEMPTS ):
74- try :
75- docker ["manifest" , "push" , merged_tag ] & plumbum .FG
76- break
77- except plumbum .ProcessExecutionError as e :
78- LOGGER .warning (f"Attempt { attempt + 1 } to push manifest failed: { e } " )
79- if attempt + 1 == ATTEMPTS :
80- LOGGER .error (f"Failed to push manifest after { ATTEMPTS } attempts" )
81- raise
82- time .sleep (SLEEP_TIME )
95+ run_with_retries (lambda : docker ["manifest" , "push" , merged_tag ] & plumbum .FG )
8396 LOGGER .info (f"Successfully pushed manifest for tag: { merged_tag } " )
8497
8598
@@ -88,23 +101,16 @@ def merge_tags(
88101) -> None :
89102 LOGGER .info (f"Trying to merge tag: { merged_tag } " )
90103
91- existing_platform_tags = pull_missing_tags (merged_tag , all_local_tags )
92-
93104 # This allows to rerun the script without having to remove the manifest manually
94105 try :
95106 docker ["manifest" , "rm" , merged_tag ] & plumbum .FG
96107 LOGGER .warning (f"Manifest { merged_tag } was present locally, removed it" )
97108 except plumbum .ProcessExecutionError :
98109 pass
99110
111+ existing_platform_tags = pull_missing_tags (merged_tag , all_local_tags )
100112 if push_to_registry :
101- # Unforunately, `docker manifest create` requires images to have been already pushed to the registry
102- # which is not true for new tags in PRs
103- LOGGER .info (f"Creating manifest for tag: { merged_tag } " )
104- docker ["manifest" , "create" , merged_tag ][existing_platform_tags ] & plumbum .FG
105- LOGGER .info (f"Successfully created manifest for tag: { merged_tag } " )
106-
107- push_manifest (merged_tag )
113+ push_manifest (merged_tag , existing_platform_tags )
108114 else :
109115 LOGGER .info (f"Skipping push for tag: { merged_tag } " )
110116
0 commit comments