func (r *Reporter) PublishArtifacts(cmdCnf client.ConfigCmd, a adapter.Adapter, clientLog *client.Log) { r.runWithDeadline(r.deadline, func() { if r.bucket == nil { return } if len(cmdCnf.Artifacts) == 0 { return } matches, err := a.CollectArtifacts(cmdCnf.Artifacts, clientLog) if err != nil { clientLog.Writeln(fmt.Sprintf("[artifactstore] ERROR filtering artifacts: " + err.Error())) return } var wg sync.WaitGroup for _, artifact := range matches { wg.Add(1) go func(artifact string) { defer wg.Done() log.Println(fmt.Sprintf("[artifactstore] Uploading: %s", artifact)) fileBaseName := filepath.Base(artifact) if f, err := os.Open(artifact); err != nil { clientLog.Writeln(fmt.Sprintf("[artifactstore] Error opening file for streaming %s: %s", artifact, err)) return } else if stat, err := f.Stat(); err != nil { clientLog.Writeln(fmt.Sprintf("[artifactstore] Error stat'ing file for streaming %s: %s", artifact, err)) return } else if sAfct, err := r.bucket.NewStreamedArtifact(fileBaseName, stat.Size()); err != nil { clientLog.Writeln(fmt.Sprintf("[artifactstore] Error creating streaming artifact for %s: %s", artifact, err)) return } else { // TODO: If possible, avoid reading entire contents of the file into memory, and pass the // file io.Reader directly to http.Post. // // The reason it is done this way is because, using bytes.NewReader() ensures that // Content-Length header is set to a correct value. If not, it is left blank. Alternately, // we could remove this requirement from the server where Content-Length is verified before // starting upload to S3. if contents, err := ioutil.ReadAll(f); err != nil { clientLog.Writeln(fmt.Sprintf("[artifactstore] Error reading file for streaming %s: %s", artifact, err)) return } else if err := sAfct.UploadArtifact(bytes.NewReader(contents)); err != nil { // TODO retry if not a terminal error clientLog.Writeln(fmt.Sprintf("[artifactstore] Error uploading contents of %s: %s", artifact, err)) return } else { clientLog.Writeln(fmt.Sprintf("[artifactstore] Successfully uploaded artifact %s to %s", artifact, sAfct.GetContentURL())) } } }(artifact) } wg.Wait() }) }
func (r *Reporter) PublishArtifacts(cmd client.ConfigCmd, a adapter.Adapter, clientLog *client.Log) { if len(cmd.Artifacts) == 0 { clientLog.Writeln("==> Skipping artifact collection") return } clientLog.Writeln(fmt.Sprintf("==> Collecting artifacts matching %s", cmd.Artifacts)) matches, err := a.CollectArtifacts(cmd.Artifacts, clientLog) if err != nil { clientLog.Writeln(fmt.Sprintf("==> ERROR: " + err.Error())) return } for _, artifact := range matches { clientLog.Writeln(fmt.Sprintf("==> Found: %s", artifact)) } r.pushArtifacts(matches) }