4
4
import logging
5
5
import os
6
6
import time
7
+ from collections .abc import Callable
7
8
8
9
import plumbum
9
10
@@ -41,6 +42,22 @@ def read_local_tags_from_files(config: Config) -> tuple[list[str], set[str]]:
41
42
return all_local_tags , merged_local_tags
42
43
43
44
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
+
44
61
def pull_missing_tags (merged_tag : str , all_local_tags : list [str ]) -> list [str ]:
45
62
existing_platform_tags = []
46
63
@@ -55,7 +72,7 @@ def pull_missing_tags(merged_tag: str, all_local_tags: list[str]) -> list[str]:
55
72
56
73
LOGGER .warning (f"Trying to pull: { platform_tag } from registry" )
57
74
try :
58
- docker ["pull" , platform_tag ] & plumbum .FG
75
+ run_with_retries ( lambda : docker ["pull" , platform_tag ] & plumbum .FG )
59
76
existing_platform_tags .append (platform_tag )
60
77
LOGGER .info (f"Tag { platform_tag } pulled successfully" )
61
78
except plumbum .ProcessExecutionError :
@@ -64,22 +81,18 @@ def pull_missing_tags(merged_tag: str, all_local_tags: list[str]) -> list[str]:
64
81
return existing_platform_tags
65
82
66
83
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 } " )
70
93
71
94
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 )
83
96
LOGGER .info (f"Successfully pushed manifest for tag: { merged_tag } " )
84
97
85
98
@@ -88,23 +101,16 @@ def merge_tags(
88
101
) -> None :
89
102
LOGGER .info (f"Trying to merge tag: { merged_tag } " )
90
103
91
- existing_platform_tags = pull_missing_tags (merged_tag , all_local_tags )
92
-
93
104
# This allows to rerun the script without having to remove the manifest manually
94
105
try :
95
106
docker ["manifest" , "rm" , merged_tag ] & plumbum .FG
96
107
LOGGER .warning (f"Manifest { merged_tag } was present locally, removed it" )
97
108
except plumbum .ProcessExecutionError :
98
109
pass
99
110
111
+ existing_platform_tags = pull_missing_tags (merged_tag , all_local_tags )
100
112
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 )
108
114
else :
109
115
LOGGER .info (f"Skipping push for tag: { merged_tag } " )
110
116
0 commit comments