diff --git a/cli/internal/login/login.go b/cli/internal/login/login.go
index d0a24067e0eae..65438cd67a267 100644
--- a/cli/internal/login/login.go
+++ b/cli/internal/login/login.go
@@ -3,16 +3,14 @@ package login
import (
"context"
"fmt"
- "log"
"net/http"
"net/url"
"os"
- "os/exec"
- "runtime"
"strings"
"turbo/internal/config"
"turbo/internal/ui"
"turbo/internal/util"
+ "turbo/internal/util/browser"
"github.com/fatih/color"
"github.com/hashicorp/go-hclog"
@@ -53,7 +51,7 @@ func (c *LoginCommand) Run(args []string) int {
loginUrl := fmt.Sprintf("%v/turborepo/token?redirect_uri=%v", c.Config.LoginUrl, redirectUrl)
c.Ui.Info(util.Sprintf(">>> Opening browser to %v", c.Config.LoginUrl))
s := ui.NewSpinner(os.Stdout)
- openbrowser(loginUrl)
+ browser.OpenBrowser(loginUrl)
s.Start("Waiting for your authorization...")
var query url.Values
@@ -127,22 +125,3 @@ func (c *LoginCommand) logFatal(log hclog.Logger, prefix string, err error) {
c.Ui.Error(fmt.Sprintf("%s%s%s", ui.ERROR_PREFIX, prefix, color.RedString(" %v", err)))
os.Exit(1)
}
-
-func openbrowser(url string) {
- var err error
-
- switch runtime.GOOS {
- case "linux":
- err = exec.Command("xdg-open", url).Start()
- case "windows":
- err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
- case "darwin":
- err = exec.Command("open", url).Start()
- default:
- err = fmt.Errorf("unsupported platform")
- }
- if err != nil {
- log.Fatal(err)
- }
-
-}
diff --git a/cli/internal/run/run.go b/cli/internal/run/run.go
index a4f730252ca9e..d612c424783df 100644
--- a/cli/internal/run/run.go
+++ b/cli/internal/run/run.go
@@ -8,7 +8,6 @@ import (
"log"
"os"
"os/exec"
- "path"
"path/filepath"
"sort"
"strconv"
@@ -24,13 +23,13 @@ import (
"turbo/internal/scm"
"turbo/internal/ui"
"turbo/internal/util"
+ "turbo/internal/util/browser"
"github.com/pyr-sh/dag"
"github.com/fatih/color"
glob "github.com/gobwas/glob"
"github.com/hashicorp/go-hclog"
- "github.com/mattn/go-isatty"
"github.com/mitchellh/cli"
"github.com/pkg/errors"
)
@@ -613,9 +612,39 @@ func (c *RunCommand) Run(args []string) int {
Verbose: true,
DrawCycles: true,
}))
+ ext := filepath.Ext(runOptions.dotGraph)
+ if ext == ".html" {
+ f, err := os.Create(filepath.Join(cwd, runOptions.dotGraph))
+ if err != nil {
+ c.logError(c.Config.Logger, "", fmt.Errorf("error writing graph: %w", err))
+ return 1
+ }
+ defer f.Close()
+ f.WriteString(`
+
+
+
+ Graph
+
+
+
+
+
+
+ `)
+ c.Ui.Output("")
+ c.Ui.Output(fmt.Sprintf("✔ Generated task graph in %s", ui.Bold(runOptions.dotGraph)))
+ if ui.IsTTY {
+ browser.OpenBrowser(filepath.Join(cwd, runOptions.dotGraph))
+ }
+ return 0
+ }
hasDot := hasGraphViz()
if hasDot {
- dotArgs := []string{"-T" + path.Ext(runOptions.dotGraph)[1:], "-o", runOptions.dotGraph}
+ dotArgs := []string{"-T" + ext[1:], "-o", runOptions.dotGraph}
cmd := exec.Command("dot", dotArgs...)
cmd.Stdin = strings.NewReader(graphString)
if err := cmd.Run(); err != nil {
@@ -808,7 +837,7 @@ func parseRunArgs(args []string, cwd string) (*RunOptions, error) {
}
// Force streaming output in CI/CD non-interactive mode
- if !isatty.IsTerminal(os.Stdout.Fd()) || os.Getenv("CI") != "" {
+ if !ui.IsTTY || ui.IsCI {
runOptions.stream = true
}
diff --git a/cli/internal/util/browser/open.go b/cli/internal/util/browser/open.go
new file mode 100644
index 0000000000000..291ec30f55c28
--- /dev/null
+++ b/cli/internal/util/browser/open.go
@@ -0,0 +1,27 @@
+package browser
+
+import (
+ "fmt"
+ "log"
+ "os/exec"
+ "runtime"
+)
+
+func OpenBrowser(url string) {
+ var err error
+
+ switch runtime.GOOS {
+ case "linux":
+ err = exec.Command("xdg-open", url).Start()
+ case "windows":
+ err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
+ case "darwin":
+ err = exec.Command("open", url).Start()
+ default:
+ err = fmt.Errorf("unsupported platform")
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+
+}
diff --git a/docs/pages/docs/reference/command-line-reference.mdx b/docs/pages/docs/reference/command-line-reference.mdx
index 0d555b977bce1..5e5be2cc7326d 100644
--- a/docs/pages/docs/reference/command-line-reference.mdx
+++ b/docs/pages/docs/reference/command-line-reference.mdx
@@ -82,7 +82,7 @@ Let's say you have packages A, B, C, and D where A depends on B and C depends on
`type: string`
-If [Graphviz](https://graphviz.org) is installed, this command will generate an svg, png, jpg, pdf, json, or [other supported output formats](https://graphviz.org/doc/info/output.html) of the current task graph.
+If [Graphviz](https://graphviz.org) is installed, this command will generate an svg, png, jpg, pdf, json, html, or [other supported output formats](https://graphviz.org/doc/info/output.html) of the current task graph.
The output file format can be controlled with the filename's extension if it is specified. If a filename is not specified, `graph-.jpg` is outputted.
If Graphviz is not installed, this command prints the dot graph to `stdout`.
@@ -93,6 +93,7 @@ turbo run build test lint --graph=my-graph.svg
turbo run build test lint --graph=my-json-graph.json
turbo run build test lint --graph=my-graph.pdf
turbo run build test lint --graph=my-graph.png
+turbo run build test lint --graph=my-graph.html
```