diff --git a/cli/internal/context/context.go b/cli/internal/context/context.go index 819833205c19c..4727ac083a1a8 100644 --- a/cli/internal/context/context.go +++ b/cli/internal/context/context.go @@ -2,6 +2,7 @@ package context import ( "fmt" + "log" "os" "path" "path/filepath" @@ -36,6 +37,7 @@ type Context struct { Dir string RootNode string RootPackageJSON *fs.PackageJSON + TurboConfig *fs.TurboConfigJSON GlobalHashableEnvPairs []string GlobalHashableEnvNames []string GlobalHash string @@ -97,12 +99,38 @@ func WithGraph(rootpath string, config *config.Config) Option { return fmt.Errorf("could not get cwd: %w", err) } - pkg, err := fs.ReadPackageJSON("package.json") + packageJSONPath := path.Join(rootpath, "package.json") + pkg, err := fs.ReadPackageJSON(packageJSONPath) if err != nil { return fmt.Errorf("package.json: %w", err) } c.RootPackageJSON = pkg + // If turbo.json exists, we use that + // 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") + if !fs.FileExists(turboJSONPath) { + if pkg.LegacyTurboConfig == nil { + // TODO: suggestion on how to create one + return fmt.Errorf("Could not find turbo.json. Follow directions at https://turborepo.org/docs/getting-started to create one") + } else { + log.Println("[WARNING] Turbo configuration now lives in \"turbo.json\". Migrate to turbo.json by running \"npx @turbo/codemod create-turbo-config\"") + c.TurboConfig = pkg.LegacyTurboConfig + } + } else { + turbo, err := fs.ReadTurboConfigJSON(turboJSONPath) + if err != nil { + return fmt.Errorf("turbo.json: %w", err) + } + c.TurboConfig = turbo + if pkg.LegacyTurboConfig != nil { + log.Println("[WARNING] Ignoring legacy \"turbo\" key in package.json, using turbo.json instead. Consider deleting the \"turbo\" key from package.json") + pkg.LegacyTurboConfig = nil + } + } + if backend, err := backends.GetBackend(cwd, pkg); err != nil { return err } else { @@ -132,9 +160,9 @@ func WithGraph(rootpath string, config *config.Config) Option { globalDeps := make(util.Set) // Calculate global file and env var dependencies - if len(pkg.Turbo.GlobalDependencies) > 0 { + if len(c.TurboConfig.GlobalDependencies) > 0 { var globs []string - for _, v := range pkg.Turbo.GlobalDependencies { + for _, v := range c.TurboConfig.GlobalDependencies { if strings.HasPrefix(v, "$") { trimmed := strings.TrimPrefix(v, "$") c.GlobalHashableEnvNames = append(c.GlobalHashableEnvNames, trimmed) @@ -188,7 +216,7 @@ func WithGraph(rootpath string, config *config.Config) Option { return fmt.Errorf("error hashing global dependencies %w", err) } c.GlobalHash = globalHash - targets, err := GetTargetsFromArguments(c.Args, &c.RootPackageJSON.Turbo) + targets, err := GetTargetsFromArguments(c.Args, c.TurboConfig) if err != nil { return err } @@ -284,7 +312,7 @@ func (c *Context) loadPackageDepsHash(pkg *fs.PackageJSON) error { return nil } -func (c *Context) ResolveWorkspaceRootDeps() (error) { +func (c *Context) ResolveWorkspaceRootDeps() error { seen := mapset.NewSet() var lockfileWg sync.WaitGroup pkg := c.RootPackageJSON diff --git a/cli/internal/fs/package_json.go b/cli/internal/fs/package_json.go index 95667ea1f9f9d..5f6a0b9ba6187 100644 --- a/cli/internal/fs/package_json.go +++ b/cli/internal/fs/package_json.go @@ -6,15 +6,35 @@ import ( "sync" ) +// TurboConfigJSON is the root turborepo configuration type TurboConfigJSON struct { + // Base Git branch Base string `json:"baseBranch,omitempty"` + // Global root filesystem dependencies GlobalDependencies []string `json:"globalDependencies,omitempty"` TurboCacheOptions string `json:"cacheOptions,omitempty"` Outputs []string `json:"outputs,omitempty"` + // RemoteCacheUrl is the Remote Cache API URL RemoteCacheUrl string `json:"remoteCacheUrl,omitempty"` + // Pipeline is a map of Turbo pipeline entries which define the task graph + // and cache behavior on a per task or per package-task basis. Pipeline map[string]Pipeline } +func ReadTurboConfigJSON(path string) (*TurboConfigJSON, error) { + b, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + var turboConfig *TurboConfigJSON + err = json.Unmarshal(b, &turboConfig) + if err != nil { + println("error unmarshalling", err.Error()) + return nil, err + } + return turboConfig, nil +} + type PPipeline struct { Outputs *[]string `json:"outputs"` Cache *bool `json:"cache,omitempty"` @@ -64,7 +84,7 @@ type PackageJSON struct { UnresolvedExternalDeps map[string]string ExternalDeps []string SubLockfile YarnLockfile - Turbo TurboConfigJSON `json:"turbo"` + LegacyTurboConfig *TurboConfigJSON `json:"turbo"` Mu sync.Mutex FilesHash string ExternalDepsHash string diff --git a/cli/internal/run/run.go b/cli/internal/run/run.go index 94370e6b4988b..a3b681ba8a4c7 100644 --- a/cli/internal/run/run.go +++ b/cli/internal/run/run.go @@ -344,7 +344,7 @@ func (c *RunCommand) Run(args []string) int { runState.Listen(c.Ui, time.Now()) engine := core.NewScheduler(&ctx.TopologicalGraph) var logReplayWaitGroup sync.WaitGroup - for taskName, value := range ctx.RootPackageJSON.Turbo.Pipeline { + for taskName, value := range ctx.TurboConfig.Pipeline { topoDeps := make(util.Set) deps := make(util.Set) if util.IsPackageTask(taskName) { @@ -410,10 +410,10 @@ func (c *RunCommand) Run(args []string) int { } // Hash --------------------------------------------- // first check for package-tasks - pipeline, ok := ctx.RootPackageJSON.Turbo.Pipeline[fmt.Sprintf("%v", id)] + pipeline, ok := ctx.TurboConfig.Pipeline[fmt.Sprintf("%v", id)] if !ok { // then check for regular tasks - altpipe, notcool := ctx.RootPackageJSON.Turbo.Pipeline[task] + altpipe, notcool := ctx.TurboConfig.Pipeline[task] // if neither, then bail if !notcool && !ok { return nil diff --git a/cli/scripts/generate.mjs b/cli/scripts/generate.mjs index a67d87ebb35fc..d37f450de8f68 100644 --- a/cli/scripts/generate.mjs +++ b/cli/scripts/generate.mjs @@ -82,22 +82,7 @@ turbo-linux [type]: "*", }, } - : { - turbo: { - pipeline: { - build: { - outputs: ["dist/**/*"], - dependsOn: ["^build"], - }, - test: { - dependsOn: ["build"], - }, - dev: { - cache: false, - }, - }, - }, - }; + : {}; fs.writeFileSync( path.join(root, "package.json"), @@ -108,7 +93,7 @@ turbo-linux private: true, workspaces: ["packages/*"], ...deps, - packageManager: "yarn@1.22.17" + packageManager: "yarn@1.22.17", }, null, 2 @@ -157,6 +142,18 @@ turbo-linux provider: "local", cacheUrl: "https://1a77600385dd.ngrok.io", }, + pipeline: { + build: { + outputs: ["dist/**/*"], + dependsOn: ["^build"], + }, + test: { + dependsOn: ["build"], + }, + dev: { + cache: false, + }, + }, }, null, 2 diff --git a/cli/scripts/monorepo.ts b/cli/scripts/monorepo.ts index 7fd5ddde4729c..729bc38e240fd 100644 --- a/cli/scripts/monorepo.ts +++ b/cli/scripts/monorepo.ts @@ -158,8 +158,8 @@ importers: execa.sync("yarn", ["install"], { cwd, env: { - "YARN_ENABLE_IMMUTABLE_INSTALLS": "false" - } + YARN_ENABLE_IMMUTABLE_INSTALLS: "false", + }, }); this.commitAll(); return; @@ -182,10 +182,10 @@ importers: test: `${turboPath} run test`, lint: `${turboPath} run lint`, }, - turbo: { - baseBranch: "origin/main", - ...turboConfig, - }, + }, + "turbo.json": { + baseBranch: "origin/main", + ...turboConfig, }, }); } @@ -222,7 +222,10 @@ fs.copyFileSync( internalDeps.reduce((deps, dep) => { return { ...deps, - [dep]: (this.npmClient === "pnpm" || this.npmClient === "berry") ? "workspace:*" : "*", + [dep]: + this.npmClient === "pnpm" || this.npmClient === "berry" + ? "workspace:*" + : "*", }; }, {})), }, diff --git a/create-turbo/templates/_shared_ts/package.json b/create-turbo/templates/_shared_ts/package.json index 43e9817e82a9f..fcb758a608957 100644 --- a/create-turbo/templates/_shared_ts/package.json +++ b/create-turbo/templates/_shared_ts/package.json @@ -16,25 +16,6 @@ "prettier": "^2.5.1", "turbo": "*" }, - "turbo": { - "pipeline": { - "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "dist/**", - ".next/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } - }, "engines": { "npm": ">=7.0.0", "node": ">=14.0.0" diff --git a/create-turbo/templates/_shared_ts/turbo.json b/create-turbo/templates/_shared_ts/turbo.json new file mode 100644 index 0000000000000..33d0621ee2f4d --- /dev/null +++ b/create-turbo/templates/_shared_ts/turbo.json @@ -0,0 +1,14 @@ +{ + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", ".next/**"] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + } + } +} diff --git a/create-turbo/templates/npm/package.json b/create-turbo/templates/npm/package.json index 9be9226892e15..3bf4c70411294 100644 --- a/create-turbo/templates/npm/package.json +++ b/create-turbo/templates/npm/package.json @@ -15,24 +15,5 @@ "devDependencies": { "prettier": "^2.5.1", "turbo": "*" - }, - "turbo": { - "pipeline": { - "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "dist/**", - ".next/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } } } diff --git a/create-turbo/templates/npm/turbo.json b/create-turbo/templates/npm/turbo.json new file mode 100644 index 0000000000000..33d0621ee2f4d --- /dev/null +++ b/create-turbo/templates/npm/turbo.json @@ -0,0 +1,14 @@ +{ + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", ".next/**"] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + } + } +} diff --git a/create-turbo/templates/pnpm/package.json b/create-turbo/templates/pnpm/package.json index d54edd92e54e8..9644536b51f12 100644 --- a/create-turbo/templates/pnpm/package.json +++ b/create-turbo/templates/pnpm/package.json @@ -11,24 +11,5 @@ "devDependencies": { "prettier": "^2.5.1", "turbo": "latest" - }, - "turbo": { - "pipeline": { - "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "dist/**", - ".next/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } } } diff --git a/create-turbo/templates/pnpm/turbo.json b/create-turbo/templates/pnpm/turbo.json new file mode 100644 index 0000000000000..33d0621ee2f4d --- /dev/null +++ b/create-turbo/templates/pnpm/turbo.json @@ -0,0 +1,14 @@ +{ + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", ".next/**"] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + } + } +} diff --git a/create-turbo/templates/yarn/package.json b/create-turbo/templates/yarn/package.json index efa99167c8044..55b8d565d69dd 100644 --- a/create-turbo/templates/yarn/package.json +++ b/create-turbo/templates/yarn/package.json @@ -15,24 +15,5 @@ "devDependencies": { "prettier": "^2.5.1", "turbo": "*" - }, - "turbo": { - "pipeline": { - "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "dist/**", - ".next/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } } } diff --git a/create-turbo/templates/yarn/turbo.json b/create-turbo/templates/yarn/turbo.json new file mode 100644 index 0000000000000..33d0621ee2f4d --- /dev/null +++ b/create-turbo/templates/yarn/turbo.json @@ -0,0 +1,14 @@ +{ + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", ".next/**"] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + } + } +} diff --git a/docs/pages/docs/features/pipelines.mdx b/docs/pages/docs/features/pipelines.mdx index b1e4f61051801..336e67acab925 100644 --- a/docs/pages/docs/features/pipelines.mdx +++ b/docs/pages/docs/features/pipelines.mdx @@ -22,7 +22,7 @@ Notice that `turbo` is able to schedule tasks efficiently--collapsing waterfalls ## Defining a `pipeline` -To define your project's task dependency graph, use the [`pipeline`](../reference/configuration#pipeline) key in the root `package.json`'s `turbo` configuration. `turbo` interprets this configuration and conventions to properly schedule, execute, and cache the outputs of the tasks in your project. +To define your project's task dependency graph, use the [`pipeline`](../reference/configuration#pipeline) key in the `turbo.json` configuration file at the root of your project. `turbo` interprets this configuration and conventions to properly schedule, execute, and cache the outputs of the tasks in your project. Each key in the [`pipeline`](../reference/configuration#pipeline) object is the name of a task that can be executed by [`turbo run`](../reference/command-line-reference#turbo-run-task1-task2-1). You can specify its dependencies with the [`dependsOn`](../reference/configuration#dependson) key beneath it as well as some other options related to [caching](./caching). diff --git a/docs/pages/docs/getting-started.mdx b/docs/pages/docs/getting-started.mdx index 5e219760a8d87..f719de5212a65 100644 --- a/docs/pages/docs/getting-started.mdx +++ b/docs/pages/docs/getting-started.mdx @@ -56,43 +56,41 @@ pnpm add turbo -DW The `turbo` package is a little shell that will install the proper `@turborepo/*` packages. -### Add `turbo` to `package.json` +### Create `turbo.json` -In your root `package.json`, add a key `turbo`. If your git repo's base branch is NOT `origin/master` then you need to specify a `baseBranch` too (for example, ours is set to `origin/main`). +In your root directory, create an empty file named `turbo.json`. +This will hold the configuration for Turborepo in your project. +If your git repo's base branch is NOT `origin/master` then you need to specify a `baseBranch` too (for example, ours is set to `origin/main`). ```json { - "turbo": { - "baseBranch": "origin/main" - } + "baseBranch": "origin/main" } ``` ### Create a `pipeline` -In your `package.json`, add the commands you want to "turbocharge" to your pipeline. +In `turbo.json`, add the commands you want to "turbocharge" to your pipeline. Your pipeline both defines the way in which your NPM `package.json` scripts relate to each other, and configures cache artifacts for those scripts. These relationships and cache settings are then fanned out and applied to all package tasks across your entire monorepo. ```json { - "turbo": { - "baseBranch": "origin/main", - "pipeline": { - "build": { - "dependsOn": ["^build"], - "outputs": [".next/**"] - }, - "test": { - "dependsOn": ["^build"], - "outputs": [] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } + "baseBranch": "origin/main", + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": [".next/**"] + }, + "test": { + "dependsOn": ["^build"], + "outputs": [] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false } } } diff --git a/docs/pages/docs/reference/codemods.mdx b/docs/pages/docs/reference/codemods.mdx index 95f7b9fa89ec2..3056e2a8a66ed 100644 --- a/docs/pages/docs/reference/codemods.mdx +++ b/docs/pages/docs/reference/codemods.mdx @@ -69,3 +69,56 @@ Run the codemod: ```sh npx @turbo/codemod add-package-manager ``` + +### `create-turbo-config` + +Creates the `turbo.json` file at the root of your project based on the `"turbo"` key in `package.json`. +The `"turbo"` key is subsequently deleted from `package.json`. + +For example: + +```json +// Before, package.json +{ + "name": "Monorepo root", + "private": true, + "turbo": { + "baseBranch": "origin/main", + "pipeline": { + ... + } + }, + ... +} +``` + +```json +// After, package.json +{ + "name": "Monorepo root", + "private": true, + ... +} + +// After, turbo.json +{ + "baseBranch": "origin/main", + "pipeline": { + ... + } +} +``` + +#### Usage + +Go to your project: + +```sh +cd path-to-your-turborepo/ +``` + +Run the codemod: + +```sh +npx @turbo/codemod create-turbo-config +``` diff --git a/docs/pages/docs/reference/configuration.mdx b/docs/pages/docs/reference/configuration.mdx index e455cf74173e9..158cfa1e01584 100644 --- a/docs/pages/docs/reference/configuration.mdx +++ b/docs/pages/docs/reference/configuration.mdx @@ -4,7 +4,7 @@ title: Configuration Options # Configuration Options -You can configure the behavior of `turbo` by adding a `turbo` object in the `package.json` in your monorepo's root (i.e. the same one you specify your `workspaces` key is set for Yarn and NPM users). +You can configure the behavior of `turbo` by adding a `turbo.json` file in your monorepo's root (i.e. the same one you specify your `workspaces` key is set for Yarn and NPM users). ## `baseBranch` @@ -23,17 +23,15 @@ This is useful for busting the cache based on `.env` files (not in Git), environ ```json { - "turbo": { - "pipeline": { - // ... omitted for brevity - }, - - "globalDependencies": [ - ".env", // contents will impact hashes of all tasks - "tsconfig.json", // contents will impact hashes of all tasks - "$GITHUB_TOKEN"// value will impact the hashes of all tasks - ] - } + "pipeline": { + // ... omitted for brevity + }, + + "globalDependencies": [ + ".env", // contents will impact hashes of all tasks + "tsconfig.json", // contents will impact hashes of all tasks + "$GITHUB_TOKEN"// value will impact the hashes of all tasks + ] } ``` @@ -51,18 +49,16 @@ Each key in the `pipeline` object is the name of a task that can be executed by ```json { - "turbo": { - "pipeline": { - "build": { - "dependsOn": ["^build"] - }, - "test": { - "outputs": ["coverage/**"], - "dependsOn": ["build"] - }, - "dev": { - "cache": false - } + "pipeline": { + "build": { + "dependsOn": ["^build"] + }, + "test": { + "outputs": ["coverage/**"], + "dependsOn": ["build"] + }, + "dev": { + "cache": false } } } @@ -84,26 +80,24 @@ Prefixing an item in `dependsOn` with a `$` tells `turbo` that this pipeline tas ```json { - "turbo": { - "pipeline": { - "build": { - // "A package's `build` command depends on its dependencies' - // or devDependencies' `build` command being completed first" - "dependsOn": ["^build"] - }, - "test": { - // "A package's `test` command depends on its own `lint` and - // `build` commands first being completed" - "dependsOn": ["lint", "build"] - }, - "deploy": { - // "A package's `deploy` command, depends on its own `build` - // and `test` commands first being completed" - "dependsOn": ["build", "test"] - }, - // A package's `lint` command has no dependencies - "lint": {} - } + "pipeline": { + "build": { + // "A package's `build` command depends on its dependencies' + // or devDependencies' `build` command being completed first" + "dependsOn": ["^build"] + }, + "test": { + // "A package's `test` command depends on its own `lint` and + // `build` commands first being completed" + "dependsOn": ["lint", "build"] + }, + "deploy": { + // "A package's `deploy` command, depends on its own `build` + // and `test` commands first being completed" + "dependsOn": ["build", "test"] + }, + // A package's `lint` command has no dependencies + "lint": {} } } ``` @@ -112,28 +106,26 @@ Prefixing an item in `dependsOn` with a `$` tells `turbo` that this pipeline tas ```json { - "turbo": { - "pipeline": { - "build": { - "dependsOn": { - "^build", - "$SOMETHING_ELSE" // value will impact the hashes of all build tasks - }, - "outputs": ["dist/**", ".next/**"] + "pipeline": { + "build": { + "dependsOn": { + "^build", + "$SOMETHING_ELSE" // value will impact the hashes of all build tasks }, - "web#build": { - "dependsOn": [ - "^build", - "$STRIPE_SECRET_KEY", // value will impact hash of only web's build task - "$NEXT_PUBLIC_STRIPE_PUBLIC_KEY" - ], - "outputs": [".next/**"] - } + "outputs": ["dist/**", ".next/**"] }, - "globalDependencies": [ - "$GITHUB_TOKEN"// value will impact the hashes of all tasks - ] - } + "web#build": { + "dependsOn": [ + "^build", + "$STRIPE_SECRET_KEY", // value will impact hash of only web's build task + "$NEXT_PUBLIC_STRIPE_PUBLIC_KEY" + ], + "outputs": [".next/**"] + } + }, + "globalDependencies": [ + "$GITHUB_TOKEN"// value will impact the hashes of all tasks + ] } ``` diff --git a/examples/basic/package.json b/examples/basic/package.json index 00537c8f8f68e..62f141eabd27f 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -15,24 +15,5 @@ "devDependencies": { "prettier": "^2.5.1", "turbo": "latest" - }, - "turbo": { - "pipeline": { - "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "dist/**", - ".next/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } } } diff --git a/examples/basic/turbo.json b/examples/basic/turbo.json new file mode 100644 index 0000000000000..df69a7e0c2b48 --- /dev/null +++ b/examples/basic/turbo.json @@ -0,0 +1,19 @@ +{ + "pipeline": { + "build": { + "dependsOn": [ + "^build" + ], + "outputs": [ + "dist/**", + ".next/**" + ] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + } + } +} diff --git a/examples/design-system/package.json b/examples/design-system/package.json index 796e3a4949313..1e02c2e09bc4d 100755 --- a/examples/design-system/package.json +++ b/examples/design-system/package.json @@ -18,33 +18,5 @@ "eslint": "7.32.0", "prettier": "^2.5.1", "turbo": "latest" - }, - "turbo": { - "pipeline": { - "build": { - "outputs": [ - "dist/**", - ".next/**" - ], - "dependsOn": [ - "^build" - ] - }, - "test": { - "outputs": [ - "coverage/**" - ], - "dependsOn": [] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - }, - "clean": { - "cache": false - } - } } } diff --git a/examples/design-system/turbo.json b/examples/design-system/turbo.json new file mode 100644 index 0000000000000..284edea98ce4c --- /dev/null +++ b/examples/design-system/turbo.json @@ -0,0 +1,28 @@ +{ + "pipeline": { + "build": { + "outputs": [ + "dist/**", + ".next/**" + ], + "dependsOn": [ + "^build" + ] + }, + "test": { + "outputs": [ + "coverage/**" + ], + "dependsOn": [] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + }, + "clean": { + "cache": false + } + } +} diff --git a/examples/kitchen-sink/package.json b/examples/kitchen-sink/package.json index 664d08d596c47..bba71cc782611 100755 --- a/examples/kitchen-sink/package.json +++ b/examples/kitchen-sink/package.json @@ -17,37 +17,5 @@ "devDependencies": { "prettier": "^2.5.1", "turbo": "latest" - }, - "turbo": { - "pipeline": { - "build": { - "outputs": [ - "dist/**", - ".next/**", - "public/dist/**" - ], - "dependsOn": [ - "^build" - ] - }, - "test": { - "outputs": [ - "coverage/**" - ], - "dependsOn": [] - }, - "lint": { - "dependsOn": [ - "^build" - ], - "outputs": [] - }, - "dev": { - "cache": false - }, - "clean": { - "cache": false - } - } } } diff --git a/examples/kitchen-sink/turbo.json b/examples/kitchen-sink/turbo.json new file mode 100644 index 0000000000000..0a573acf5e1f0 --- /dev/null +++ b/examples/kitchen-sink/turbo.json @@ -0,0 +1,32 @@ +{ + "pipeline": { + "build": { + "outputs": [ + "dist/**", + ".next/**", + "public/dist/**" + ], + "dependsOn": [ + "^build" + ] + }, + "test": { + "outputs": [ + "coverage/**" + ], + "dependsOn": [] + }, + "lint": { + "dependsOn": [ + "^build" + ], + "outputs": [] + }, + "dev": { + "cache": false + }, + "clean": { + "cache": false + } + } +} diff --git a/examples/with-pnpm/package.json b/examples/with-pnpm/package.json index c39cc140c5880..256fff4f58bae 100644 --- a/examples/with-pnpm/package.json +++ b/examples/with-pnpm/package.json @@ -11,24 +11,5 @@ "eslint": "7.32.0", "prettier": "^2.5.1", "turbo": "latest" - }, - "turbo": { - "pipeline": { - "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "dist/**", - ".next/**" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - } - } } } diff --git a/examples/with-pnpm/turbo.json b/examples/with-pnpm/turbo.json new file mode 100644 index 0000000000000..df69a7e0c2b48 --- /dev/null +++ b/examples/with-pnpm/turbo.json @@ -0,0 +1,19 @@ +{ + "pipeline": { + "build": { + "dependsOn": [ + "^build" + ], + "outputs": [ + "dist/**", + ".next/**" + ] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + } + } +} diff --git a/package.json b/package.json index 9ece25bd5a1c6..521260a475896 100644 --- a/package.json +++ b/package.json @@ -31,52 +31,6 @@ "simple-git-hooks": { "pre-commit": "npx lint-staged" }, - "turbo": { - "baseBranch": "origin/main", - "env": [ - "CONVERTKIT_API_KEY", - "CONVERTKIT_API_SECRET", - "CONVERTKIT_FORM_ID" - ], - "pipeline": { - "test": { - "outputs": [ - "coverage/**/*" - ], - "dependsOn": [ - "^build" - ] - }, - "lint": { - "outputs": [] - }, - "dev": { - "cache": false - }, - "build": { - "outputs": [ - "dist/**/*", - ".next/**/*" - ], - "dependsOn": [ - "^build" - ] - }, - "cli#build": { - "outputs": [ - "turbo", - "turbo.exe" - ], - "dependsOn": [] - }, - "create-turbo#test": { - "dependsOn": [ - "create-turbo#build" - ], - "outputs": [] - } - } - }, "packageManager": "yarn@1.22.17", "dependencies": { "patch-package": "^6.4.7" diff --git a/turbo-codemod/src/index.ts b/turbo-codemod/src/index.ts index 97734a0287d21..fe27ce3094fda 100644 --- a/turbo-codemod/src/index.ts +++ b/turbo-codemod/src/index.ts @@ -29,6 +29,10 @@ const TRANSFORMER_INQUIRER_CHOICES = [ name: "add-package-manager: Set the `packageManager` key in root package.json file", value: "add-package-manager", }, + { + name: 'create-turbo-config: Creates the turbo.json file from an existing "turbo" key in package.json', + value: "create-turbo-config", + }, ]; run() diff --git a/turbo-codemod/src/transforms/create-turbo-config.ts b/turbo-codemod/src/transforms/create-turbo-config.ts new file mode 100644 index 0000000000000..0ba586f362de7 --- /dev/null +++ b/turbo-codemod/src/transforms/create-turbo-config.ts @@ -0,0 +1,51 @@ +import fs from "fs-extra"; +import path from "path"; +import { Flags } from "../types"; +import chalk from "chalk"; + +export default function createTurboConfig(files: string[], flags: Flags) { + if (files.length === 1) { + const dir = files[0]; + const root = path.resolve(process.cwd(), dir); + console.log(`Migrating package.json "turbo" key to "turbo.json" file...`); + const turboConfigPath = path.join(root, "turbo.json"); + + const rootPackageJsonPath = path.join(root, "package.json"); + if (!fs.existsSync(rootPackageJsonPath)) { + error(`No package.json found at ${root}. Is the path correct?`); + process.exit(1); + } + const rootPackageJson = fs.readJsonSync(rootPackageJsonPath); + + if (fs.existsSync(turboConfigPath)) { + skip("turbo.json already exists"); + return; + } + + if (rootPackageJson.hasOwnProperty("turbo")) { + const { turbo: turboConfig, ...remainingPkgJson } = rootPackageJson; + if (flags.dry) { + skip("Skipping writing turbo.json (dry run)"); + skip('Skipping deleting "turbo" key from package.json (dry run)'); + } else { + console.log("Writing turbo.json"); + fs.writeJsonSync(turboConfigPath, turboConfig, { spaces: 2 }); + console.log('Removing "turbo" key from package.json'); + fs.writeJsonSync(rootPackageJsonPath, remainingPkgJson, { spaces: 2 }); + } + } else { + skip('"turbo" key does not exist in package.json'); + } + ok("Finished"); + } +} + +function skip(...args: any[]) { + console.log(chalk.yellow.inverse(` SKIP `), ...args); +} +function error(...args: any[]) { + console.log(chalk.red.inverse(` ERROR `), ...args); +} +function ok(...args: any[]) { + console.log(chalk.green.inverse(` OK `), ...args); +} diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000000000..71fe99be76c2f --- /dev/null +++ b/turbo.json @@ -0,0 +1,46 @@ +{ + "baseBranch": "origin/main", + "env": [ + "CONVERTKIT_API_KEY", + "CONVERTKIT_API_SECRET", + "CONVERTKIT_FORM_ID" + ], + "pipeline": { + "test": { + "outputs": [ + "coverage/**/*" + ], + "dependsOn": [ + "^build" + ] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + }, + "build": { + "outputs": [ + "dist/**/*", + ".next/**/*" + ], + "dependsOn": [ + "^build" + ] + }, + "cli#build": { + "outputs": [ + "turbo", + "turbo.exe" + ], + "dependsOn": [] + }, + "create-turbo#test": { + "dependsOn": [ + "create-turbo#build" + ], + "outputs": [] + } + } +}