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

Running build with --cwd works #783

Merged
merged 6 commits into from
Feb 28, 2022
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/internal/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type LanguageBackend struct {
GetPackageDir func() string

// Return the list of workspace glob
GetWorkspaceGlobs func() ([]string, error)
GetWorkspaceGlobs func(rootpath string) ([]string, error)
// Returns run command
GetRunCommand func() []string

Expand Down
17 changes: 9 additions & 8 deletions cli/internal/backends/nodejs/nodejs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"log"
"path/filepath"

"github.com/vercel/turborepo/cli/internal/api"
"github.com/vercel/turborepo/cli/internal/fs"
"github.com/vercel/turborepo/cli/internal/util"
Expand All @@ -20,8 +21,8 @@ var NodejsYarnBackend = api.LanguageBackend{
Specfile: "package.json",
Lockfile: "yarn.lock",
FilenamePatterns: nodejsPatterns,
GetWorkspaceGlobs: func() ([]string, error) {
pkg, err := fs.ReadPackageJSON("package.json")
GetWorkspaceGlobs: func(rootpath string) ([]string, error) {
pkg, err := fs.ReadPackageJSON(filepath.Join(rootpath, "package.json"))
if err != nil {
return nil, fmt.Errorf("package.json: %w", err)
}
Expand Down Expand Up @@ -81,8 +82,8 @@ var NodejsBerryBackend = api.LanguageBackend{
Specfile: "package.json",
Lockfile: "yarn.lock",
FilenamePatterns: nodejsPatterns,
GetWorkspaceGlobs: func() ([]string, error) {
pkg, err := fs.ReadPackageJSON("package.json")
GetWorkspaceGlobs: func(rootpath string) ([]string, error) {
pkg, err := fs.ReadPackageJSON(filepath.Join(rootpath, "package.json"))
if err != nil {
return nil, fmt.Errorf("package.json: %w", err)
}
Expand Down Expand Up @@ -161,8 +162,8 @@ var NodejsPnpmBackend = api.LanguageBackend{
Specfile: "package.json",
Lockfile: "pnpm-lock.yaml",
FilenamePatterns: nodejsPatterns,
GetWorkspaceGlobs: func() ([]string, error) {
bytes, err := ioutil.ReadFile("pnpm-workspace.yaml")
GetWorkspaceGlobs: func(rootpath string) ([]string, error) {
bytes, err := ioutil.ReadFile(filepath.Join(rootpath, "pnpm-workspace.yaml"))
if err != nil {
return nil, fmt.Errorf("pnpm-workspace.yaml: %w", err)
}
Expand Down Expand Up @@ -212,8 +213,8 @@ var NodejsNpmBackend = api.LanguageBackend{
Specfile: "package.json",
Lockfile: "package-lock.json",
FilenamePatterns: nodejsPatterns,
GetWorkspaceGlobs: func() ([]string, error) {
pkg, err := fs.ReadPackageJSON("package.json")
GetWorkspaceGlobs: func(rootpath string) ([]string, error) {
pkg, err := fs.ReadPackageJSON(filepath.Join(rootpath, "package.json"))
if err != nil {
return nil, fmt.Errorf("package.json: %w", err)
}
Expand Down
27 changes: 12 additions & 15 deletions cli/internal/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"log"
"os"
"path"
"path/filepath"
"sort"
"strings"
Expand Down Expand Up @@ -93,12 +92,7 @@ func WithGraph(rootpath string, config *config.Config) Option {
// Need to ALWAYS have a root node, might as well do it now
c.TaskGraph.Add(core.ROOT_NODE_NAME)

cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("could not get cwd: %w", err)
}

packageJSONPath := path.Join(rootpath, "package.json")
packageJSONPath := filepath.Join(rootpath, "package.json")
pkg, err := fs.ReadPackageJSON(packageJSONPath)
if err != nil {
return fmt.Errorf("package.json: %w", err)
Expand All @@ -109,7 +103,7 @@ func WithGraph(rootpath string, config *config.Config) Option {
// If pkg.Turbo exists, we warn about running the migration
// Use pkg.Turbo if turbo.json doesn't exist
// If neither exists, it's a fatal error
turboJSONPath := path.Join(rootpath, "turbo.json")
turboJSONPath := filepath.Join(rootpath, "turbo.json")
if !fs.FileExists(turboJSONPath) {
if pkg.LegacyTurboConfig == nil {
// TODO: suggestion on how to create one
Expand All @@ -130,15 +124,15 @@ func WithGraph(rootpath string, config *config.Config) Option {
}
}

if backend, err := backends.GetBackend(cwd, pkg); err != nil {
if backend, err := backends.GetBackend(rootpath, pkg); err != nil {
return err
} else {
c.Backend = backend
}

// this should go into the bacend abstraction
if util.IsYarn(c.Backend.Name) {
lockfile, err := fs.ReadLockfile(c.Backend.Name, config.Cache.Dir)
lockfile, err := fs.ReadLockfile(rootpath, c.Backend.Name, config.Cache.Dir)
if err != nil {
return fmt.Errorf("yarn.lock: %w", err)
}
Expand All @@ -149,7 +143,7 @@ func WithGraph(rootpath string, config *config.Config) Option {
return err
}

spaces, err := c.Backend.GetWorkspaceGlobs()
spaces, err := c.Backend.GetWorkspaceGlobs(rootpath)

if err != nil {
return fmt.Errorf("could not detect workspaces: %w", err)
Expand Down Expand Up @@ -226,15 +220,18 @@ func WithGraph(rootpath string, config *config.Config) Option {
parseJSONWaitGroup := new(errgroup.Group)
justJsons := make([]string, 0, len(spaces))
for _, space := range spaces {
justJsons = append(justJsons, path.Join(space, "package.json"))
justJsons = append(justJsons, filepath.Join(space, "package.json"))
}

f := globby.GlobFiles(rootpath, justJsons, getWorkspaceIgnores())

for i, val := range f {
_, val := i, val // https://golang.org/doc/faq#closures_and_goroutines
for _, val := range f {
relativePkgPath, err := filepath.Rel(rootpath, val)
if err != nil {
return fmt.Errorf("non-nested package.json path %w", err)
}
parseJSONWaitGroup.Go(func() error {
return c.parsePackageJSON(val)
return c.parsePackageJSON(relativePkgPath)
})
}

Expand Down
6 changes: 3 additions & 3 deletions cli/internal/fs/lockfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import (
)

// ReadLockfile will read `yarn.lock` into memory (either from the cache or fresh)
func ReadLockfile(backendName string, cacheDir string) (*YarnLockfile, error) {
func ReadLockfile(rootpath string, backendName string, cacheDir string) (*YarnLockfile, error) {
var lockfile YarnLockfile
var prettyLockFile = YarnLockfile{}
hash, err := HashFile("yarn.lock")
hash, err := HashFile(filepath.Join(rootpath, "yarn.lock"))
if err != nil {
return &YarnLockfile{}, fmt.Errorf("failed to hash lockfile: %w", err)
}
contentsOfLock, err := ioutil.ReadFile(filepath.Join(cacheDir, fmt.Sprintf("%v-turbo-lock.yaml", hash)))
if err != nil {
contentsB, err := ioutil.ReadFile("yarn.lock")
contentsB, err := ioutil.ReadFile(filepath.Join(rootpath, "yarn.lock"))
if err != nil {
return nil, fmt.Errorf("reading yarn.lock: %w", err)
}
Expand Down
5 changes: 3 additions & 2 deletions cli/internal/prune/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"
"strings"
"sync"

"github.com/vercel/turborepo/cli/internal/config"
"github.com/vercel/turborepo/cli/internal/context"
"github.com/vercel/turborepo/cli/internal/fs"
Expand Down Expand Up @@ -99,7 +100,7 @@ func (c *PruneCommand) Run(args []string) int {
c.logError(c.Config.Logger, "", err)
return 1
}
ctx, err := context.New(context.WithTracer(""), context.WithArgs(args), context.WithGraph(".", c.Config))
ctx, err := context.New(context.WithTracer(""), context.WithArgs(args), context.WithGraph(pruneOptions.cwd, c.Config))

if err != nil {
c.logError(c.Config.Logger, "", fmt.Errorf("could not construct graph: %w", err))
Expand Down Expand Up @@ -129,7 +130,7 @@ func (c *PruneCommand) Run(args []string) int {
workspaces := []string{}
seen := mapset.NewSet()
var lockfileWg sync.WaitGroup
pkg, err := fs.ReadPackageJSON("package.json")
pkg, err := fs.ReadPackageJSON(filepath.Join(pruneOptions.cwd, "package.json"))
if err != nil {
c.logError(c.Config.Logger, "", fmt.Errorf("could not read package.json: %w", err))
return 1
Expand Down
32 changes: 15 additions & 17 deletions cli/internal/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,27 +135,21 @@ func (c *RunCommand) Run(args []string) int {
return 1
}

cwd, err := os.Getwd()
if err != nil {
c.logError(c.Config.Logger, "", fmt.Errorf("invalid working directory?: %w", err))
return 1
}

runOptions, err := parseRunArgs(args, cwd, c.Ui)
runOptions, err := parseRunArgs(args, c.Ui)
if err != nil {
c.logError(c.Config.Logger, "", err)
return 1
}

c.Config.Cache.Dir = runOptions.cacheFolder

ctx, err := context.New(context.WithTracer(runOptions.profile), context.WithArgs(args), context.WithGraph(".", c.Config))
ctx, err := context.New(context.WithTracer(runOptions.profile), context.WithArgs(args), context.WithGraph(runOptions.cwd, c.Config))
if err != nil {
c.logError(c.Config.Logger, "", err)
return 1
}

gitRepoRoot, err := fs.FindupFrom(".git", cwd)
gitRepoRoot, err := fs.FindupFrom(".git", runOptions.cwd)
if err != nil {
c.logWarning(c.Config.Logger, "Cannot find a .git folder in current working directory or in any parent directories. Falling back to manual file hashing (which may be slower). If you are running this build in a pruned directory, you can ignore this message. Otherwise, please initialize a git repository in the root of your monorepo.", err)
}
Expand All @@ -177,7 +171,7 @@ func (c *RunCommand) Run(args []string) int {
hasRepoGlobalFileChanged := false
var changedFiles []string
if runOptions.since != "" {
changedFiles = git.ChangedFiles(runOptions.since, true, cwd)
changedFiles = git.ChangedFiles(runOptions.since, true, runOptions.cwd)
}

ignoreSet := make(util.Set)
Expand Down Expand Up @@ -319,10 +313,10 @@ func (c *RunCommand) Run(args []string) int {
Opts: runOptions,
}
backend := ctx.Backend
return c.runOperation(g, rs, backend, cwd, startAt)
return c.runOperation(g, rs, backend, startAt)
}

func (c *RunCommand) runOperation(g *completeGraph, rs *runSpec, backend *api.LanguageBackend, cwd string, startAt time.Time) int {
func (c *RunCommand) runOperation(g *completeGraph, rs *runSpec, backend *api.LanguageBackend, startAt time.Time) int {
goctx := gocontext.Background()
var analyticsSink analytics.Sink
if c.Config.IsLoggedIn() {
Expand Down Expand Up @@ -685,7 +679,7 @@ func (c *RunCommand) runOperation(g *completeGraph, rs *runSpec, backend *api.La
}))
ext := filepath.Ext(rs.Opts.dotGraph)
if ext == ".html" {
f, err := os.Create(filepath.Join(cwd, rs.Opts.dotGraph))
f, err := os.Create(filepath.Join(rs.Opts.cwd, rs.Opts.dotGraph))
if err != nil {
c.logError(c.Config.Logger, "", fmt.Errorf("error writing graph: %w", err))
return 1
Expand All @@ -709,7 +703,7 @@ func (c *RunCommand) runOperation(g *completeGraph, rs *runSpec, backend *api.La
c.Ui.Output("")
c.Ui.Output(fmt.Sprintf("✔ Generated task graph in %s", ui.Bold(rs.Opts.dotGraph)))
if ui.IsTTY {
browser.OpenBrowser(filepath.Join(cwd, rs.Opts.dotGraph))
browser.OpenBrowser(filepath.Join(rs.Opts.cwd, rs.Opts.dotGraph))
}
return 0
}
Expand Down Expand Up @@ -815,13 +809,19 @@ func getDefaultRunOptions() *RunOptions {
}
}

func parseRunArgs(args []string, cwd string, output cli.Ui) (*RunOptions, error) {
func parseRunArgs(args []string, output cli.Ui) (*RunOptions, error) {
var runOptions = getDefaultRunOptions()

if len(args) == 0 {
return nil, errors.Errorf("At least one task must be specified.")
}

cwd, err := os.Getwd()
if err != nil {
return nil, fmt.Errorf("invalid working directory: %w", err)
}
runOptions.cwd = cwd

unresolvedCacheFolder := filepath.FromSlash("./node_modules/.cache/turbo")

for argIndex, arg := range args {
Expand Down Expand Up @@ -849,8 +849,6 @@ func parseRunArgs(args []string, cwd string, output cli.Ui) (*RunOptions, error)
case strings.HasPrefix(arg, "--cwd="):
if len(arg[len("--cwd="):]) > 0 {
runOptions.cwd = arg[len("--cwd="):]
} else {
runOptions.cwd = cwd
}
case strings.HasPrefix(arg, "--parallel"):
runOptions.parallel = true
Expand Down
25 changes: 18 additions & 7 deletions cli/internal/run/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import (
)

func TestParseConfig(t *testing.T) {
defaultCwd, err := os.Getwd()
if err != nil {
t.Errorf("failed to get cwd: %v", err)
}
defaultCacheFolder := filepath.Join(defaultCwd, filepath.FromSlash("node_modules/.cache/turbo"))
cases := []struct {
Name string
Args []string
Expand All @@ -32,7 +37,8 @@ func TestParseConfig(t *testing.T) {
cache: true,
forceExecution: false,
profile: "",
cacheFolder: filepath.FromSlash("node_modules/.cache/turbo"),
cwd: defaultCwd,
cacheFolder: defaultCacheFolder,
},
},
{
Expand Down Expand Up @@ -66,7 +72,8 @@ func TestParseConfig(t *testing.T) {
forceExecution: false,
profile: "",
scope: []string{"foo", "blah"},
cacheFolder: filepath.FromSlash("node_modules/.cache/turbo"),
cwd: defaultCwd,
cacheFolder: defaultCacheFolder,
},
},
{
Expand All @@ -82,7 +89,8 @@ func TestParseConfig(t *testing.T) {
cache: true,
forceExecution: false,
profile: "",
cacheFolder: filepath.FromSlash("node_modules/.cache/turbo"),
cwd: defaultCwd,
cacheFolder: defaultCacheFolder,
},
},
{
Expand All @@ -98,7 +106,8 @@ func TestParseConfig(t *testing.T) {
cache: true,
forceExecution: false,
profile: "",
cacheFolder: filepath.FromSlash("node_modules/.cache/turbo"),
cwd: defaultCwd,
cacheFolder: defaultCacheFolder,
},
},
{
Expand All @@ -114,7 +123,8 @@ func TestParseConfig(t *testing.T) {
cache: true,
forceExecution: false,
profile: "",
cacheFolder: filepath.FromSlash("node_modules/.cache/turbo"),
cwd: defaultCwd,
cacheFolder: defaultCacheFolder,
passThroughArgs: []string{"--boop", "zoop"},
},
},
Expand All @@ -131,7 +141,8 @@ func TestParseConfig(t *testing.T) {
cache: true,
forceExecution: false,
profile: "",
cacheFolder: filepath.FromSlash("node_modules/.cache/turbo"),
cwd: defaultCwd,
cacheFolder: defaultCacheFolder,
passThroughArgs: []string{},
},
},
Expand All @@ -146,7 +157,7 @@ func TestParseConfig(t *testing.T) {
for i, tc := range cases {
t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {

actual, err := parseRunArgs(tc.Args, ".", ui)
actual, err := parseRunArgs(tc.Args, ui)
if err != nil {
t.Fatalf("invalid parse: %#v", err)
}
Expand Down