Skip to content

Commit 2e02a73

Browse files
committed
Add some nicer log output
1 parent ac28cd9 commit 2e02a73

File tree

3 files changed

+90
-17
lines changed

3 files changed

+90
-17
lines changed

envbuilder.go

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bufio"
55
"bytes"
66
"context"
7+
"encoding/json"
78
"errors"
89
"fmt"
910
"io"
@@ -130,18 +131,21 @@ func Run(ctx context.Context, options Options) error {
130131
}
131132
}
132133

133-
logf("%s - Build development environments from repositories in a container", color.New(color.Bold).Sprintf("envbuilder"))
134+
logf(codersdk.LogLevelInfo, "%s - Build development environments from repositories in a container", newColor(color.Bold).Sprintf("envbuilder"))
134135

135136
if options.GitURL != "" {
136-
endStage := startStage("Cloning Repository %s to %s...", options.GitURL, options.WorkspaceFolder)
137+
endStage := startStage("📦 Cloning %s to %s...",
138+
newColor(color.FgCyan).Sprintf(options.GitURL),
139+
newColor(color.FgCyan).Sprintf(options.WorkspaceFolder),
140+
)
137141

138142
reader, writer := io.Pipe()
139143
defer reader.Close()
140144
defer writer.Close()
141145
go func() {
142146
scanner := bufio.NewScanner(reader)
143147
for scanner.Scan() {
144-
logf("git: %s", scanner.Text())
148+
logf(codersdk.LogLevelInfo, "#1: %s", scanner.Text())
145149
}
146150
}()
147151

@@ -165,7 +169,7 @@ func Run(ctx context.Context, options Options) error {
165169
return err
166170
}
167171

168-
endStage("Cloned Repository")
172+
endStage("📦 Cloned repository!")
169173
}
170174

171175
var buildParams *BuildParameters
@@ -210,12 +214,14 @@ func Run(ctx context.Context, options Options) error {
210214
return fmt.Errorf("read devcontainer.json: %w", err)
211215
}
212216
devContainer, err := ParseDevcontainer(content)
213-
if err != nil {
214-
return fmt.Errorf("parse devcontainer.json: %w", err)
215-
}
216-
buildParams, err = devContainer.Compile(options.Filesystem, devcontainerDir, MagicDir)
217-
if err != nil {
218-
return fmt.Errorf("compile devcontainer.json: %w", err)
217+
if err == nil {
218+
buildParams, err = devContainer.Compile(options.Filesystem, devcontainerDir, MagicDir)
219+
if err != nil {
220+
return fmt.Errorf("compile devcontainer.json: %w", err)
221+
}
222+
} else {
223+
logf(codersdk.LogLevelError, "Failed to parse devcontainer.json: %s", err.Error())
224+
logf(codersdk.LogLevelError, "Falling back to the default image...")
219225
}
220226
}
221227
} else {
@@ -241,10 +247,12 @@ func Run(ctx context.Context, options Options) error {
241247
}
242248

243249
HijackLogrus(func(entry *logrus.Entry) {
244-
logf(codersdk.LogLevelInfo, "#2: %s", entry.Message)
250+
logf(codersdk.LogLevelInfo, "#2: %s", color.HiBlackString(entry.Message))
245251
})
246252

247253
build := func() (v1.Image, error) {
254+
endStage := startStage("🏗️ Building image...")
255+
defer endStage("🏗️ Built image!")
248256
// At this point we have all the context, we can now build!
249257
return executor.DoBuild(&config.KanikoOptions{
250258
// Boilerplate!
@@ -301,6 +309,29 @@ func Run(ctx context.Context, options Options) error {
301309
return fmt.Errorf("get image config: %w", err)
302310
}
303311

312+
// devcontainer metadata can be persisted through a standard label
313+
devContainerMetadata, exists := configFile.Config.Labels["devcontainer.metadata"]
314+
if exists {
315+
var devContainer []*DevContainer
316+
err := json.Unmarshal([]byte(devContainerMetadata), &devContainer)
317+
if err != nil {
318+
return fmt.Errorf("unmarshal metadata: %w", err)
319+
}
320+
logf(codersdk.LogLevelInfo, "#3: 👀 Found devcontainer.json label metadata in image...")
321+
for _, container := range devContainer {
322+
if container.RemoteUser != "" {
323+
logf(codersdk.LogLevelInfo, "#3: 🧑 Updating the user to %q!", container.RemoteUser)
324+
325+
configFile.Config.User = container.RemoteUser
326+
}
327+
if container.RemoteEnv != nil {
328+
for key, value := range container.RemoteEnv {
329+
os.Setenv(key, value)
330+
}
331+
}
332+
}
333+
}
334+
304335
username := configFile.Config.User
305336
if buildParams.User != "" {
306337
username = buildParams.User
@@ -326,6 +357,7 @@ func Run(ctx context.Context, options Options) error {
326357
// in the syscall is what matters.
327358
user.Username = "root"
328359
}
360+
os.Setenv("HOME", user.HomeDir)
329361

330362
// It must be set in this parent process otherwise nothing will be found!
331363
for _, env := range configFile.Config.Env {
@@ -445,7 +477,7 @@ func unsetOptionsEnv() {
445477
}
446478
}
447479

448-
func printOptions(logf func(format string, args ...interface{}), options Options) {
480+
func printOptions(logf func(level codersdk.LogLevel, format string, args ...interface{}), options Options) {
449481
val := reflect.ValueOf(&options).Elem()
450482
typ := val.Type()
451483

@@ -458,13 +490,15 @@ func printOptions(logf func(format string, args ...interface{}), options Options
458490
}
459491
switch fieldTyp.Type.Kind() {
460492
case reflect.String:
461-
logf("option %s: %q", fieldTyp.Name, field.String())
493+
logf(codersdk.LogLevelDebug, "option %s: %q", fieldTyp.Name, field.String())
462494
case reflect.Bool:
463495
field.Bool()
464496
}
465497
}
466498
}
467499

468-
func stage() {
469-
500+
func newColor(value ...color.Attribute) *color.Color {
501+
c := color.New(value...)
502+
c.EnableColor()
503+
return c
470504
}

git.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ func CloneRepo(ctx context.Context, opts CloneRepoOptions) error {
7171
ReferenceName: plumbing.ReferenceName(reference),
7272
InsecureSkipTLS: opts.Insecure,
7373
Tags: git.NoTags,
74-
// SingleBranch: true,
75-
// Depth: 1,
74+
SingleBranch: true,
75+
Depth: 1,
7676
})
7777
if errors.Is(err, git.ErrRepositoryAlreadyExists) {
7878
return nil

integration/integration_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"io"
1010
"net/http"
1111
"net/http/httptest"
12+
"net/http/httputil"
13+
"net/url"
1214
"os/exec"
1315
"strings"
1416
"testing"
@@ -111,7 +113,44 @@ func TestBuildFailsFallback(t *testing.T) {
111113
})
112114
require.ErrorContains(t, err, envbuilder.ErrNoFallbackImage.Error())
113115
})
116+
}
117+
118+
func TestPrivateRegistry(t *testing.T) {
119+
t.Parallel()
120+
t.Run("NoAuth", func(t *testing.T) {
121+
t.Parallel()
122+
image := setupPassthroughRegistry(t, "library/alpine")
123+
124+
fmt.Printf("IMAGE %s\n", image)
125+
time.Sleep(time.Hour)
114126

127+
// Ensures that a Git repository with a Dockerfile is cloned and built.
128+
url := createGitServer(t, gitServerOptions{
129+
files: map[string]string{
130+
"Dockerfile": "FROM " + image,
131+
},
132+
})
133+
_, err := runEnvbuilder(t, []string{
134+
"GIT_URL=" + url,
135+
"DOCKERFILE_PATH=Dockerfile",
136+
})
137+
require.NoError(t, err)
138+
})
139+
}
140+
141+
func setupPassthroughRegistry(t *testing.T, image string) string {
142+
t.Helper()
143+
dockerURL, err := url.Parse("https://registry-1.docker.io")
144+
require.NoError(t, err)
145+
proxy := httputil.NewSingleHostReverseProxy(dockerURL)
146+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
147+
r.Host = "registry-1.docker.io"
148+
r.URL.Host = "registry-1.docker.io"
149+
r.URL.Scheme = "https"
150+
151+
proxy.ServeHTTP(w, r)
152+
}))
153+
return fmt.Sprintf("%s/%s", strings.TrimPrefix(srv.URL, "http://"), image)
115154
}
116155

117156
func TestNoMethodFails(t *testing.T) {

0 commit comments

Comments
 (0)