@@ -131,30 +131,51 @@ runs:
131131 }
132132 }
133133
134- // Helper function to build annotations options
135- function buildAnnotationsOption(annotations) {
136- const annotationLevels = ["index"];
137- return Object.keys(annotations)
138- .map(annotation => annotationLevels
139- .map(annotationLevel => `--annotation "${annotationLevel}:${annotation}=${annotations[annotation]}"`)
140- )
141- .flat()
142- .join(" ");
143- }
144134
145135 // Helper function to create multiarch manifest
146136 async function createMultiarchManifest(builtImage, imagesWithTags) {
147- const platformsOption = builtImage.platforms.map(platform => `--platform ${platform}`).join(" ");
148- const tagsOption = imagesWithTags.map(image => `--tag ${image}`).join(" ");
149- const sources = builtImage.images.join(" ");
150- const annotationsOption = buildAnnotationsOption(builtImage.annotations);
137+ const platformArgs = builtImage.platforms.flatMap(platform => ["--platform", platform]);
138+ const tagArgs = imagesWithTags.flatMap(image => ["--tag", image]);
139+ const annotationArgs = Object.keys(builtImage.annotations).flatMap(key => [
140+ "--annotation",
141+ `index:${key}=${builtImage.annotations[key]}`,
142+ ]);
143+ const sourceArgs = builtImage.images;
144+
145+ const createManifestArgs = [
146+ "buildx", "imagetools", "create",
147+ ...platformArgs,
148+ ...annotationArgs,
149+ ...tagArgs,
150+ ...sourceArgs,
151+ ];
152+
153+ const maxAttempts = 6;
154+ const delayMs = 5000;
151155
152- const createManifestCommand = `docker buildx imagetools create ${platformsOption} ${annotationsOption} ${tagsOption} ${sources}`;
156+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
157+ const result = await exec.getExecOutput("docker", createManifestArgs, { ignoreReturnCode: true });
158+
159+ if (result.exitCode === 0) {
160+ core.debug(`Create manifest for "${builtImage.name}" executed`);
161+ builtImage.images = imagesWithTags;
162+ return;
163+ }
153164
154- await exec.exec(createManifestCommand );
155- core.debug(`Create manifest for "${builtImage.name}" ("${createManifestCommand}") executed` );
165+ const commandOutput = `${result.stderr || ""}\n${result.stdout || ""}`.trim( );
166+ const isRetryableNotFound = /not found| manifest unknown|no such manifest/i.test(commandOutput );
156167
157- builtImage.images = imagesWithTags;
168+ if (!isRetryableNotFound || attempt === maxAttempts) {
169+ throw new Error(
170+ `Failed to create manifest for "${builtImage.name}" (attempt ${attempt}/${maxAttempts}, exit code: ${result.exitCode}).\n${commandOutput}`,
171+ );
172+ }
173+
174+ core.warning(
175+ `Source manifest for "${builtImage.name}" not yet available (attempt ${attempt}/${maxAttempts}). Retrying in ${delayMs}ms...`,
176+ );
177+ await new Promise(resolve => setTimeout(resolve, delayMs));
178+ }
158179 }
159180
160181 // Helper function to build image tags
0 commit comments