@@ -119,6 +119,19 @@ func main() {
119119 }
120120 logger .Info ("Detected builder: %s" , strings .ToUpper (builder ))
121121
122+ // Run the build pipeline in a separate function so that deferred cleanup
123+ // use error returns instead and only call Fatal at the very end.
124+ if err := run (config , builder ); err != nil {
125+ logger .Fatal ("%v" , err )
126+ }
127+
128+ logger .Info ("Build completed successfully!" )
129+ }
130+
131+ // run executes the build pipeline. By returning errors instead of calling
132+ // logger.Fatal directly, we ensure that deferred cleanup (ctx.Cleanup)
133+ // always runs — even when the build fails.
134+ func run (config * Config , builder string ) error {
122135 // Prepare build context
123136 gitConfig := build.GitConfig {
124137 Context : config .Context ,
@@ -130,14 +143,13 @@ func main() {
130143
131144 ctx , err := build .Prepare (gitConfig , builder )
132145 if err != nil {
133- logger . Fatal ( "Failed to prepare build context: %v" , err )
146+ return fmt . Errorf ( "failed to prepare build context: %v" , err )
134147 }
135148 defer ctx .Cleanup ()
136-
149+
137150 // Store SubContext in context for BuildKit Git URL formatting
138151 ctx .SubContext = config .SubContext
139152
140-
141153 // Apply context-sub-path for local contexts (not Git URLs)
142154 // For Git URLs with BuildKit, SubContext is handled in FormatGitURLForBuildKit
143155 if config .SubContext != "" && ctx .Path != "" {
@@ -146,26 +158,26 @@ func main() {
146158
147159 // Clean the sub-context to resolve . and .. components
148160 cleanSubContext := filepath .Clean (config .SubContext )
149-
161+
150162 // Join the paths
151163 subPath := filepath .Join (cleanContextPath , cleanSubContext )
152164
153165 // Validate that subPath is actually within the context path
154166 // by checking if the relative path starts with ".."
155167 relPath , err := filepath .Rel (cleanContextPath , subPath )
156168 if err != nil {
157- logger . Fatal ( "Invalid context sub-path: %s" , config .SubContext )
169+ return fmt . Errorf ( "invalid context sub-path: %s" , config .SubContext )
158170 }
159171
160172 // If the relative path starts with "..", it's trying to escape
161173 if strings .HasPrefix (relPath , ".." ) {
162- logger . Fatal ( "Context sub-path attempts to escape build context: %s" , config .SubContext )
174+ return fmt . Errorf ( "context sub-path attempts to escape build context: %s" , config .SubContext )
163175 }
164176
165177 // Verify the subdirectory exists
166178 // #nosec G703 -- subPath is validated to be within cleanContextPath using filepath.Rel() check above
167179 if _ , err := os .Stat (subPath ); err != nil {
168- logger . Fatal ( "Context sub-path does not exist: %s (full path: %s)" , config .SubContext , subPath )
180+ return fmt . Errorf ( "context sub-path does not exist: %s (full path: %s)" , config .SubContext , subPath )
169181 }
170182
171183 logger .Info ("Using context sub-path: %s" , config .SubContext )
@@ -180,7 +192,7 @@ func main() {
180192
181193 err = auth .Setup (authSetup )
182194 if err != nil {
183- logger . Fatal ( "Failed to setup authentication: %v" , err )
195+ return fmt . Errorf ( "failed to setup authentication: %v" , err )
184196 }
185197
186198 // Execute build based on detected builder
@@ -218,7 +230,7 @@ func main() {
218230
219231 // Execute build
220232 if err := build .Execute (buildConfig , ctx ); err != nil {
221- logger . Fatal ( "Build failed: %v" , err )
233+ return fmt . Errorf ( "build failed: %v" , err )
222234 }
223235
224236 // Push images if not disabled
@@ -234,7 +246,7 @@ func main() {
234246
235247 digestMap , err := build .Push (pushConfig )
236248 if err != nil {
237- logger . Fatal ( "Push failed: %v" , err )
249+ return fmt . Errorf ( "push failed: %v" , err )
238250 }
239251
240252 // Save digest information after successful push
@@ -243,7 +255,7 @@ func main() {
243255 }
244256 }
245257
246- logger . Info ( "Build completed successfully!" )
258+ return nil
247259}
248260
249261// convertAttestationConfigs converts main package AttestationConfig to build package AttestationConfig
0 commit comments