Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

port(turborepo): Config #4520

Merged
merged 4 commits into from Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions cli/cmd/turbo/main.go
Expand Up @@ -15,14 +15,14 @@ func main() {
os.Exit(1)
}

argsString := os.Args[1]
var args turbostate.ParsedArgsFromRust
err := json.Unmarshal([]byte(argsString), &args)
executionStateString := os.Args[1]
var executionState turbostate.ExecutionState
err := json.Unmarshal([]byte(executionStateString), &executionState)
if err != nil {
fmt.Printf("Error unmarshalling CLI args: %v\n Arg string: %v\n", err, argsString)
fmt.Printf("Error unmarshalling execution state: %v\n Execution state string: %v\n", err, executionStateString)
os.Exit(1)
}

exitCode := cmd.RunWithArgs(&args, turboVersion)
exitCode := cmd.RunWithExecutionState(&executionState, turboVersion)
os.Exit(exitCode)
}
32 changes: 8 additions & 24 deletions cli/internal/client/client.go
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-retryablehttp"
"github.com/vercel/turbo/cli/internal/ci"
"github.com/vercel/turbo/cli/internal/turbostate"
)

// APIClient is the main interface for making network requests to Vercel
Expand Down Expand Up @@ -47,42 +48,25 @@ func (c *APIClient) SetToken(token string) {
c.token = token
}

// RemoteConfig holds the authentication and endpoint details for the API client
type RemoteConfig struct {
Token string
TeamID string
TeamSlug string
APIURL string
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have no integration testing around this at the moment, so need to be extra careful. I'm hoping to finish #4309 soon (feel free to pick it up for this purpose) so we can make this safer and get more clarity about the expected network requests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seconding this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm gonna block this PR on #4309


// Opts holds values for configuring the behavior of the API client
type Opts struct {
UsePreflight bool
Timeout uint64
}

// ClientTimeout Exported ClientTimeout used in run.go
const ClientTimeout uint64 = 20

// NewClient creates a new APIClient
func NewClient(remoteConfig RemoteConfig, logger hclog.Logger, turboVersion string, opts Opts) *APIClient {
func NewClient(config turbostate.APIClientConfig, logger hclog.Logger, turboVersion string) *APIClient {
client := &APIClient{
baseURL: remoteConfig.APIURL,
baseURL: config.APIURL,
turboVersion: turboVersion,
HTTPClient: &retryablehttp.Client{
HTTPClient: &http.Client{
Timeout: time.Duration(opts.Timeout) * time.Second,
Timeout: time.Duration(config.Timeout) * time.Second,
},
RetryWaitMin: 2 * time.Second,
RetryWaitMax: 10 * time.Second,
RetryMax: 2,
Backoff: retryablehttp.DefaultBackoff,
Logger: logger,
},
token: remoteConfig.Token,
teamID: remoteConfig.TeamID,
teamSlug: remoteConfig.TeamSlug,
usePreflight: opts.UsePreflight,
token: config.Token,
teamID: config.TeamID,
teamSlug: config.TeamSlug,
usePreflight: config.UsePreflight,
}
client.HTTPClient.CheckRetry = client.checkRetry
return client
Expand Down
17 changes: 9 additions & 8 deletions cli/internal/client/client_test.go
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/google/uuid"
"github.com/hashicorp/go-hclog"
"github.com/vercel/turbo/cli/internal/turbostate"
"github.com/vercel/turbo/cli/internal/util"
)

Expand All @@ -30,12 +31,12 @@ func Test_sendToServer(t *testing.T) {
}))
defer ts.Close()

remoteConfig := RemoteConfig{
apiClientConfig := turbostate.APIClientConfig{
TeamSlug: "my-team-slug",
APIURL: ts.URL,
Token: "my-token",
}
apiClient := NewClient(remoteConfig, hclog.Default(), "v1", Opts{})
apiClient := NewClient(apiClientConfig, hclog.Default(), "v1")

myUUID, err := uuid.NewUUID()
if err != nil {
Expand Down Expand Up @@ -85,12 +86,12 @@ func Test_PutArtifact(t *testing.T) {
defer ts.Close()

// Set up test expected values
remoteConfig := RemoteConfig{
apiClientConfig := turbostate.APIClientConfig{
TeamSlug: "my-team-slug",
APIURL: ts.URL,
Token: "my-token",
}
apiClient := NewClient(remoteConfig, hclog.Default(), "v1", Opts{})
apiClient := NewClient(apiClientConfig, hclog.Default(), "v1")
expectedArtifactBody := []byte("My string artifact")

// Test Put Artifact
Expand All @@ -111,12 +112,12 @@ func Test_PutWhenCachingDisabled(t *testing.T) {
defer ts.Close()

// Set up test expected values
remoteConfig := RemoteConfig{
apiClientConfig := turbostate.APIClientConfig{
TeamSlug: "my-team-slug",
APIURL: ts.URL,
Token: "my-token",
}
apiClient := NewClient(remoteConfig, hclog.Default(), "v1", Opts{})
apiClient := NewClient(apiClientConfig, hclog.Default(), "v1")
expectedArtifactBody := []byte("My string artifact")
// Test Put Artifact
err := apiClient.PutArtifact("hash", expectedArtifactBody, 500, "")
Expand All @@ -138,12 +139,12 @@ func Test_FetchWhenCachingDisabled(t *testing.T) {
defer ts.Close()

// Set up test expected values
remoteConfig := RemoteConfig{
apiClientConfig := turbostate.APIClientConfig{
TeamSlug: "my-team-slug",
APIURL: ts.URL,
Token: "my-token",
}
apiClient := NewClient(remoteConfig, hclog.Default(), "v1", Opts{})
apiClient := NewClient(apiClientConfig, hclog.Default(), "v1")
// Test Put Artifact
resp, err := apiClient.FetchArtifact("hash")
cd := &util.CacheDisabledError{}
Expand Down
16 changes: 8 additions & 8 deletions cli/internal/cmd/root.go
Expand Up @@ -44,29 +44,29 @@ func initializeOutputFiles(helper *cmdutil.Helper, parsedArgs *turbostate.Parsed
return nil
}

// RunWithArgs runs turbo with the ParsedArgsFromRust that is passed from the Rust side.
func RunWithArgs(args *turbostate.ParsedArgsFromRust, turboVersion string) int {
// RunWithExecutionState runs turbo with the ParsedArgsFromRust that is passed from the Rust side.
func RunWithExecutionState(executionState *turbostate.ExecutionState, turboVersion string) int {
util.InitPrintf()
// TODO: replace this with a context
signalWatcher := signals.NewWatcher()
helper := cmdutil.NewHelper(turboVersion, args)
helper := cmdutil.NewHelper(turboVersion, &executionState.CLIArgs)
ctx := context.Background()

err := initializeOutputFiles(helper, args)
err := initializeOutputFiles(helper, &executionState.CLIArgs)
if err != nil {
fmt.Printf("%v", err)
return 1
}
defer helper.Cleanup(args)
defer helper.Cleanup(&executionState.CLIArgs)

doneCh := make(chan struct{})
var execErr error
go func() {
command := args.Command
command := executionState.CLIArgs.Command
if command.Prune != nil {
execErr = prune.ExecutePrune(helper, args)
execErr = prune.ExecutePrune(helper, executionState)
} else if command.Run != nil {
execErr = run.ExecuteRun(ctx, helper, signalWatcher, args)
execErr = run.ExecuteRun(ctx, helper, signalWatcher, executionState)
} else {
execErr = fmt.Errorf("unknown command: %v", command)
}
Expand Down
58 changes: 8 additions & 50 deletions cli/internal/cmdutil/cmdutil.go
Expand Up @@ -7,7 +7,6 @@ import (
"io"
"io/ioutil"
"os"
"strconv"
"sync"

"github.com/hashicorp/go-hclog"
Expand Down Expand Up @@ -39,8 +38,6 @@ type Helper struct {

rawRepoRoot string

clientOpts client.Opts

// UserConfigPath is the path to where we expect to find
// a user-specific config file, if one is present. Public
// to allow overrides in tests
Expand Down Expand Up @@ -74,12 +71,12 @@ func (h *Helper) Cleanup(cliConfig *turbostate.ParsedArgsFromRust) {
}
}

func (h *Helper) getUI(cliConfig *turbostate.ParsedArgsFromRust) cli.Ui {
func (h *Helper) getUI(cliArgs *turbostate.ParsedArgsFromRust) cli.Ui {
colorMode := ui.GetColorModeFromEnv()
if cliConfig.GetNoColor() {
if cliArgs.NoColor {
NicholasLYang marked this conversation as resolved.
Show resolved Hide resolved
colorMode = ui.ColorModeSuppressed
}
if cliConfig.GetColor() {
if cliArgs.Color {
colorMode = ui.ColorModeForced
}
return ui.BuildColoredUi(colorMode)
Expand Down Expand Up @@ -134,15 +131,15 @@ func NewHelper(turboVersion string, args *turbostate.ParsedArgsFromRust) *Helper

// GetCmdBase returns a CmdBase instance configured with values from this helper.
// It additionally returns a mechanism to set an error, so
func (h *Helper) GetCmdBase(cliConfig *turbostate.ParsedArgsFromRust) (*CmdBase, error) {
func (h *Helper) GetCmdBase(executionState *turbostate.ExecutionState) (*CmdBase, error) {
// terminal is for color/no-color output
terminal := h.getUI(cliConfig)
terminal := h.getUI(&executionState.CLIArgs)
// logger is configured with verbosity level using --verbosity flag from end users
logger, err := h.getLogger()
if err != nil {
return nil, err
}
cwdRaw, err := cliConfig.GetCwd()
cwdRaw := executionState.CLIArgs.CWD
if err != nil {
return nil, err
}
Expand All @@ -155,55 +152,19 @@ func (h *Helper) GetCmdBase(cliConfig *turbostate.ParsedArgsFromRust) (*CmdBase,
if err != nil {
return nil, err
}
repoConfig, err := config.ReadRepoConfigFile(config.GetRepoConfigPath(repoRoot), cliConfig)
if err != nil {
return nil, err
}
userConfig, err := config.ReadUserConfigFile(h.UserConfigPath, cliConfig)
if err != nil {
return nil, err
}
remoteConfig := repoConfig.GetRemoteConfig(userConfig.Token())
mehulkar marked this conversation as resolved.
Show resolved Hide resolved
if remoteConfig.Token == "" && ui.IsCI {
vercelArtifactsToken := os.Getenv("VERCEL_ARTIFACTS_TOKEN")
vercelArtifactsOwner := os.Getenv("VERCEL_ARTIFACTS_OWNER")
if vercelArtifactsToken != "" {
remoteConfig.Token = vercelArtifactsToken
}
if vercelArtifactsOwner != "" {
remoteConfig.TeamID = vercelArtifactsOwner
}
}

// Primacy: Arg > Env
timeout, err := cliConfig.GetRemoteCacheTimeout()
if err == nil {
h.clientOpts.Timeout = timeout
} else {
val, ok := os.LookupEnv("TURBO_REMOTE_CACHE_TIMEOUT")
if ok {
number, err := strconv.ParseUint(val, 10, 64)
if err == nil {
h.clientOpts.Timeout = number
}
}
}
apiClientConfig := executionState.APIClientConfig

apiClient := client.NewClient(
remoteConfig,
apiClientConfig,
logger,
h.TurboVersion,
h.clientOpts,
)

return &CmdBase{
UI: terminal,
Logger: logger,
RepoRoot: repoRoot,
APIClient: apiClient,
RepoConfig: repoConfig,
UserConfig: userConfig,
RemoteConfig: remoteConfig,
TurboVersion: h.TurboVersion,
}, nil
}
Expand All @@ -214,9 +175,6 @@ type CmdBase struct {
Logger hclog.Logger
RepoRoot turbopath.AbsoluteSystemPath
APIClient *client.APIClient
RepoConfig *config.RepoConfig
UserConfig *config.UserConfig
RemoteConfig client.RemoteConfig
TurboVersion string
}

Expand Down