Bugfix involving path resolution in the archive stage

This commit is contained in:
2026-05-17 11:03:02 -05:00
parent 3ba564b00f
commit b065663180

View File

@@ -18,6 +18,10 @@ import (
)
type archiveStage struct{}
type archiveUploadFile struct {
RelativePath string
LocalPath string
}
var archivePrerequisiteStages = []string{
"prepare",
@@ -112,7 +116,12 @@ func (archiveStage) Run(ctx context.Context, env *Env, m *manifest.Manifest) (*S
return nil, fmt.Errorf("archive: run id is required")
}
runFiles, err := collectArchiveRunFiles(workDir)
manifestSource, err := resolveArchiveManifestSource(env, m, workDir)
if err != nil {
return nil, fmt.Errorf("archive: resolve manifest source: %w", err)
}
runFiles, err := collectArchiveRunFiles(workDir, manifestSource)
if err != nil {
return nil, fmt.Errorf("archive: collect run files: %w", err)
}
@@ -120,21 +129,13 @@ func (archiveStage) Run(ctx context.Context, env *Env, m *manifest.Manifest) (*S
if err != nil {
return nil, fmt.Errorf("archive: resolve promotion rules: %w", err)
}
currentManifestSource := filepath.Join(workDir, "manifest.json")
if info, err := os.Stat(currentManifestSource); err != nil {
return nil, fmt.Errorf("archive: current manifest source %q: %w", currentManifestSource, err)
} else if info.IsDir() {
return nil, fmt.Errorf("archive: current manifest source %q is a directory", currentManifestSource)
}
runUploaded := make([]string, 0, len(runFiles))
for _, rel := range runFiles {
localPath := filepath.Join(workDir, filepath.FromSlash(rel))
key := artifacts.S3RunRelativeDestinationKey(runPrefix, rel)
if _, err := env.ObjectStore.Upload(ctx, localPath, key, storage.UploadOptions{}); err != nil {
return nil, fmt.Errorf("archive: upload run file %q to %q: %w", rel, key, err)
for _, file := range runFiles {
key := artifacts.S3RunRelativeDestinationKey(runPrefix, file.RelativePath)
if _, err := env.ObjectStore.Upload(ctx, file.LocalPath, key, storage.UploadOptions{}); err != nil {
return nil, fmt.Errorf("archive: upload run file %q to %q: %w", file.RelativePath, key, err)
}
runUploaded = append(runUploaded, rel)
runUploaded = append(runUploaded, file.RelativePath)
}
promotedUploaded := make([]string, 0, len(promotions))
@@ -375,8 +376,8 @@ func resolveWorkDirRelativePath(workDir, rel string) (string, error) {
return cleanedFull, nil
}
func collectArchiveRunFiles(workDir string) ([]string, error) {
files := make([]string, 0, 64)
func collectArchiveRunFiles(workDir, manifestPath string) ([]archiveUploadFile, error) {
files := make([]archiveUploadFile, 0, 64)
for _, dirName := range archiveRunUploadDirs {
fullDir := filepath.Join(workDir, dirName)
@@ -403,30 +404,72 @@ func collectArchiveRunFiles(workDir string) ([]string, error) {
return fmt.Errorf("relative path from %q to %q: %w", workDir, path, err)
}
rel = filepath.ToSlash(rel)
files = append(files, rel)
files = append(files, archiveUploadFile{
RelativePath: rel,
LocalPath: path,
})
return nil
}); err != nil {
return nil, fmt.Errorf("walk %q: %w", fullDir, err)
}
}
manifestPath := filepath.Join(workDir, "manifest.json")
manifestInfo, err := os.Stat(manifestPath)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("manifest.json not found in workdir %q", workDir)
return nil, fmt.Errorf("manifest.json not found (checked path %q)", manifestPath)
}
return nil, fmt.Errorf("stat %q: %w", manifestPath, err)
}
if manifestInfo.IsDir() {
return nil, fmt.Errorf("manifest path %q is a directory", manifestPath)
}
files = append(files, "manifest.json")
files = append(files, archiveUploadFile{
RelativePath: "manifest.json",
LocalPath: manifestPath,
})
sort.Strings(files)
sort.Slice(files, func(i, j int) bool {
return files[i].RelativePath < files[j].RelativePath
})
return files, nil
}
func resolveArchiveManifestSource(env *Env, m *manifest.Manifest, workDir string) (string, error) {
candidates := make([]string, 0, 3)
candidates = append(candidates, filepath.Join(workDir, "manifest.json"))
sessionID := strings.TrimSpace(env.Config.Session.SessionID)
if sessionID == "" && m != nil {
sessionID = strings.TrimSpace(m.SessionID)
}
if sessionID != "" {
sessionManifest := filepath.Join(artifacts.SessionWorkDir(env.Config.Pipeline.Workspace.Root, sessionID), "manifest.json")
candidates = append(candidates, sessionManifest)
}
seen := make(map[string]struct{}, len(candidates))
for _, candidate := range candidates {
clean := filepath.Clean(candidate)
if _, ok := seen[clean]; ok {
continue
}
seen[clean] = struct{}{}
info, err := os.Stat(clean)
if err != nil {
if os.IsNotExist(err) {
continue
}
return "", fmt.Errorf("stat %q: %w", clean, err)
}
if info.IsDir() {
continue
}
return clean, nil
}
return "", fmt.Errorf("manifest.json not found in run workdir or session workdir")
}
func writeCurrentManifestSnapshot(m *manifest.Manifest, archiveMetadata map[string]any) (string, error) {
if m == nil {
return "", fmt.Errorf("manifest is required")