From 46bf849e2bf9cf6912c98ffffd31200e801d2b5a Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 31 Oct 2023 15:52:48 -0700 Subject: [PATCH 1/3] cli: Handle invalid board paths --- ci/release/changelogs/next.md | 1 + d2cli/fmt.go | 2 +- d2cli/main.go | 5 ++- d2plugin/plugin_dagre.go | 2 +- d2plugin/plugin_elk.go | 2 +- e2etests-cli/main_test.go | 76 +++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 6 +++ 8 files changed, 91 insertions(+), 5 deletions(-) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 89a8916b73..461c9cf76c 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -20,3 +20,4 @@ - Correctly reports errors from invalid values set by globs. [#1691](https://github.com/terrastruct/d2/pull/1691) - Fixes panic when spread substitution referenced a nonexistant var. [#1695](https://github.com/terrastruct/d2/pull/1695) - Fixes incorrect appendix icon numbering. [#1704](https://github.com/terrastruct/d2/pull/1704) +- Fixes crash when using `--watch` and navigating to an invalid board path [#1693](https://github.com/terrastruct/d2/pull/1693) diff --git a/d2cli/fmt.go b/d2cli/fmt.go index 39f29bfd67..a2b8371589 100644 --- a/d2cli/fmt.go +++ b/d2cli/fmt.go @@ -17,7 +17,7 @@ import ( func fmtCmd(ctx context.Context, ms *xmain.State) (err error) { defer xdefer.Errorf(&err, "failed to fmt") - ms.Opts = xmain.NewOpts(ms.Env, ms.Log, ms.Opts.Flags.Args()[1:]) + ms.Opts = xmain.NewOpts(ms.Env, ms.Opts.Flags.Args()[1:]) if len(ms.Opts.Args) == 0 { return xmain.UsageErrorf("fmt must be passed at least one file to be formatted") } diff --git a/d2cli/main.go b/d2cli/main.go index 52f3a2ed0e..239d60d4f0 100644 --- a/d2cli/main.go +++ b/d2cli/main.go @@ -2,6 +2,7 @@ package d2cli import ( "context" + "encoding/json" "errors" "fmt" "io" @@ -490,6 +491,8 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, la default: compileDur := time.Since(start) if animateInterval <= 0 { + b, _ := json.MarshalIndent(diagram, "", " ") + println("\033[1;31m--- DEBUG:", string(b), "\033[m") // Rename all the "root.layers.x" to the paths that the boards get output to linkToOutput, err := resolveLinks("root", outputPath, diagram) if err != nil { @@ -503,7 +506,7 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, la board := diagram.GetBoard(boardPath) if board == nil { - return nil, false, fmt.Errorf("Diagram with path %s not found", boardPath) + return nil, false, fmt.Errorf(`Diagram with path "%s" not found. Did you mean to specify a board like "layers.%s"?`, boardPath, boardPath) } boards, err := render(ctx, ms, compileDur, plugin, renderOpts, inputPath, outputPath, bundle, forceAppendix, page, ruler, board) diff --git a/d2plugin/plugin_dagre.go b/d2plugin/plugin_dagre.go index 3c8fd3dcfe..f3d095ebde 100644 --- a/d2plugin/plugin_dagre.go +++ b/d2plugin/plugin_dagre.go @@ -61,7 +61,7 @@ func (p *dagrePlugin) HydrateOpts(opts []byte) error { func (p *dagrePlugin) Info(ctx context.Context) (*PluginInfo, error) { p.mu.Lock() defer p.mu.Unlock() - opts := xmain.NewOpts(nil, nil, nil) + opts := xmain.NewOpts(nil, nil) flags, err := p.Flags(ctx) if err != nil { return nil, err diff --git a/d2plugin/plugin_elk.go b/d2plugin/plugin_elk.go index d28fba3cb0..4726a666dc 100644 --- a/d2plugin/plugin_elk.go +++ b/d2plugin/plugin_elk.go @@ -76,7 +76,7 @@ func (p *elkPlugin) HydrateOpts(opts []byte) error { } func (p elkPlugin) Info(ctx context.Context) (*PluginInfo, error) { - opts := xmain.NewOpts(nil, nil, nil) + opts := xmain.NewOpts(nil, nil) flags, err := p.Flags(ctx) if err != nil { return nil, err diff --git a/e2etests-cli/main_test.go b/e2etests-cli/main_test.go index 29c92ec5c1..7f55ad6681 100644 --- a/e2etests-cli/main_test.go +++ b/e2etests-cli/main_test.go @@ -3,12 +3,17 @@ package e2etests_cli import ( "bytes" "context" + "fmt" + "net/http" "os" "path/filepath" + "regexp" "strings" "testing" "time" + "github.com/davecgh/go-spew/spew" + "nhooyr.io/websocket" "oss.terrastruct.com/util-go/assert" "oss.terrastruct.com/util-go/diff" "oss.terrastruct.com/util-go/xmain" @@ -544,6 +549,77 @@ i used to read assert.Equal(t, "x -> y\n", string(gotBar)) }, }, + { + name: "watch", + run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { + writeFile(t, dir, "index.d2", ` +a -> b +b.link: cream + +layers: { + cream: { + c -> b + } +}`) + stderr := &bytes.Buffer{} + tms := testMain(dir, env, "--watch", "--browser=0", "index.d2") + tms.Stderr = stderr + + doneChan := make(chan struct{}, 1) + + tms.Start(t, ctx) + defer tms.Cleanup(t) + + go tms.Wait(ctx) + + ticker := time.NewTicker(100 * time.Millisecond) + urlRE := regexp.MustCompile(`127.0.0.1:([0-9]+)`) + compiled := false + go func() { + var url string + for i := 0; i < 10 && url == ""; i++ { + select { + case <-ticker.C: + out := string(stderr.Bytes()) + url = urlRE.FindString(out) + compiled, _ = regexp.MatchString(`failed to recompile`, out) + println("\033[1;31m--- DEBUG:", compiled, "\033[m") + case <-ctx.Done(): + ticker.Stop() + return + } + } + + if url != "" { + c, _, err := websocket.Dial(ctx, fmt.Sprintf("ws://%s/watch", url), nil) + assert.Success(t, err) + + req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://%s/cream", url), nil) + assert.Success(t, err) + var httpClient = &http.Client{} + resp, err := httpClient.Do(req) + assert.Success(t, err) + defer resp.Body.Close() + assert.Equal(t, 200, resp.StatusCode) + + time.Sleep(1000) + spew.Dump(string(stderr.Bytes())) + + _, _, err = c.Read(ctx) + spew.Dump(err) + + defer c.Close(websocket.StatusNormalClosure, "") + } + + doneChan <- struct{}{} + }() + + <-doneChan + + err := tms.Signal(ctx, os.Interrupt) + assert.Error(t, err) + }, + }, } ctx := context.Background() diff --git a/go.mod b/go.mod index 92b1ac7524..18a31b9a42 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 gonum.org/v1/plot v0.12.0 nhooyr.io/websocket v1.8.7 - oss.terrastruct.com/util-go v0.0.0-20230604222829-11c3c60fec14 + oss.terrastruct.com/util-go v0.0.0-20231101220827-55b3812542c2 ) require ( diff --git a/go.sum b/go.sum index 5459577846..bd2909b608 100644 --- a/go.sum +++ b/go.sum @@ -331,4 +331,10 @@ nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= oss.terrastruct.com/util-go v0.0.0-20230604222829-11c3c60fec14 h1:oy5vtt6O2qYxeSpqWhyevrdUenFfuhphixozUlpL6qY= oss.terrastruct.com/util-go v0.0.0-20230604222829-11c3c60fec14/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= +oss.terrastruct.com/util-go v0.0.0-20231101215508-f36525fd4280 h1:AoxRLGSofA+l7zYwwxzdQSqyEYPOq8GznZU1CXByxsQ= +oss.terrastruct.com/util-go v0.0.0-20231101215508-f36525fd4280/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= +oss.terrastruct.com/util-go v0.0.0-20231101220527-f06cd5cb4db4 h1:trpfw07GR3LYlM/7MLMRM7y7o7H8e8PEF9XtVl5J6FE= +oss.terrastruct.com/util-go v0.0.0-20231101220527-f06cd5cb4db4/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= +oss.terrastruct.com/util-go v0.0.0-20231101220827-55b3812542c2 h1:n6y6RoZCgZDchN4gLGlzNRO1Jdf9xOGGqohDBph5BG8= +oss.terrastruct.com/util-go v0.0.0-20231101220827-55b3812542c2/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= From adb59ec47080a26478e1f508723ee68056ba4cfb Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 6 Nov 2023 11:38:15 -0800 Subject: [PATCH 2/3] add tests --- d2cli/main.go | 3 - d2target/d2target.go | 9 +- e2etests-cli/main_test.go | 226 +++++++++++++++++++++++++++++--------- go.mod | 3 +- go.sum | 51 +-------- 5 files changed, 185 insertions(+), 107 deletions(-) diff --git a/d2cli/main.go b/d2cli/main.go index 239d60d4f0..4aae3c4943 100644 --- a/d2cli/main.go +++ b/d2cli/main.go @@ -2,7 +2,6 @@ package d2cli import ( "context" - "encoding/json" "errors" "fmt" "io" @@ -491,8 +490,6 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, la default: compileDur := time.Since(start) if animateInterval <= 0 { - b, _ := json.MarshalIndent(diagram, "", " ") - println("\033[1;31m--- DEBUG:", string(b), "\033[m") // Rename all the "root.layers.x" to the paths that the boards get output to linkToOutput, err := resolveLinks("root", outputPath, diagram) if err != nil { diff --git a/d2target/d2target.go b/d2target/d2target.go index 46e086985e..c7c9a834ab 100644 --- a/d2target/d2target.go +++ b/d2target/d2target.go @@ -74,7 +74,8 @@ type Diagram struct { } // boardPath comes in the form of "x/layers/z/scenarios/a" -// or in the form of "layers/z/scenarios/a" +// or "layers/z/scenarios/a" +// or "x/z/a" func (d *Diagram) GetBoard(boardPath string) *Diagram { path := strings.Split(boardPath, string(os.PathSeparator)) if len(path) == 0 || len(boardPath) == 0 { @@ -127,17 +128,17 @@ func (d *Diagram) getBoard(boardPath []string) *Diagram { for _, b := range d.Layers { if b.Name == head { - return b.getBoard(boardPath[2:]) + return b.getBoard(boardPath[1:]) } } for _, b := range d.Scenarios { if b.Name == head { - return b.getBoard(boardPath[2:]) + return b.getBoard(boardPath[1:]) } } for _, b := range d.Steps { if b.Name == head { - return b.getBoard(boardPath[2:]) + return b.getBoard(boardPath[1:]) } } return nil diff --git a/e2etests-cli/main_test.go b/e2etests-cli/main_test.go index 7f55ad6681..647b6722e3 100644 --- a/e2etests-cli/main_test.go +++ b/e2etests-cli/main_test.go @@ -3,6 +3,7 @@ package e2etests_cli import ( "bytes" "context" + "errors" "fmt" "net/http" "os" @@ -12,8 +13,8 @@ import ( "testing" "time" - "github.com/davecgh/go-spew/spew" "nhooyr.io/websocket" + "oss.terrastruct.com/util-go/assert" "oss.terrastruct.com/util-go/diff" "oss.terrastruct.com/util-go/xmain" @@ -550,11 +551,11 @@ i used to read }, }, { - name: "watch", + name: "watch-regular", run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { writeFile(t, dir, "index.d2", ` a -> b -b.link: cream +b.link: layers.cream layers: { cream: { @@ -565,59 +566,151 @@ layers: { tms := testMain(dir, env, "--watch", "--browser=0", "index.d2") tms.Stderr = stderr - doneChan := make(chan struct{}, 1) - tms.Start(t, ctx) - defer tms.Cleanup(t) + defer func() { + // Manually close, since watcher is daemon + err := tms.Signal(ctx, os.Interrupt) + assert.Success(t, err) + }() - go tms.Wait(ctx) + // Wait for watch server to spin up and listen + urlRE := regexp.MustCompile(`127.0.0.1:([0-9]+)`) + watchURL := waitLogs(ctx, stderr, urlRE) + + if watchURL == "" { + t.Error(errors.New(string(stderr.Bytes()))) + } + stderr.Reset() + + // Start a client + c, _, err := websocket.Dial(ctx, fmt.Sprintf("ws://%s/watch", watchURL), nil) + assert.Success(t, err) + defer c.CloseNow() + + // Get the link + _, msg, err := c.Read(ctx) + assert.Success(t, err) + aRE := regexp.MustCompile(`href=\\"([^\"]*)\\"`) + match := aRE.FindSubmatch(msg) + assert.Equal(t, 2, len(match)) + linkedPath := match[1] + + err = getWatchPage(ctx, t, fmt.Sprintf("http://%s/%s", watchURL, linkedPath)) + assert.Success(t, err) + + successRE := regexp.MustCompile(`broadcasting update to 1 client`) + line := waitLogs(ctx, stderr, successRE) + assert.NotEqual(t, "", line) + }, + }, + { + name: "watch-ok-link", + run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { + // This link technically works because D2 interprets it as a URL, + // and on local filesystem, that is whe path where the compilation happens + // to output it to. + writeFile(t, dir, "index.d2", ` +a -> b +b.link: cream - ticker := time.NewTicker(100 * time.Millisecond) +layers: { + cream: { + c -> b + } +}`) + stderr := &bytes.Buffer{} + tms := testMain(dir, env, "--watch", "--browser=0", "index.d2") + tms.Stderr = stderr + + tms.Start(t, ctx) + defer func() { + // Manually close, since watcher is daemon + err := tms.Signal(ctx, os.Interrupt) + assert.Success(t, err) + }() + + // Wait for watch server to spin up and listen urlRE := regexp.MustCompile(`127.0.0.1:([0-9]+)`) - compiled := false - go func() { - var url string - for i := 0; i < 10 && url == ""; i++ { - select { - case <-ticker.C: - out := string(stderr.Bytes()) - url = urlRE.FindString(out) - compiled, _ = regexp.MatchString(`failed to recompile`, out) - println("\033[1;31m--- DEBUG:", compiled, "\033[m") - case <-ctx.Done(): - ticker.Stop() - return - } - } - - if url != "" { - c, _, err := websocket.Dial(ctx, fmt.Sprintf("ws://%s/watch", url), nil) - assert.Success(t, err) - - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://%s/cream", url), nil) - assert.Success(t, err) - var httpClient = &http.Client{} - resp, err := httpClient.Do(req) - assert.Success(t, err) - defer resp.Body.Close() - assert.Equal(t, 200, resp.StatusCode) - - time.Sleep(1000) - spew.Dump(string(stderr.Bytes())) - - _, _, err = c.Read(ctx) - spew.Dump(err) - - defer c.Close(websocket.StatusNormalClosure, "") - } - - doneChan <- struct{}{} + watchURL := waitLogs(ctx, stderr, urlRE) + + if watchURL == "" { + t.Error(errors.New(string(stderr.Bytes()))) + } + stderr.Reset() + + // Start a client + c, _, err := websocket.Dial(ctx, fmt.Sprintf("ws://%s/watch", watchURL), nil) + assert.Success(t, err) + defer c.CloseNow() + + // Get the link + _, msg, err := c.Read(ctx) + assert.Success(t, err) + aRE := regexp.MustCompile(`href=\\"([^\"]*)\\"`) + match := aRE.FindSubmatch(msg) + assert.Equal(t, 2, len(match)) + linkedPath := match[1] + + err = getWatchPage(ctx, t, fmt.Sprintf("http://%s/%s", watchURL, linkedPath)) + assert.Success(t, err) + + successRE := regexp.MustCompile(`broadcasting update to 1 client`) + line := waitLogs(ctx, stderr, successRE) + assert.NotEqual(t, "", line) + }, + }, + { + name: "watch-bad-link", + run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { + // Just verify we don't crash even with a bad link (it's treated as a URL, which users might have locally) + writeFile(t, dir, "index.d2", ` +a -> b +b.link: dream + +layers: { + cream: { + c -> b + } +}`) + stderr := &bytes.Buffer{} + tms := testMain(dir, env, "--watch", "--browser=0", "index.d2") + tms.Stderr = stderr + + tms.Start(t, ctx) + defer func() { + // Manually close, since watcher is daemon + err := tms.Signal(ctx, os.Interrupt) + assert.Success(t, err) }() - <-doneChan + // Wait for watch server to spin up and listen + urlRE := regexp.MustCompile(`127.0.0.1:([0-9]+)`) + watchURL := waitLogs(ctx, stderr, urlRE) + + if watchURL == "" { + t.Error(errors.New(string(stderr.Bytes()))) + } + stderr.Reset() + + // Start a client + c, _, err := websocket.Dial(ctx, fmt.Sprintf("ws://%s/watch", watchURL), nil) + assert.Success(t, err) + defer c.CloseNow() - err := tms.Signal(ctx, os.Interrupt) - assert.Error(t, err) + // Get the link + _, msg, err := c.Read(ctx) + assert.Success(t, err) + aRE := regexp.MustCompile(`href=\\"([^\"]*)\\"`) + match := aRE.FindSubmatch(msg) + assert.Equal(t, 2, len(match)) + linkedPath := match[1] + + err = getWatchPage(ctx, t, fmt.Sprintf("http://%s/%s", watchURL, linkedPath)) + assert.Success(t, err) + + successRE := regexp.MustCompile(`broadcasting update to 1 client`) + line := waitLogs(ctx, stderr, successRE) + assert.NotEqual(t, "", line) }, }, } @@ -716,3 +809,38 @@ func testdataIgnoreDiff(tb testing.TB, ext string, got []byte) { func getNumBoards(svg string) int { return strings.Count(svg, `class="d2`) } + +func waitLogs(ctx context.Context, buf *bytes.Buffer, pattern *regexp.Regexp) string { + ticker := time.NewTicker(10 * time.Millisecond) + var match string + for i := 0; i < 100 && match == ""; i++ { + select { + case <-ticker.C: + out := string(buf.Bytes()) + match = pattern.FindString(out) + case <-ctx.Done(): + ticker.Stop() + return "" + } + } + + return match +} + +func getWatchPage(ctx context.Context, t *testing.T, page string) error { + req, err := http.NewRequestWithContext(ctx, "GET", page, nil) + if err != nil { + return err + } + + var httpClient = &http.Client{} + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return fmt.Errorf("status code: %d", resp.StatusCode) + } + return nil +} diff --git a/go.mod b/go.mod index 18a31b9a42..ef61206b1b 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( golang.org/x/text v0.8.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 gonum.org/v1/plot v0.12.0 - nhooyr.io/websocket v1.8.7 + nhooyr.io/websocket v1.8.10 oss.terrastruct.com/util-go v0.0.0-20231101220827-55b3812542c2 ) @@ -44,7 +44,6 @@ require ( github.com/go-stack/stack v1.8.1 // indirect github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/klauspost/compress v1.10.3 // indirect github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect diff --git a/go.sum b/go.sum index bd2909b608..91a8c78533 100644 --- a/go.sum +++ b/go.sum @@ -66,10 +66,6 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= @@ -78,23 +74,10 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop github.com/go-fonts/liberation v0.2.0 h1:jAkAWJP4S+OsrPLZM4/eC9iW7CtHy+HBXrEwZXWo5VM= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 h1:6zl3BbBhdnMkpSj2YY30qV3gDcVBGtFgVsV3+/i+mKQ= github.com/go-pdf/fpdf v0.6.0 h1:MlgtGIfsdMEEQJr2le6b/HNr1ZlQwxyWr77r2aj2U/8= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= @@ -108,8 +91,6 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -125,22 +106,15 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc= github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0= -github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= @@ -149,8 +123,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= @@ -160,10 +132,6 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mazznoer/csscolorparser v0.1.3 h1:vug4zh6loQxAUxfU1DZEu70gTPufDPspamZlHAkKcxE= github.com/mazznoer/csscolorparser v0.1.3/go.mod h1:Aj22+L/rYN/Y6bj3bYqO3N6g1dtdHtGfQ32xZ5PJQic= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= @@ -185,16 +153,11 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.3 h1:3HUJmBFbQW9fhQOzMgseU134xfi6hU+mjWywx5Ty+/M= github.com/yuin/goldmark v1.5.3/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -266,14 +229,12 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -316,9 +277,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -327,14 +286,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -oss.terrastruct.com/util-go v0.0.0-20230604222829-11c3c60fec14 h1:oy5vtt6O2qYxeSpqWhyevrdUenFfuhphixozUlpL6qY= -oss.terrastruct.com/util-go v0.0.0-20230604222829-11c3c60fec14/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= -oss.terrastruct.com/util-go v0.0.0-20231101215508-f36525fd4280 h1:AoxRLGSofA+l7zYwwxzdQSqyEYPOq8GznZU1CXByxsQ= -oss.terrastruct.com/util-go v0.0.0-20231101215508-f36525fd4280/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= -oss.terrastruct.com/util-go v0.0.0-20231101220527-f06cd5cb4db4 h1:trpfw07GR3LYlM/7MLMRM7y7o7H8e8PEF9XtVl5J6FE= -oss.terrastruct.com/util-go v0.0.0-20231101220527-f06cd5cb4db4/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= +nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= +nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= oss.terrastruct.com/util-go v0.0.0-20231101220827-55b3812542c2 h1:n6y6RoZCgZDchN4gLGlzNRO1Jdf9xOGGqohDBph5BG8= oss.terrastruct.com/util-go v0.0.0-20231101220827-55b3812542c2/go.mod h1:eMWv0sOtD9T2RUl90DLWfuShZCYp4NrsqNpI8eqO6U4= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= From c54ea05e27c1050a1f6c41f1bfe6ce13d0924b9a Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 7 Nov 2023 10:43:19 -0800 Subject: [PATCH 3/3] pr comments --- e2etests-cli/main_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/e2etests-cli/main_test.go b/e2etests-cli/main_test.go index 647b6722e3..272457eb3b 100644 --- a/e2etests-cli/main_test.go +++ b/e2etests-cli/main_test.go @@ -578,7 +578,7 @@ layers: { watchURL := waitLogs(ctx, stderr, urlRE) if watchURL == "" { - t.Error(errors.New(string(stderr.Bytes()))) + t.Error(errors.New(stderr.String())) } stderr.Reset() @@ -634,7 +634,7 @@ layers: { watchURL := waitLogs(ctx, stderr, urlRE) if watchURL == "" { - t.Error(errors.New(string(stderr.Bytes()))) + t.Error(errors.New(stderr.String())) } stderr.Reset() @@ -688,7 +688,7 @@ layers: { watchURL := waitLogs(ctx, stderr, urlRE) if watchURL == "" { - t.Error(errors.New(string(stderr.Bytes()))) + t.Error(errors.New(stderr.String())) } stderr.Reset() @@ -812,11 +812,12 @@ func getNumBoards(svg string) int { func waitLogs(ctx context.Context, buf *bytes.Buffer, pattern *regexp.Regexp) string { ticker := time.NewTicker(10 * time.Millisecond) + defer ticker.Stop() var match string for i := 0; i < 100 && match == ""; i++ { select { case <-ticker.C: - out := string(buf.Bytes()) + out := buf.String() match = pattern.FindString(out) case <-ctx.Done(): ticker.Stop()