diff --git a/internal/build/util.go b/internal/build/util.go index 34cd6d4544..cd6db09d00 100644 --- a/internal/build/util.go +++ b/internal/build/util.go @@ -17,6 +17,7 @@ package build import ( + "bufio" "bytes" "flag" "fmt" @@ -116,7 +117,6 @@ func render(tpl *template.Template, outputFile string, outputPerm os.FileMode, x // the form sftp://[user@]host[:port]. func UploadSFTP(identityFile, host, dir string, files []string) error { sftp := exec.Command("sftp") - sftp.Stdout = os.Stdout sftp.Stderr = os.Stderr if identityFile != "" { sftp.Args = append(sftp.Args, "-i", identityFile) @@ -131,6 +131,10 @@ func UploadSFTP(identityFile, host, dir string, files []string) error { if err != nil { return fmt.Errorf("can't create stdin pipe for sftp: %v", err) } + stdout, err := sftp.StdoutPipe() + if err != nil { + return fmt.Errorf("can't create stdout pipe for sftp: %v", err) + } if err := sftp.Start(); err != nil { return err } @@ -139,24 +143,34 @@ func UploadSFTP(identityFile, host, dir string, files []string) error { fmt.Fprintln(in, "put", f, path.Join(dir, filepath.Base(f))) } fmt.Fprintln(in, "exit") - // Avoid travis timout after 10m of inactivity by printing something - // every 8 minutes. - done := make(chan bool) + // Some issue with the PPA sftp server makes it so the server does not + // respond properly to a 'bye', 'exit' or 'quit' from the client. + // To work around that, we check the output, and when we see the client + // exit command, we do a hard exit. + // See + // https://github.com/kolban-google/sftp-gcs/issues/23 + // https://github.com/mscdex/ssh2/pull/1111 + aborted := false go func() { - for { - select { - case <-time.After(8 * time.Minute): - fmt.Println("keepalive log") - continue - case <-done: - return + scanner := bufio.NewScanner(stdout) + for scanner.Scan() { + txt := scanner.Text() + fmt.Println(txt) + if txt == "sftp> exit" { + // Give it .5 seconds to exit (server might be fixed), then + // hard kill it from the outside + time.Sleep(500 * time.Millisecond) + aborted = true + sftp.Process.Kill() } - } }() stdin.Close() - defer close(done) - return sftp.Wait() + err = sftp.Wait() + if aborted { + return nil + } + return err } // FindMainPackages finds all 'main' packages in the given directory and returns their