@@ -20,6 +20,10 @@ export interface BuildImageOptions {
2020 imagePlatform : string ;
2121 noCache ?: boolean ;
2222 load ?: boolean ;
23+ compression ?: "zstd" | "gzip" ;
24+ cacheCompression ?: "zstd" | "gzip" ;
25+ compressionLevel ?: number ;
26+ forceCompression ?: boolean ;
2327
2428 // Local build options
2529 push ?: boolean ;
@@ -79,6 +83,10 @@ export async function buildImage(options: BuildImageOptions): Promise<BuildImage
7983 buildEnvVars,
8084 network,
8185 builder,
86+ compression,
87+ cacheCompression,
88+ compressionLevel,
89+ forceCompression,
8290 onLog,
8391 } = options ;
8492
@@ -105,6 +113,10 @@ export async function buildImage(options: BuildImageOptions): Promise<BuildImage
105113 buildEnvVars,
106114 network,
107115 builder,
116+ compression,
117+ cacheCompression,
118+ compressionLevel,
119+ forceCompression,
108120 onLog,
109121 } ) ;
110122 }
@@ -134,6 +146,9 @@ export async function buildImage(options: BuildImageOptions): Promise<BuildImage
134146 apiKey,
135147 branchName,
136148 buildEnvVars,
149+ compression,
150+ compressionLevel,
151+ forceCompression,
137152 onLog,
138153 } ) ;
139154}
@@ -157,6 +172,9 @@ export interface DepotBuildImageOptions {
157172 noCache ?: boolean ;
158173 extraCACerts ?: string ;
159174 buildEnvVars ?: Record < string , string | undefined > ;
175+ compression ?: "zstd" | "gzip" ;
176+ compressionLevel ?: number ;
177+ forceCompression ?: boolean ;
160178 onLog ?: ( log : string ) => void ;
161179}
162180
@@ -180,6 +198,14 @@ async function remoteBuildImage(options: DepotBuildImageOptions): Promise<BuildI
180198 . filter ( ( [ key , value ] ) => value )
181199 . flatMap ( ( [ key , value ] ) => [ "--build-arg" , `${ key } =${ value } ` ] ) ;
182200
201+ const outputOptions = getOutputOptions ( {
202+ imageTag : undefined , // This is already handled via the --save flag
203+ push : true , // We always push the image to the registry
204+ compression : options . compression ,
205+ compressionLevel : options . compressionLevel ,
206+ forceCompression : options . forceCompression ,
207+ } ) ;
208+
183209 const args = [
184210 "build" ,
185211 "-f" ,
@@ -214,6 +240,8 @@ async function remoteBuildImage(options: DepotBuildImageOptions): Promise<BuildI
214240 "plain" ,
215241 "." ,
216242 "--save" ,
243+ "--output" ,
244+ outputOptions . join ( "," ) ,
217245 ] . filter ( Boolean ) as string [ ] ;
218246
219247 logger . debug ( `depot ${ args . join ( " " ) } ` , { cwd : options . cwd } ) ;
@@ -316,11 +344,25 @@ interface SelfHostedBuildImageOptions {
316344 network ?: string ;
317345 builder : string ;
318346 load ?: boolean ;
347+ compression ?: "zstd" | "gzip" ;
348+ cacheCompression ?: "zstd" | "gzip" ;
349+ compressionLevel ?: number ;
350+ forceCompression ?: boolean ;
319351 onLog ?: ( log : string ) => void ;
320352}
321353
322354async function localBuildImage ( options : SelfHostedBuildImageOptions ) : Promise < BuildImageResults > {
323- const { builder, imageTag, deploymentId, apiClient, useRegistryCache } = options ;
355+ const {
356+ builder,
357+ imageTag,
358+ deploymentId,
359+ apiClient,
360+ useRegistryCache,
361+ compression,
362+ cacheCompression,
363+ compressionLevel,
364+ forceCompression,
365+ } = options ;
324366
325367 // Ensure multi-platform build is supported on the local machine
326368 let builderExists = false ;
@@ -489,6 +531,14 @@ async function localBuildImage(options: SelfHostedBuildImageOptions): Promise<Bu
489531
490532 const projectCacheRef = getProjectCacheRefFromImageTag ( imageTag ) ;
491533
534+ const outputOptions = getOutputOptions ( {
535+ imageTag,
536+ push,
537+ compression,
538+ compressionLevel,
539+ forceCompression,
540+ } ) ;
541+
492542 const args = [
493543 "buildx" ,
494544 "build" ,
@@ -500,16 +550,19 @@ async function localBuildImage(options: SelfHostedBuildImageOptions): Promise<Bu
500550 ...( useRegistryCache
501551 ? [
502552 "--cache-to" ,
503- `type=registry,mode=max,image-manifest=true,oci-mediatypes=true,ref=${ projectCacheRef } ` ,
553+ `type=registry,mode=max,image-manifest=true,oci-mediatypes=true,ref=${ projectCacheRef } ${
554+ cacheCompression === "zstd" ? ",compression=zstd" : ""
555+ } `,
504556 "--cache-from" ,
505557 `type=registry,ref=${ projectCacheRef } ` ,
506558 ]
507559 : [ ] ) ,
560+ "--output" ,
561+ outputOptions . join ( "," ) ,
508562 "--platform" ,
509563 options . imagePlatform ,
510564 options . network ? `--network=${ options . network } ` : undefined ,
511565 addHost ? `--add-host=${ addHost } ` : undefined ,
512- push ? "--push" : undefined ,
513566 load ? "--load" : undefined ,
514567 "--provenance" ,
515568 "false" ,
@@ -1072,3 +1125,43 @@ function shouldLoad(load?: boolean, push?: boolean) {
10721125 }
10731126 }
10741127}
1128+
1129+ function getOutputOptions ( {
1130+ imageTag,
1131+ push,
1132+ compression,
1133+ compressionLevel,
1134+ forceCompression,
1135+ } : {
1136+ imageTag ?: string ;
1137+ push ?: boolean ;
1138+ compression ?: "zstd" | "gzip" ;
1139+ compressionLevel ?: number ;
1140+ forceCompression ?: boolean ;
1141+ } ) : string [ ] {
1142+ // Always use OCI media types for compatibility
1143+ const outputOptions : string [ ] = [ "type=image" , "oci-mediatypes=true" ] ;
1144+
1145+ if ( imageTag ) {
1146+ outputOptions . push ( `name=${ imageTag } ` ) ;
1147+ }
1148+
1149+ if ( push ) {
1150+ outputOptions . push ( "push=true" ) ;
1151+ }
1152+
1153+ // Only add compression args when using zstd (gzip is the default, no args needed)
1154+ if ( compression === "zstd" ) {
1155+ outputOptions . push ( "compression=zstd" ) ;
1156+
1157+ if ( compressionLevel !== undefined ) {
1158+ outputOptions . push ( `compression-level=${ compressionLevel } ` ) ;
1159+ }
1160+ }
1161+
1162+ if ( forceCompression ) {
1163+ outputOptions . push ( "force-compression=true" ) ;
1164+ }
1165+
1166+ return outputOptions ;
1167+ }
0 commit comments