Skip to content

Commit d85f950

Browse files
committed
tools/flow: add debug support via CUE_DEBUG_TOOLS_FLOW
Setting CUE_DEBUG_TOOLS_FLOW to some value other than the empty string now causes a mermaid graph to be printed out for each update of the flow Controller. This will help with debugging of tools/flow and cue cmd issues. Signed-off-by: Paul Jolly <[email protected]> Change-Id: Ic5f122250a0fa13a2134aa47161acbf8e570ee02 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/546541 Unity-Result: CUEcueckoo <[email protected]> Reviewed-by: Roger Peppe <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 32bfffd commit d85f950

File tree

5 files changed

+85
-17
lines changed

5 files changed

+85
-17
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
env CUE_DEBUG_TOOLS_FLOW=1
2+
3+
exec cue cmd bar
4+
cmp stderr stderr.golden
5+
6+
-- x_tool.cue --
7+
package x
8+
9+
import (
10+
"tool/cli"
11+
)
12+
13+
command: bar: {
14+
a: cli.Print & {
15+
text: "a"
16+
}
17+
"\"b#": cli.Print & {
18+
text: "b"
19+
$after: a
20+
}
21+
22+
}
23+
-- stderr.golden --
24+
tools/flow task dependency graph:
25+
```mermaid
26+
graph TD
27+
t0("command.bar.a [Ready]")
28+
t1("command.bar.#quot;\#quot;b#35;#quot; [Waiting]")
29+
t1-->t0
30+
```
31+
tools/flow task dependency graph:
32+
```mermaid
33+
graph TD
34+
t0("command.bar.a [Terminated]")
35+
t1("command.bar.#quot;\#quot;b#35;#quot; [Ready]")
36+
t1-->t0
37+
```
38+
tools/flow task dependency graph:
39+
```mermaid
40+
graph TD
41+
t0("command.bar.a [Terminated]")
42+
t1("command.bar.#quot;\#quot;b#35;#quot; [Terminated]")
43+
t1-->t0
44+
```

tools/flow/cycle_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import (
2020
"testing"
2121
)
2222

23+
// MermaidGraph exports mermaidGraph for external tests
24+
var MermaidGraph = mermaidGraph
25+
2326
func TestIsCyclic(t *testing.T) {
2427
testCases := []struct {
2528
// semi-colon-separated list of nodes with comma-separated list

tools/flow/flow.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ package flow
6868

6969
import (
7070
"context"
71+
"fmt"
72+
"os"
73+
"strings"
7174
"sync"
7275

7376
"cuelang.org/go/cue"
@@ -86,6 +89,8 @@ var (
8689

8790
// TODO: ErrUpdate: update and run a dependency, but don't complete a
8891
// dependency as more results may come. This is useful in server mode.
92+
93+
debug = os.Getenv("CUE_DEBUG_TOOLS_FLOW") != ""
8994
)
9095

9196
// A TaskFunc creates a Runner for v if v defines a task or reports nil
@@ -278,6 +283,27 @@ func (c *Controller) Value() cue.Value {
278283
return c.inst
279284
}
280285

286+
// We need to escape quotes in the path, per
287+
// https://mermaid-js.github.io/mermaid/#/flowchart?id=entity-codes-to-escape-characters
288+
// This also requires that we escape the quoting character #.
289+
var mermaidQuote = strings.NewReplacer("#", "#35;", `"`, "#quot;")
290+
291+
// mermaidGraph generates a mermaid graph of the current state. This can be
292+
// pasted into https://mermaid-js.github.io/mermaid-live-editor/ for
293+
// visualization.
294+
func mermaidGraph(c *Controller) string {
295+
w := &strings.Builder{}
296+
fmt.Fprintln(w, "graph TD")
297+
for i, t := range c.Tasks() {
298+
path := mermaidQuote.Replace(t.Path().String())
299+
fmt.Fprintf(w, " t%d(\"%s [%s]\")\n", i, path, t.State())
300+
for _, t := range t.Dependencies() {
301+
fmt.Fprintf(w, " t%d-->t%d\n", i, t.Index())
302+
}
303+
}
304+
return w.String()
305+
}
306+
281307
// A State indicates the state of a Task.
282308
//
283309
// The following state diagram indicates the possible state transitions:

tools/flow/flow_test.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func TestFlow(t *testing.T) {
5252
var tasksTotal stats.Counts
5353

5454
updateFunc := func(c *flow.Controller, task *flow.Task) error {
55-
str := mermaidGraph(c)
55+
str := flow.MermaidGraph(c)
5656
step := fmt.Sprintf("t%d", seqNum)
5757
fmt.Fprintln(t.Writer(step), str)
5858

@@ -245,21 +245,6 @@ func waitSeqNum(seq int64) {
245245
seqCond.L.Unlock()
246246
}
247247

248-
// mermaidGraph generates a mermaid graph of the current state. This can be
249-
// pasted into https://mermaid-js.github.io/mermaid-live-editor/ for
250-
// visualization.
251-
func mermaidGraph(c *flow.Controller) string {
252-
w := &strings.Builder{}
253-
fmt.Fprintln(w, "graph TD")
254-
for i, t := range c.Tasks() {
255-
fmt.Fprintf(w, " t%d(\"%s [%s]\")\n", i, t.Path(), t.State())
256-
for _, t := range t.Dependencies() {
257-
fmt.Fprintf(w, " t%d-->t%d\n", i, t.Index())
258-
}
259-
}
260-
return w.String()
261-
}
262-
263248
// DO NOT REMOVE: for testing purposes.
264249
func TestX(t *testing.T) {
265250
in := `
@@ -285,7 +270,7 @@ func TestX(t *testing.T) {
285270
},
286271
}, v, taskFunc)
287272

288-
t.Error(mermaidGraph(c))
273+
t.Error(flow.MermaidGraph(c))
289274

290275
if err := c.Run(context.Background()); err != nil {
291276
t.Fatal(errors.Details(err, nil))

tools/flow/run.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ package flow
2626
// future tasks may be long running, as discussed above.
2727

2828
import (
29+
"fmt"
30+
"os"
31+
2932
"cuelang.org/go/cue/errors"
3033
"cuelang.org/go/internal/core/adt"
3134
"cuelang.org/go/internal/core/eval"
@@ -136,6 +139,13 @@ func (c *Controller) markReady(t *Task) {
136139
}
137140
}
138141

142+
if debug {
143+
fmt.Fprintln(os.Stderr, "tools/flow task dependency graph:")
144+
fmt.Fprintln(os.Stderr, "```mermaid")
145+
fmt.Fprint(os.Stderr, mermaidGraph(c))
146+
fmt.Fprintln(os.Stderr, "```")
147+
}
148+
139149
if c.cfg.UpdateFunc != nil {
140150
if err := c.cfg.UpdateFunc(c, t); err != nil {
141151
c.addErr(err, "task completed")

0 commit comments

Comments
 (0)