Skip to content

Commit 0ac8005

Browse files
retlehsclaude
andcommitted
Fix p2/ migration: upload all p2/ files when not yet at top level
The p2/ skip logic was trusting the local diff even when p2/ files had never been uploaded to the top-level prefix on R2. Added hasSharedP2 detection (checks if metadata-url is unprefixed) to force a full p2/ upload on the first deploy with the new layout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 687df76 commit 0ac8005

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

internal/deploy/r2.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,11 @@ func SyncToR2(ctx context.Context, cfg config.R2Config, buildDir, buildID, previ
7979
return fmt.Errorf("walking build files: %w", err)
8080
}
8181

82-
// Check if the current R2 root already uses the shared p/ prefix layout.
83-
// If not (first deploy after upgrade from old release-prefixed layout),
84-
// we must upload all shared files — they don't exist at the top level yet.
82+
// Check if the current R2 root already uses the shared layout.
83+
// If not, we must upload all files — they don't exist at the top level yet.
8584
previousShared := collectSharedFiles(previousBuildDir)
86-
if len(previousShared) > 0 {
85+
skipUnchangedP2 := previousBuildDir != ""
86+
if previousBuildDir != "" {
8787
live, err := fetchLiveRelease(ctx, client, cfg.Bucket)
8888
if err != nil {
8989
return fmt.Errorf("checking R2 layout: %w", err)
@@ -92,6 +92,10 @@ func SyncToR2(ctx context.Context, cfg config.R2Config, buildDir, buildID, previ
9292
logger.Info("R2 sync: shared p/ prefix not yet on R2, uploading all shared files")
9393
previousShared = nil
9494
}
95+
if !live.hasSharedP2 {
96+
logger.Info("R2 sync: shared p2/ prefix not yet on R2, uploading all p2/ files")
97+
skipUnchangedP2 = false
98+
}
9599
}
96100

97101
sortBuildFiles2(filePaths)
@@ -126,8 +130,9 @@ func SyncToR2(ctx context.Context, cfg config.R2Config, buildDir, buildID, previ
126130
return fmt.Errorf("R2 sync: %w", err)
127131
}
128132
} else if strings.HasPrefix(relPath, "p2/") {
129-
// Mutable p2/ file — skip if unchanged from previous build.
130-
if fileUnchanged(previousBuildDir, buildDir, relPath) {
133+
// Mutable p2/ file — skip if unchanged from previous build
134+
// and p2/ files already exist at top level on R2.
135+
if skipUnchangedP2 && fileUnchanged(previousBuildDir, buildDir, relPath) {
131136
skipped.Add(1)
132137
return nil
133138
}
@@ -464,6 +469,9 @@ type liveReleaseResult struct {
464469
// prefix (new layout). False means the old layout where p/ files lived under
465470
// releases/<id>/p/... — shared files have not been uploaded to the top level yet.
466471
hasSharedPrefix bool
472+
// hasSharedP2 is true when metadata-url points at the shared top-level p2/
473+
// prefix. False means p2/ files still live under releases/<id>/p2/.
474+
hasSharedP2 bool
467475
// exists is true when a root packages.json was found on R2.
468476
exists bool
469477
}
@@ -518,6 +526,14 @@ func fetchLiveRelease(ctx context.Context, client r2API, bucket string) (liveRel
518526
result.hasSharedPrefix = !strings.HasPrefix(pu, "releases/")
519527
}
520528

529+
// Detect whether p2/ files are at the shared top-level prefix.
530+
// Old layout: metadata-url = "/releases/<id>/p2/%package%.json"
531+
// New layout: metadata-url = "/p2/%package%.json"
532+
if mu, ok := pkg["metadata-url"].(string); ok {
533+
mu = strings.TrimPrefix(mu, "/")
534+
result.hasSharedP2 = !strings.HasPrefix(mu, "releases/")
535+
}
536+
521537
return result, nil
522538
}
523539

0 commit comments

Comments
 (0)