From 6ba26180dcc77bbbeb6b3a1d2376bc3bee024f20 Mon Sep 17 00:00:00 2001 From: John Soo Date: Fri, 11 Mar 2022 11:10:12 -0800 Subject: [PATCH] Collect artifacts in directories. --- agent/artifact_uploader.go | 67 +++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/agent/artifact_uploader.go b/agent/artifact_uploader.go index 585cfc34bc..a92d93b6c9 100644 --- a/agent/artifact_uploader.go +++ b/agent/artifact_uploader.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "runtime" @@ -103,7 +104,71 @@ func (a *ArtifactUploader) Collect() (artifacts []*api.Artifact, err error) { // file paths are deduplicated after resolving globs etc seenPaths := make(map[string]bool) - for _, globPath := range strings.Split(a.conf.Paths, ArtifactPathDelimiter) { + prospects := strings.Split(a.conf.Paths, ArtifactPathDelimiter) + + // Handle directories first + for _, literalPath := range prospects { + // I think this is a bug; ' name.ext ' is a valid filepath. + // Keeping it because it was handled in the globbing case. + literalPath = strings.TrimSpace(literalPath) + if literalPath == "" { + continue + } + + a.logger.Debug("Searching for %s", literalPath) + + absolutePath, err := filepath.Abs(literalPath) + if err != nil { + return nil, err + } + + if _, ok := seenPaths[absolutePath]; ok { + a.logger.Debug("Skipping duplicate path %s", literalPath) + continue + } + + if isDir(absolutePath) { + a.logger.Debug("Searching for %s", literalPath) + + err := filepath.WalkDir(absolutePath, func(p string, d fs.DirEntry, error error) error { + seenPaths[p] = true + + if error != nil { + return error + } + if d.IsDir() { + return nil + } else if a.conf.FollowSymlinks { + // FIXME: Resolve symlink relative to cwd and set seenPaths + } else { + path, err := filepath.Rel(wd, p) + if err != nil { + return err + } + + if experiments.IsEnabled(`normalised-upload-paths`) { + // Convert any Windows paths to Unix/URI form + path = filepath.ToSlash(path) + } + + // Build an artifact object using the paths we have. + artifact, err := a.build(path, p, literalPath) + if err != nil { + return err + } + + artifacts = append(artifacts, artifact) + } + + return nil + }) + if err != nil { + return nil, err + } + } + } + + for _, globPath := range prospects { globPath = strings.TrimSpace(globPath) if globPath == "" { continue