@@ -169,18 +169,28 @@ export class RemoteClient {
169169 // The log stream will capture it and add it to BuildResults
170170 const successMessage = `Activation successful` ;
171171
172+ // Write directly to log file first to ensure it's captured even if pipe fails
173+ // This is critical for all providers, especially K8s where timing matters
174+ try {
175+ const logFilePath = CloudRunner . isCloudRunnerEnvironment
176+ ? `/home/job-log.txt`
177+ : path . join ( process . cwd ( ) , 'temp' , 'job-log.txt' ) ;
178+ if ( fs . existsSync ( path . dirname ( logFilePath ) ) ) {
179+ fs . appendFileSync ( logFilePath , `${ successMessage } \n` ) ;
180+ }
181+ } catch ( error ) {
182+ // If direct file write fails, continue with other methods
183+ }
184+
172185 // Write to stdout so it gets piped through remote-cli-log-stream when invoked via pipe
173186 // This ensures the message is captured in BuildResults for all providers
174187 // Use synchronous write and ensure newline is included for proper flushing
175188 process . stdout . write ( `${ successMessage } \n` , 'utf8' ) ;
176189
177- // For K8s, also write directly to stdout (not through pipe) to ensure kubectl logs captures it
178- // This is critical because kubectl logs reads from stdout, and the pipe might not process
179- // the message in time before the container exits
190+ // For K8s, also write to stderr as a backup since kubectl logs reads from both stdout and stderr
191+ // This ensures the message is captured even if stdout pipe has issues
180192 if ( CloudRunnerOptions . providerStrategy === 'k8s' ) {
181- // Write directly to stdout so kubectl logs can capture it immediately
182- // This bypasses the pipe to ensure the message is captured even if the pipe fails
183- process . stdout . write ( `${ successMessage } \n` , 'utf8' ) ;
193+ process . stderr . write ( `${ successMessage } \n` , 'utf8' ) ;
184194 }
185195
186196 // Ensure stdout is flushed before process exits (critical for K8s where process might exit quickly)
0 commit comments