8000 feat: track progress on image pull/push by AustinAbro321 · Pull Request #3904 · zarf-dev/zarf · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: track progress on image pull/push #3904

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

AustinAbro321
Copy link
Contributor
@AustinAbro321 AustinAbro321 commented Jun 10, 2025

Description

This introduces occasional log statements to give progress during OCI pulls and pushes (images and Zarf packages).

Implementation was loosely inspired by the progressbar implementation in the ORAS CLI. Goal was to create simple a simple solution that avoids leaving users without feedback from the system for more than five seconds. UX was designed to be similar to how opentofu gives occasional progress feedback when something takes a while.

Views:
image pull on create:
image
image push on deploy (lowered interval for screenshot because local pushes are fast):
image
package pull:
image
package publish:
image

Related Issue

Fixes #3633

Checklist before merging

Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Copy link
netlify bot commented Jun 10, 2025

Deploy Preview for zarf-docs canceled.

Name Link
🔨 Latest commit 2b78774
🔍 Latest deploy log https://app.netlify.com/projects/zarf-docs/deploys/6852e8665a699400088da71b

Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Copy link
codecov bot commented Jun 10, 2025

Codecov Report

Attention: Patch coverage is 71.42857% with 42 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/internal/packager/images/pull.go 60.46% 11 Missing and 6 partials ⚠️
src/internal/packager/images/progress.go 80.88% 11 Missing and 2 partials ⚠️
src/pkg/zoci/pull.go 0.00% 7 Missing ⚠️
src/internal/packager/images/push.go 70.58% 4 Missing and 1 partial ⚠️
Files with missing lines Coverage Δ
src/pkg/zoci/push.go 69.79% <100.00%> (+2.37%) ⬆️
src/internal/packager/images/push.go 52.84% <70.58%> (+1.62%) ⬆️
src/pkg/zoci/pull.go 57.05% <0.00%> (-2.19%) ⬇️
src/internal/packager/images/progress.go 80.88% <80.88%> (ø)
src/internal/packager/images/pull.go 53.16% <60.46%> (+0.40%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
@AustinAbro321 AustinAbro321 marked this pull request as ready for review June 18, 2025 12:21
@AustinAbro321 AustinAbro321 requested review from a team as code owners June 18, 2025 12:21
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's easier to review this with whitespace hidden

Copy link
Member
@brandtkeller brandtkeller left a comment

Choose a reason for hiding this comment

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

I love improvements that hits the UX. Minor items that come to mind - also believe some of this could be potentially unit tested in some capacity?

const defaultProgressInterval = 5 * time.Second

// StartReporting starts the reporting goroutine
func (tt *TrackedTarget) StartReporting() {
Copy link
Member

Choose a reason for hiding this comment

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

Given that the push is governed by the caller-supplied context - I wonder if this should accept context and if we could remove more of the bespoke stopReports in favor of a ctx.Done()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it should definitely accept a context. Though to get rid of the StopReporting call we'd have to make a separate context for StartReporting then cancel it. I like the feel of the defer StopReporting slightly more, but I don't feel too strongly either way


const defaultProgressInterval = 5 * time.Second

// StartReporting starts the reporting goroutine
Copy link
Member

Choose a reason for hiding this comment

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

What happens if StartReporting is called twice? is there any potential state that needs to be tracked?

Copy link
Contributor Author
@AustinAbro321 AustinAbro321 Jun 18, 2025

Choose a reason for hiding this comment

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

It would duplicate the log calls. Not sure if I should add a boolean like reportingStarted on the Tracker object and return if so.

On one hand we wouldn't want duplicate logging calls to happen for the same object. On the other hand, there is no situation where startReporting should be called twice without StopReporting called inbetween, so having the check for duplicate calls makes it easier for mistakes like that to go unnoticed. LMK what you think.

}

// NewTrackedTarget creates a new TrackedTarget
func NewTrackedTarget(target oras.Target, totalBytes int64, reporter Report) *TrackedTarget {
Copy link
Member

Choose a reason for hiding this comment

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

Is there any value in making interval configurable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe in the future, given that this is internal and we want the same interval everywhere. I didn't expose the interval


// Push wraps the target push method with an appropriate tracked reader.
func (tt *TrackedTarget) Push(ctx context.Context, desc ocispec.Descriptor, content io.Reader) error {
tReader := &trackedReader{
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a nit - I think we could potentially do without the temporary trackedReader

if wt, ok := content.(io.WriterTo); ok {
    tracked := &trackedWriterToReader{writerTo: wt, bytesRead: &tt.bytesRead}
    return tt.Target.Push(ctx, desc, tracked)
}
return tt.Target.Push(ctx, desc, &trackedReader{reader: content, bytesRead: &tt.bytesRead})

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like embedding the trackedReader into the trackedWritertoReader struct this way we don't have to maintain another Read method on the trackedWritertoReader, it'll just use the trackedReader object.

Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
Signed-off-by: Austin Abro <AustinAbro321@gmail.com>
@AustinAbro321
Copy link
Contributor Author

@brandtkeller Separated out the Tracker object and created a unit test for it. I wanted to avoid creating a registry or mocking an oras.target for the test. I feel it's a reasonable test, but a bit jank. There might be way to better structure the code for easier unit tests, open to alternative ideas.

)

// newTestTracker creates a Tracker instance with a customizable report interval for testing.
func newTestTracker(bytesRead, totalBytes int64, reporter Report, interval time.Duration) *Tracker {
Copy link
Contributor

Choose a reason for hiding this comment

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

++

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.

Give occasional progress updates during image pull and pushes
3 participants
0