Skip to content

Commit 63a5697

Browse files
committed
feat: Added improved error logging for devcontainer feature.
1 parent b2a5bea commit 63a5697

4 files changed

Lines changed: 19 additions & 37 deletions

File tree

install-edge.sh

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ main() {
2828
os=$(get_os)
2929
arch=$(get_arch)
3030

31+
# Cache sudo credentials up front so the prompt happens before the
32+
# download — avoids issues when the script is piped via curl | sh.
33+
if [ ! -w "$INSTALL_DIR" ]; then
34+
echo "Installation to ${INSTALL_DIR} requires sudo access."
35+
sudo -v
36+
fi
37+
3138
binary_name="bridge-${os}-${arch}"
3239
download_url="https://github.com/${REPO}/releases/download/edge/${binary_name}"
3340

@@ -36,15 +43,14 @@ main() {
3643
curl -fsSL -o bridge "${download_url}"
3744
chmod +x bridge
3845

39-
# Remove macOS quarantine attribute to prevent Gatekeeper from killing the binary
4046
if [ "$os" = "darwin" ]; then
47+
# Remove macOS quarantine attribute to prevent Gatekeeper prompts
4148
xattr -d com.apple.quarantine bridge 2>/dev/null || true
4249
fi
4350

4451
if [ -w "$INSTALL_DIR" ]; then
4552
mv bridge "${INSTALL_DIR}/bridge"
4653
else
47-
echo "Moving binary to ${INSTALL_DIR} (requires sudo)..."
4854
sudo mv bridge "${INSTALL_DIR}/bridge"
4955
fi
5056

pkg/commands/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ func runCreate(ctx context.Context, c *cli.Command) error {
206206
if !yes {
207207
p.Newline()
208208
p.Warn("No bridge administrator found in the cluster.")
209-
p.Info(fmt.Sprintf("Bridge can use your local credentials for cluster %q instead.", kubeContext))
209+
p.Info(fmt.Sprintf("Should Bridge use your local credentials for cluster %q instead.", kubeContext))
210210
fmt.Fprintf(w, "Continue? [y/N] ")
211211

212212
answer := promptYN(r)

pkg/devcontainer/client.go

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package devcontainer
22

33
import (
4-
"bytes"
54
"context"
6-
"encoding/json"
75
"fmt"
86
"io"
97
"os"
@@ -33,7 +31,7 @@ func (c *Client) Up(ctx context.Context) error {
3331
cmd.Stdout = nil
3432
cmd.Stderr = nil
3533
if out, err := cmd.CombinedOutput(); err != nil {
36-
return fmt.Errorf("devcontainer up: %w\n%s", err, extractErrorMessage(out))
34+
return fmt.Errorf("devcontainer up: %w\n%s", err, out)
3735
}
3836
return nil
3937
}
@@ -97,35 +95,6 @@ func (c *Client) Stop(ctx context.Context) error {
9795
return nil
9896
}
9997

100-
// extractErrorMessage parses the devcontainer CLI's JSON output to find the
101-
// error message. The CLI emits newline-delimited JSON; the line with
102-
// "outcome":"error" contains the human-readable description. If no such line
103-
// is found, the raw output is returned as-is.
104-
func extractErrorMessage(out []byte) string {
105-
var result struct {
106-
Outcome string `json:"outcome"`
107-
Message string `json:"message"`
108-
Description string `json:"description"`
109-
}
110-
for _, line := range bytes.Split(out, []byte("\n")) {
111-
line = bytes.TrimSpace(line)
112-
if len(line) == 0 || line[0] != '{' {
113-
continue
114-
}
115-
if err := json.Unmarshal(line, &result); err != nil {
116-
continue
117-
}
118-
if result.Outcome == "error" {
119-
msg := result.Description
120-
if msg == "" {
121-
msg = result.Message
122-
}
123-
return msg
124-
}
125-
}
126-
return string(out)
127-
}
128-
12998
func (c *Client) stdinOrDefault() io.Reader {
13099
if c.Stdin != nil {
131100
return c.Stdin

pkg/interact/printer.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package interact
33
import (
44
"fmt"
55
"io"
6+
"strings"
67
)
78

89
// Printer writes themed, styled messages to a writer.
@@ -31,10 +32,16 @@ func (p *Printer) Info(msg string) {
3132
fmt.Fprintf(p.w, "%s %s\n", p.theme.Info.Render("→"), msg)
3233
}
3334

34-
// Errorf prints a red error message with formatting.
35+
// Errorf prints a red error message with formatting. If the message contains
36+
// newlines, only the first line is styled to avoid lipgloss mangling
37+
// multi-line output (e.g. devcontainer build logs).
3538
func (p *Printer) Errorf(format string, a ...any) {
3639
msg := fmt.Sprintf(format, a...)
37-
fmt.Fprintf(p.w, "%s %s\n", p.theme.Error.Render("✗"), p.theme.Error.Render(msg))
40+
first, rest, _ := strings.Cut(msg, "\n")
41+
fmt.Fprintf(p.w, "%s %s\n", p.theme.Error.Render("✗"), p.theme.Error.Render(first))
42+
if rest != "" {
43+
fmt.Fprintln(p.w, rest)
44+
}
3845
}
3946

4047
// Header prints a bold, underlined header.

0 commit comments

Comments
 (0)