Skip to content

Add retry logic for retrieving top layer SHA with registry mirrors#1675

Merged
jabrown85 merged 10 commits into
buildpacks:mainfrom
vpelikh:GH-1674
Jun 19, 2026
Merged

Add retry logic for retrieving top layer SHA with registry mirrors#1675
jabrown85 merged 10 commits into
buildpacks:mainfrom
vpelikh:GH-1674

Conversation

@vpelikh

@vpelikh vpelikh commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds retry logic to mitigate intermittent failures when retrieving the top layer SHA from registry mirrors. Registry mirrors may temporarily return incomplete manifests as layers sync, causing the image has no layers error. The retry mechanism gives the mirror time to stabilize.

Release notes

When using registry mirrors, the lifecycle will now retry top layer retrieval up to 5 times with exponential backoff before failing.


Related

Resolves #1674


Context

  • Added OpenRemoteImage function in phase/retry.go with 5 retry attempts
  • Exponential backoff delays: 100ms → 200ms → 500ms → 1s → 2s
  • Exporter and Rebaser now use OpenRemoteImage instead of direct TopLayer() calls
  • All existing tests pass

@vpelikh vpelikh requested a review from a team as a code owner June 17, 2026 19:08
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated

@vpelikh vpelikh left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jabrown85 , thank you for the thorough review! I've gone through all your comments and pushed the necessary fixes. The PR should be ready for another look when you have a moment.

Really appreciate your time and attention to detail!

Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go
Metadata files.LauncherMetadata
}

// ExportOptions is the set of options for exporting an image.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jabrown85, linting fail without comment for ExportOptions and Rebaser. Should I keep it?

Comment thread cmd/lifecycle/exporter.go Outdated
Comment thread cmd/lifecycle/rebaser.go Outdated
vpelikh added 6 commits June 19, 2026 10:18
- Add TopLayerWithRetry function with exponential backoff for transient registry errors
- Exporter and Rebaser now use TopLayerWithRetry instead of direct TopLayer calls
- Return error directly from TopLayerWithRetry (callers wrap with context)
- Delays made constant to avoid recreation on each call

Closes: buildpacks#1674
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
TopLayerWithRetry now accepts an image factory to create fresh images per retry attempt, bypassing go-containerregistry's manifest cache for registry mirrors. Non-retryable errors (401, 403) are returned immediately without retry. Retry uses backoff delays (100ms-2s) with a final bare attempt.

Exporter and rebaser callers provide factory closures for remote images.

Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
Simplify retry architecture by replacing WorkingImageFactory/NewBaseImageFactory plumbing with a single OpenRemoteImage function that opens a remote image with retry logic for registry mirror transient errors.

Changes:
- Add phase.OpenRemoteImage(logger, newImage func()) that retries both image creation and TopLayer() sniff test on transient errors
- Remove TopLayerWithRetry from phase package
- Remove WorkingImageFactory from ExportOptions and NewBaseImageFactory from Rebaser struct
- Update cmd callers to use OpenRemoteImage directly
- Remove factory plumbing from cmd/lifecycle/exporter.go initRemoteAppImage and cmd/lifecycle/rebaser.go Exec()
- Rewrite retry_test.go for OpenRemoteImage API

Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>

@jabrown85 jabrown85 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking much better! A few nits and we'll be ready

Comment thread phase/rebaser.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
Comment thread phase/exporter.go Outdated
vpelikh added 2 commits June 19, 2026 20:36
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
vpelikh added 2 commits June 19, 2026 20:42
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com>
@vpelikh vpelikh requested a review from jabrown85 June 19, 2026 17:53
@jabrown85 jabrown85 merged commit f74dc16 into buildpacks:main Jun 19, 2026
5 checks passed
@vpelikh vpelikh deleted the GH-1674 branch June 19, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lifecycle export fails intermittently with "get run image top layer SHA: image has no layers" when using a registry mirror

2 participants