@@ -144,75 +144,61 @@ export async function runMain(): Promise<void> {
144144 const digestsObj : Record < string , string > = { } ;
145145
146146 if ( platform ) {
147+ // Extract digest from OCI tarball
147148 for ( const tag of imageTagArray ) {
148149 const imageSource = `oci-archive:/tmp/output.tar:${ tag } ` ;
149- const imageDest = `docker://${ imageName } :${ tag } ` ;
150- await copyImage ( true , imageSource , imageDest ) ;
151- }
152-
153- // Extract the image digest from the build output
154- if ( buildResult . imageDigests ) {
155- core . info (
156- `Image digest for ${ platform } : ${ buildResult . imageDigests } ` ,
150+
151+ const inspectOCICmd = await exec (
152+ 'skopeo' ,
153+ [ 'inspect' , imageSource ] ,
154+ { silent : true }
157155 ) ;
158- digestsObj [ platform ] = buildResult . imageDigests [ platform ] ;
159- } else {
160- // If buildResult doesn't have imageDigest, try to get it from the built image
161- if ( imageName ) {
162- // sleep for 5 seconds
163- await new Promise ( resolve => setTimeout ( resolve , 5000 ) ) ;
164- // list images
165- const listCmd = await exec (
166- 'docker' ,
167- [ 'images' , '--format' , '{{.Repository}}:{{.Tag}}' ] ,
168- { silent : true } ,
169- ) ;
170- core . info ( `Images: ${ listCmd . stdout } ` ) ;
171- // get the digest of the image
172- const inspectCmd = await exec (
173- 'docker' ,
174- [
175- 'buildx' ,
176- 'imagetools' ,
177- 'inspect' ,
178- `${ imageName } :${ imageTagArray [ 0 ] } ` ,
179- '--format' ,
180- '{{json .}}' ,
181- ] ,
182- { silent : true } ,
183- ) ;
184- if ( inspectCmd . exitCode === 0 ) {
185- try {
186- const imageInfo = JSON . parse ( inspectCmd . stdout ) ;
187- if ( imageInfo . manifest && imageInfo . manifest . digest ) {
188- const digest = imageInfo . manifest . digest ;
189- core . info ( `Image digest for ${ platform } : ${ digest } ` ) ;
190- digestsObj [ platform ] = digest ;
191- }
192- } catch ( error ) {
193- core . warning ( `Failed to parse image digest: ${ error . message } ` ) ;
156+
157+ if ( inspectOCICmd . exitCode === 0 ) {
158+ try {
159+ const imageInfo = JSON . parse ( inspectOCICmd . stdout ) ;
160+ if ( imageInfo . Digest ) {
161+ core . info ( `Image digest for ${ platform } : ${ imageInfo . Digest } ` ) ;
162+ digestsObj [ platform ] = imageInfo . Digest ;
163+ break ; // Found digest, stop looking
194164 }
195- } else {
196- core . warning ( `Failed to inspect image : ${ inspectCmd . stderr } ` ) ;
165+ } catch ( error ) {
166+ core . warning ( `Failed to parse OCI archive info : ${ error } ` ) ;
197167 }
168+ } else {
169+ core . warning ( `Failed to inspect OCI tarball for ${ tag } ` ) ;
198170 }
199171 }
172+
173+ // Copy image to registry AFTER extracting digest locally
174+ for ( const tag of imageTagArray ) {
175+ const imageSource = `oci-archive:/tmp/output.tar:${ tag } ` ;
176+ const imageDest = `docker://${ imageName } :${ tag } ` ;
177+ await copyImage ( true , imageSource , imageDest ) ;
178+ }
200179 } else if ( imageName ) {
201- // For non-platform specific builds, still try to get the digest
180+ // For non-platform specific builds, use local docker inspect
202181 const inspectCmd = await exec (
203182 'docker' ,
204183 [
205184 'inspect' ,
206185 `${ imageName } :${ imageTagArray [ 0 ] } ` ,
207186 '--format' ,
208- '{{.Id }}' ,
187+ '{{index .RepoDigests 0 }}' ,
209188 ] ,
210189 { silent : true } ,
211190 ) ;
212191 if ( inspectCmd . exitCode === 0 ) {
213- const digest = inspectCmd . stdout . trim ( ) ;
214- core . info ( `Image digest: ${ digest } ` ) ;
215- digestsObj [ 'default' ] = digest ;
192+ const digestLine = inspectCmd . stdout . trim ( ) ;
193+ // Extract just the digest part (sha256:...)
194+ const digestMatch = digestLine . match ( / s h a 2 5 6 : [ a - f 0 - 9 ] + / ) ;
195+ if ( digestMatch ) {
196+ const digest = digestMatch [ 0 ] ;
197+ core . info ( `Image digest: ${ digest } ` ) ;
198+ digestsObj [ 'default' ] = digest ;
199+ }
200+ } else {
201+ core . warning ( `Failed to get image digest: ${ inspectCmd . stderr } ` ) ;
216202 }
217203 }
218204
@@ -352,7 +338,6 @@ export async function runPost(): Promise<void> {
352338 if ( platform ) {
353339 // Create a digests object to track digests for each platform
354340 const digestsObj : Record < string , string > = { } ;
355- const platforms = platform . split ( / \s * , \s * / ) ;
356341
357342 for ( const tag of imageTagArray ) {
358343 core . info ( `Copying multiplatform image '${ imageName } :${ tag } '...` ) ;
@@ -361,42 +346,54 @@ export async function runPost(): Promise<void> {
361346
362347 await copyImage ( true , imageSource , imageDest ) ;
363348
364- // After pushing, get and set digest
365- const inspectCmd = await exec (
366- 'docker' ,
349+ // Try to inspect local OCI archive first to get the correct digest
350+ // This avoids race conditions with parallel multi-platform builds
351+ const inspectOCICmd = await exec (
352+ 'skopeo' ,
367353 [
368- 'buildx' ,
369- 'imagetools' ,
370354 'inspect' ,
371- `${ imageName } :${ tag } ` ,
372- '--format' ,
373- '{{json .}}' ,
355+ imageSource ,
374356 ] ,
375357 { silent : true } ,
376358 ) ;
377- if ( inspectCmd . exitCode === 0 ) {
359+
360+ if ( inspectOCICmd . exitCode === 0 ) {
378361 try {
379- const imageInfo = JSON . parse ( inspectCmd . stdout ) ;
380-
381- // If it's a manifest list, extract digests for each platform
382- if ( imageInfo . manifests ) {
383- for ( const manifest of imageInfo . manifests ) {
384- if ( manifest . platform && manifest . digest ) {
385- const platformStr = `${ manifest . platform . os } /${ manifest . platform . architecture } ${ manifest . platform . variant ? `/${ manifest . platform . variant } ` : '' } ` ;
386- core . info (
387- `Image digest for ${ imageName } :${ tag } (${ platformStr } ): ${ manifest . digest } ` ,
388- ) ;
389- digestsObj [ platformStr ] = manifest . digest ;
390- }
391- }
392- } else if ( imageInfo . manifest && imageInfo . manifest . digest ) {
393- // Single platform image
394- const digest = imageInfo . manifest . digest ;
395- core . info ( `Image digest for ${ imageName } :${ tag } : ${ digest } ` ) ;
396- digestsObj [ platforms [ 0 ] || 'default' ] = digest ;
362+ const imageInfo = JSON . parse ( inspectOCICmd . stdout ) ;
363+ if ( imageInfo . Digest ) {
364+ core . info ( `Image digest for ${ imageName } :${ tag } (${ platform } ): ${ imageInfo . Digest } ` ) ;
365+ digestsObj [ platform ] = imageInfo . Digest ;
397366 }
398367 } catch ( error ) {
399- core . warning ( `Failed to parse image digest: ${ error . message } ` ) ;
368+ core . warning ( `Failed to parse local OCI image info: ${ error . message } ` ) ;
369+ }
370+ } else {
371+ // Fallback to registry inspection (with race condition risk)
372+ core . info ( 'Local OCI inspection failed, trying registry...' ) ;
373+ const inspectCmd = await exec (
374+ 'docker' ,
375+ [
376+ 'buildx' ,
377+ 'imagetools' ,
378+ 'inspect' ,
379+ `${ imageName } :${ tag } ` ,
380+ '--format' ,
381+ '{{json .}}' ,
382+ ] ,
383+ { silent : true } ,
384+ ) ;
385+ if ( inspectCmd . exitCode === 0 ) {
386+ try {
387+ const imageInfo = JSON . parse ( inspectCmd . stdout ) ;
388+ if ( imageInfo . manifest && imageInfo . manifest . digest ) {
389+ // Single platform image
390+ const digest = imageInfo . manifest . digest ;
391+ core . info ( `Image digest for ${ imageName } :${ tag } : ${ digest } ` ) ;
392+ digestsObj [ platform ] = digest ;
393+ }
394+ } catch ( error ) {
395+ core . warning ( `Failed to parse registry image info: ${ error . message } ` ) ;
396+ }
400397 }
401398 }
402399 }
@@ -445,3 +442,5 @@ function emptyStringAsUndefined(value: string): string | undefined {
445442 }
446443 return value ;
447444}
445+
446+
0 commit comments