Skip to content

Commit b9cf497

Browse files
author
Anket Satbhai
committed
update smurf sdkr push gcp logs
1 parent 66d38c4 commit b9cf497

1 file changed

Lines changed: 102 additions & 56 deletions

File tree

internal/docker/pushGcr.go

Lines changed: 102 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,97 @@ import (
1616
"golang.org/x/oauth2/google"
1717
)
1818

19-
type MinimalLogger struct {
20-
startTime time.Time
21-
lastLayer string
22-
lastProgress string
19+
// Color codes
20+
const (
21+
colorReset = "\033[0m"
22+
colorRed = "\033[31m"
23+
colorGreen = "\033[32m"
24+
colorYellow = "\033[33m"
25+
colorBlue = "\033[34m"
26+
colorMagenta = "\033[35m"
27+
colorCyan = "\033[36m"
28+
colorWhite = "\033[37m"
29+
)
30+
31+
type FancyLogger struct {
32+
startTime time.Time
33+
lastUpdate map[string]float64
34+
layerWidth int
35+
spinnerStates []string
36+
spinnerIndex int
37+
}
38+
39+
func NewFancyLogger() *FancyLogger {
40+
return &FancyLogger{
41+
startTime: time.Now(),
42+
lastUpdate: make(map[string]float64),
43+
layerWidth: 12, // Truncate long layer IDs
44+
spinnerStates: []string{"⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾"},
45+
}
2346
}
2447

25-
func NewMinimalLogger() *MinimalLogger {
26-
return &MinimalLogger{startTime: time.Now()}
48+
func (l *FancyLogger) getSpinner() string {
49+
l.spinnerIndex = (l.spinnerIndex + 1) % len(l.spinnerStates)
50+
return l.spinnerStates[l.spinnerIndex]
2751
}
2852

29-
func (l *MinimalLogger) logStep(message string) {
30-
fmt.Printf("[%s] %s\n", time.Since(l.startTime).Round(time.Millisecond), message)
53+
func (l *FancyLogger) logHeader(message string) {
54+
fmt.Printf("%s[%s] %s %s%s%s\n", colorBlue, time.Since(l.startTime).Round(time.Millisecond), "⚡", colorCyan, message, colorReset)
3155
}
3256

33-
func (l *MinimalLogger) logSuccess(message string) {
34-
fmt.Printf("[%s] %s\n", time.Since(l.startTime).Round(time.Millisecond), message)
57+
func (l *FancyLogger) logSuccess(message string) {
58+
fmt.Printf("%s[%s] %s %s%s%s\n", colorGreen, time.Since(l.startTime).Round(time.Millisecond), "✓", colorGreen, message, colorReset)
3559
}
3660

37-
func (l *MinimalLogger) logProgress(layer, operation string, current, total int64) {
38-
progress := ""
39-
if total > 0 {
40-
progress = fmt.Sprintf(" (%.1f%%)", float64(current)/float64(total)*100)
61+
func (l *FancyLogger) logProgress(layer, operation string, percent float64) {
62+
// Truncate layer ID for display
63+
displayLayer := layer
64+
if len(layer) > l.layerWidth {
65+
displayLayer = layer[:l.layerWidth] + "..."
4166
}
42-
msg := fmt.Sprintf("%s: %s%s", layer, operation, progress)
4367

44-
if msg != l.lastProgress {
45-
fmt.Printf("[%s] ↳ %s\n", time.Since(l.startTime).Round(time.Millisecond), msg)
46-
l.lastProgress = msg
68+
// Only update if:
69+
// - Operation changed
70+
// - Progress increased by at least 5%
71+
// - It's the first update for this layer
72+
lastPercent, exists := l.lastUpdate[layer]
73+
if !exists || operation != "" || percent-lastPercent >= 5 || percent == 100 {
74+
bar := l.progressBar(percent)
75+
spinner := l.getSpinner()
76+
fmt.Printf("\r%s[%s] %s %s: %s %s %s",
77+
colorYellow,
78+
time.Since(l.startTime).Round(time.Millisecond),
79+
spinner,
80+
colorMagenta+displayLayer+colorReset,
81+
operation,
82+
bar,
83+
fmt.Sprintf("%5.1f%%", percent))
84+
85+
if percent == 100 {
86+
fmt.Println() // New line when complete
87+
}
88+
l.lastUpdate[layer] = percent
4789
}
4890
}
4991

50-
func (l *MinimalLogger) logFinal(message string) {
51-
fmt.Printf("[%s] ★ %s\n", time.Since(l.startTime).Round(time.Millisecond), message)
92+
func (l *FancyLogger) progressBar(percent float64) string {
93+
const width = 20
94+
completed := int(percent / 5)
95+
if completed > width {
96+
completed = width
97+
}
98+
return fmt.Sprintf("%s%s%s%s",
99+
colorGreen,
100+
strings.Repeat("█", completed),
101+
colorWhite,
102+
strings.Repeat("░", width-completed))
103+
}
104+
105+
func (l *FancyLogger) logFinal(message string) {
106+
fmt.Printf("%s[%s] %s %s%s%s\n", colorMagenta, time.Since(l.startTime).Round(time.Millisecond), "✨", colorMagenta, message, colorReset)
52107
}
53108

109+
// Helper function to parse image name and tag
54110
func parseImageName(imageNameWithTag string) (string, string) {
55111
parts := strings.Split(imageNameWithTag, ":")
56112
if len(parts) == 2 {
@@ -59,13 +115,17 @@ func parseImageName(imageNameWithTag string) (string, string) {
59115
return imageNameWithTag, "latest"
60116
}
61117

118+
// Helper function to build tagged image name
62119
func buildTaggedImageName(projectID, imageName, imageTag string) string {
120+
// If image already contains registry info, use as-is
63121
if strings.Contains(imageName, "gcr.io") || strings.Contains(imageName, "docker.pkg.dev") {
64122
return fmt.Sprintf("%s:%s", imageName, imageTag)
65123
}
124+
// Otherwise prepend gcr.io registry
66125
return fmt.Sprintf("gcr.io/%s/%s:%s", projectID, imageName, imageTag)
67126
}
68127

128+
// Helper function to build GCR console link
69129
func buildGCRLink(projectID, imageName string) string {
70130
registryType := "gcr"
71131
if strings.Contains(imageName, "docker.pkg.dev") {
@@ -76,95 +136,81 @@ func buildGCRLink(projectID, imageName string) string {
76136
}
77137

78138
func PushImageToGCR(projectID, imageNameWithTag string) error {
79-
logger := NewMinimalLogger()
139+
logger := NewFancyLogger()
80140
ctx := context.Background()
81141

82-
// Initial setup
83-
logger.logStep("Starting image push to GCR")
142+
logger.logHeader("Starting GCR image push")
84143
defer func() {
85-
logger.logStep("Push operation completed")
144+
logger.logHeader("Push operation completed")
86145
}()
87146

88147
// Authentication
89-
logger.logStep("Authenticating with Google Cloud")
90148
creds, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/cloud-platform")
91149
if err != nil {
92-
return fmt.Errorf("authentication failed: %v", err)
150+
return fmt.Errorf("%sauthentication failed%s: %v", colorRed, colorReset, err)
93151
}
94152
logger.logSuccess("Google Cloud authenticated")
95153

96-
logger.logStep("Obtaining access token")
97154
token, err := creds.TokenSource.Token()
98155
if err != nil {
99-
return fmt.Errorf("token acquisition failed: %v", err)
156+
return fmt.Errorf("%stoken acquisition failed%s: %v", colorRed, colorReset, err)
100157
}
101158

102159
// Docker client
103-
logger.logStep("Creating Docker client")
104160
dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
105161
if err != nil {
106-
return fmt.Errorf("docker client creation failed: %v", err)
162+
return fmt.Errorf("%sdocker client creation failed%s: %v", colorRed, colorReset, err)
107163
}
108164

109165
// Image tagging
110166
imageName, imageTag := parseImageName(imageNameWithTag)
111167
taggedImage := buildTaggedImageName(projectID, imageName, imageTag)
112168

113-
logger.logStep(fmt.Sprintf("Tagging image as: %s", taggedImage))
114169
if err := dockerClient.ImageTag(ctx, fmt.Sprintf("%s:%s", imageName, imageTag), taggedImage); err != nil {
115-
return fmt.Errorf("image tagging failed: %v", err)
170+
return fmt.Errorf("%simage tagging failed%s: %v", colorRed, colorReset, err)
116171
}
117-
logger.logSuccess("Image successfully tagged")
172+
logger.logSuccess(fmt.Sprintf("Image tagged: %s%s%s", colorCyan, taggedImage, colorReset))
118173

119174
// Image push
120-
logger.logStep("Preparing to push image")
121175
authConfig := registry.AuthConfig{
122176
Username: "oauth2accesstoken",
123177
Password: token.AccessToken,
124178
ServerAddress: "https://gcr.io",
125179
}
126180
encodedAuth, err := encodeAuthToBase64(authConfig)
127181
if err != nil {
128-
return fmt.Errorf("auth encoding failed: %v", err)
182+
return fmt.Errorf("%sauth encoding failed%s: %v", colorRed, colorReset, err)
129183
}
130184

131185
pushResponse, err := dockerClient.ImagePush(ctx, taggedImage, image.PushOptions{
132186
RegistryAuth: encodedAuth,
133187
})
134188
if err != nil {
135-
return fmt.Errorf("image push failed: %v", err)
189+
return fmt.Errorf("%spush failed%s: %v", colorRed, colorReset, err)
136190
}
137191
defer pushResponse.Close()
138192

139-
// Minimal push progress logging
140-
logger.logStep("Starting image push")
193+
// Fancy progress logging
194+
logger.logHeader("Pushing image layers")
141195
dec := json.NewDecoder(pushResponse)
142196
for {
143197
var event jsonmessage.JSONMessage
144198
if err := dec.Decode(&event); err != nil {
145199
if err == io.EOF {
146200
break
147201
}
148-
return fmt.Errorf("push response read failed: %v", err)
202+
return fmt.Errorf("%spush response failed%s: %v", colorRed, colorReset, err)
149203
}
150204
if event.Error != nil {
151-
return fmt.Errorf("push failed: %v", event.Error)
205+
return fmt.Errorf("%spush failed%s: %v", colorRed, colorReset, event.Error)
152206
}
153207

154-
if event.ID != "" && event.Status != "" {
155-
current := int64(0)
156-
total := int64(0)
157-
if event.Progress != nil {
158-
current = event.Progress.Current
159-
total = event.Progress.Total
160-
}
161-
162-
// Only log significant events
163-
if event.ID != logger.lastLayer ||
164-
(total > 0 && (current == 0 || current == total || current%(total/10) == 0)) {
165-
logger.logProgress(event.ID, event.Status, current, total)
166-
logger.lastLayer = event.ID
208+
if event.ID != "" {
209+
percent := 0.0
210+
if event.Progress != nil && event.Progress.Total > 0 {
211+
percent = float64(event.Progress.Current) / float64(event.Progress.Total) * 100
167212
}
213+
logger.logProgress(event.ID, event.Status, percent)
168214
}
169215
}
170216

@@ -177,9 +223,9 @@ func PushImageToGCR(projectID, imageNameWithTag string) error {
177223
}
178224
}
179225

180-
logger.logFinal(fmt.Sprintf("Image successfully pushed to GCR"))
181-
logger.logFinal(fmt.Sprintf("View in console: %s", link))
182-
logger.logFinal(fmt.Sprintf("Image reference: %s", taggedImage))
226+
logger.logFinal(fmt.Sprintf("Image pushed successfully!"))
227+
logger.logFinal(fmt.Sprintf("View in console: %s%s%s", colorCyan, link, colorReset))
228+
logger.logFinal(fmt.Sprintf("Image reference: %s%s%s", colorCyan, taggedImage, colorReset))
183229

184230
return nil
185231
}

0 commit comments

Comments
 (0)