From 1f866db4a1b05f2f9776262e4462f0eafe7b4d25 Mon Sep 17 00:00:00 2001 From: Thomas Knickman Date: Sat, 25 Feb 2023 18:16:45 -0500 Subject: [PATCH 01/16] feat(turbo-utils): bundle to esm (#3952 Now that we're throwing a few more things in turbo-utils, we should bundle it to esm instead of cjs to support code splitting. This is an internal package, and everything that consumes this bundles to cjs, so compatibility isn't an issue, and this will ensure each package that uses a util from turbo-utils only gets what it needs instead of the entire package. I tested this locally to see the bundle size difference. For turbo-ignore, the bundle size drops from `245K` to `229K`. No _huge_ (~6%) but worth it. --- packages/turbo-utils/package.json | 1 + packages/turbo-utils/tsup.config.ts | 6 +++++- pnpm-lock.yaml | 12 ++---------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/turbo-utils/package.json b/packages/turbo-utils/package.json index a7f0bdadde7a5..69b883b2ac62b 100644 --- a/packages/turbo-utils/package.json +++ b/packages/turbo-utils/package.json @@ -15,6 +15,7 @@ "bugs": { "url": "https://github.com/vercel/turbo/issues" }, + "module": "dist/index.mjs", "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { diff --git a/packages/turbo-utils/tsup.config.ts b/packages/turbo-utils/tsup.config.ts index 8728c85248204..716b7a5ac4d72 100644 --- a/packages/turbo-utils/tsup.config.ts +++ b/packages/turbo-utils/tsup.config.ts @@ -1,8 +1,12 @@ import { defineConfig, Options } from "tsup"; export default defineConfig((options: Options) => ({ - entry: ["src/index.ts"], + entry: ["src/**/*.ts"], + treeshake: true, + splitting: true, + format: ["esm", "cjs"], dts: true, + minify: true, clean: true, ...options, })); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d876d1c310c37..e2a10b3b0d300 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -797,20 +797,12 @@ packages: resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} engines: {node: '>=6.9.0'} - /@babel/helper-function-name/7.19.0: - resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.20.7 - '@babel/types': 7.21.0 - /@babel/helper-function-name/7.21.0: resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.20.7 '@babel/types': 7.21.0 - dev: true /@babel/helper-hoist-variables/7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} @@ -1106,11 +1098,11 @@ packages: '@babel/code-frame': 7.18.6 '@babel/generator': 7.20.7 '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 + '@babel/helper-function-name': 7.21.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 '@babel/parser': 7.20.7 - '@babel/types': 7.20.7 + '@babel/types': 7.21.0 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: From 67354b250906fadace9c51a5783f2c3b6c8d6cdc Mon Sep 17 00:00:00 2001 From: Lee Robinson Date: Sun, 26 Feb 2023 16:52:24 -0600 Subject: [PATCH 02/16] Update index.mdx (#3958) --- docs/pages/pack/docs/index.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/pages/pack/docs/index.mdx b/docs/pages/pack/docs/index.mdx index 93cec383b9e19..3cbc782703f38 100644 --- a/docs/pages/pack/docs/index.mdx +++ b/docs/pages/pack/docs/index.mdx @@ -12,8 +12,6 @@ import FullTurboCTA from "../../../components/FullTurboCTA"; Turbopack is an incremental bundler optimized for JavaScript and TypeScript, written in Rust by the creators of webpack and [Next.js](https://nextjs.org/) at [Vercel](https://vercel.com/). -On large applications Turbopack updates 10x faster than Vite and 700x faster than webpack. For the biggest applications the difference grows even more stark with updates up to 20x faster than Vite. - The secret to Turbopack's performance is twofold: highly optimized machine code and a low-level incremental computation engine that enables caching down to the level of individual functions. Once Turbopack performs a task it never does it again. Our team has taken the lessons from 10 years of webpack, combined with the innovations in incremental computation from [Turborepo](/repo) and Google's Bazel, and created an architecture ready to support the coming decades of computing. From c9c9e2f4554788e13c8dcc58d4b1abba8d37a6b0 Mon Sep 17 00:00:00 2001 From: Kevin Simper Date: Mon, 27 Feb 2023 07:24:28 +0100 Subject: [PATCH 03/16] Update getting started to depend on turbo.json for order (#3859) With the improvements to dependOn, it seems to be that this is the new best practice and not having the order defined in the `npx turbo run ...` This would make it easier for new adopters how to structure their turborepo project --- docs/pages/repo/docs/getting-started/existing-monorepo.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/repo/docs/getting-started/existing-monorepo.mdx b/docs/pages/repo/docs/getting-started/existing-monorepo.mdx index 1939aae4053e6..0eff1b2342d97 100644 --- a/docs/pages/repo/docs/getting-started/existing-monorepo.mdx +++ b/docs/pages/repo/docs/getting-started/existing-monorepo.mdx @@ -140,7 +140,7 @@ The rough execution order for a given package is based on the `dependsOn` keys: After execution, the full pipeline can run: ```sh -npx turbo run build test lint deploy +npx turbo run deploy ``` `turbo` will then schedule the execution of each task(s) to optimize usage of the machine's resources. From b75b04d4d0b61bcfdd7a33b53ec593e1499ff853 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Mon, 27 Feb 2023 14:30:00 +0800 Subject: [PATCH 04/16] Root inference: skip turbo.json (#3946) Integration tests for inferring the root. This demonstrates that detection based upon `turbo.json` (and the change made in #3938) is not (particularly) relevant to root identification. How to review: - Each commit is pretty self-contained. You can see me adding a debug line to assert against in the first commit. - The third commit is both a revert of #3938 and a full deletion of the `turbo.json`-included detection logic.
OUTDATED There is _one_ behavior change. If you previously: 1. Had nested workspaces (which is not supported by us or any package manager). 2. Had a `turbo.json` at the "outer" one. 3. Did _not_ have a `turbo.json` at the "inner" one Then we would have selected the outer one. We now select the inner one, and throw an error because the inner one does not have a `turbo.json`. I believe this to be an _improvement_.
*** #3938 treats any `turbo.json` that has comments in it as nonexistent since `serde_json` doesn't support JSONC. That everything still worked with parsing that is throwing an error made it clear that the `turbo.json` check was not being used except for the described edge case. --- .../basic_monorepo/verbosity.t | 2 + .../inference/has-workspaces.t | 113 +++++++++ .../has-workspaces/apps/docs/package.json | 3 + .../has-workspaces/apps/web/package.json | 3 + .../tests/test-package/package.json | 3 + .../inference/has-workspaces/package.json | 9 + .../eslint-config-custom/package.json | 3 + .../packages/ui-library/package.json | 3 + .../packages/ui-library/src/.gitkeep | 0 .../packages/ui-library/turbo.json | 5 + .../inference/has-workspaces/turbo.json | 7 + .../inference/nested-workspaces.t | 228 ++++++++++++++++++ .../inference/nested-workspaces/README.md | 1 + .../outer-no-turbo/apps/docs/package.json | 3 + .../outer-no-turbo/apps/web/package.json | 3 + .../inner-no-turbo/apps/docs/package.json | 3 + .../inner-no-turbo/apps/web/package.json | 3 + .../inner-no-turbo/package.json | 8 + .../eslint-config-custom/package.json | 3 + .../packages/ui-library/package.json | 3 + .../inner/apps/docs/package.json | 3 + .../inner/apps/web/package.json | 3 + .../outer-no-turbo/inner/package.json | 8 + .../eslint-config-custom/package.json | 3 + .../inner/packages/ui-library/package.json | 3 + .../outer-no-turbo/inner/turbo.json | 6 + .../outer-no-turbo/package-lock.json | 1 + .../outer-no-turbo/package.json | 8 + .../eslint-config-custom/package.json | 3 + .../packages/ui-library/package.json | 3 + .../outer/apps/docs/package.json | 3 + .../outer/apps/web/package.json | 3 + .../inner-no-turbo/apps/docs/package.json | 3 + .../inner-no-turbo/apps/web/package.json | 3 + .../outer/inner-no-turbo/package.json | 8 + .../eslint-config-custom/package.json | 3 + .../packages/ui-library/package.json | 3 + .../outer/inner/apps/docs/package.json | 3 + .../outer/inner/apps/web/package.json | 3 + .../outer/inner/package.json | 8 + .../eslint-config-custom/package.json | 3 + .../inner/packages/ui-library/package.json | 3 + .../nested-workspaces/outer/inner/turbo.json | 6 + .../nested-workspaces/outer/package-lock.json | 1 + .../nested-workspaces/outer/package.json | 8 + .../eslint-config-custom/package.json | 3 + .../outer/packages/ui-library/package.json | 3 + .../nested-workspaces/outer/turbo.json | 6 + .../inference/nested_workspaces_setup.sh | 13 + .../inference/no-workspaces.t | 64 +++++ .../inference/no-workspaces/package.json | 4 + .../no-workspaces/parent/child/package.json | 4 + .../no-workspaces/parent/package.json | 4 + .../inference/no_workspaces_setup.sh | 9 + cli/integration_tests/inference/setup.sh | 8 + crates/turborepo-lib/src/lib.rs | 1 - crates/turborepo-lib/src/shim.rs | 72 ++++-- crates/turborepo-lib/src/turbo_json.rs | 33 --- 58 files changed, 676 insertions(+), 56 deletions(-) create mode 100644 cli/integration_tests/inference/has-workspaces.t create mode 100644 cli/integration_tests/inference/has-workspaces/apps/docs/package.json create mode 100644 cli/integration_tests/inference/has-workspaces/apps/web/package.json create mode 100644 cli/integration_tests/inference/has-workspaces/crates/super-crate/tests/test-package/package.json create mode 100644 cli/integration_tests/inference/has-workspaces/package.json create mode 100644 cli/integration_tests/inference/has-workspaces/packages/eslint-config-custom/package.json create mode 100644 cli/integration_tests/inference/has-workspaces/packages/ui-library/package.json create mode 100644 cli/integration_tests/inference/has-workspaces/packages/ui-library/src/.gitkeep create mode 100644 cli/integration_tests/inference/has-workspaces/packages/ui-library/turbo.json create mode 100644 cli/integration_tests/inference/has-workspaces/turbo.json create mode 100644 cli/integration_tests/inference/nested-workspaces.t create mode 100644 cli/integration_tests/inference/nested-workspaces/README.md create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/docs/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/web/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/docs/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/web/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/eslint-config-custom/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/ui-library/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/docs/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/web/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/eslint-config-custom/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/ui-library/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/turbo.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package-lock.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/eslint-config-custom/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/ui-library/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/apps/docs/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/apps/web/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/docs/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/web/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/eslint-config-custom/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/ui-library/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner/apps/docs/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner/apps/web/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner/packages/eslint-config-custom/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner/packages/ui-library/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/inner/turbo.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/package-lock.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/packages/eslint-config-custom/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/packages/ui-library/package.json create mode 100644 cli/integration_tests/inference/nested-workspaces/outer/turbo.json create mode 100644 cli/integration_tests/inference/nested_workspaces_setup.sh create mode 100644 cli/integration_tests/inference/no-workspaces.t create mode 100644 cli/integration_tests/inference/no-workspaces/package.json create mode 100644 cli/integration_tests/inference/no-workspaces/parent/child/package.json create mode 100644 cli/integration_tests/inference/no-workspaces/parent/package.json create mode 100644 cli/integration_tests/inference/no_workspaces_setup.sh create mode 100644 cli/integration_tests/inference/setup.sh delete mode 100644 crates/turborepo-lib/src/turbo_json.rs diff --git a/cli/integration_tests/basic_monorepo/verbosity.t b/cli/integration_tests/basic_monorepo/verbosity.t index a1f202b4747f9..40e6b1e5d1dbb 100644 --- a/cli/integration_tests/basic_monorepo/verbosity.t +++ b/cli/integration_tests/basic_monorepo/verbosity.t @@ -40,6 +40,7 @@ Verbosity level 2 $ ${TURBO} build -vv --filter=util --force [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/verbosity\.t (re) [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) @@ -69,6 +70,7 @@ Verbosity level 2 $ ${TURBO} build --verbosity=2 --filter=util --force [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/verbosity\.t (re) [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) diff --git a/cli/integration_tests/inference/has-workspaces.t b/cli/integration_tests/inference/has-workspaces.t new file mode 100644 index 0000000000000..447a78fc2bb97 --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces.t @@ -0,0 +1,113 @@ +Setup + $ . ${TESTDIR}/../setup.sh + $ . ${TESTDIR}/setup.sh $(pwd) "has-workspaces" + + $ cd $TARGET_DIR && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/has-workspaces\.t (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/apps/web && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/has-workspaces\.t (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "apps/web" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using apps/web as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/crates && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/has-workspaces\.t (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "crates" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using crates as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/crates/super-crate/tests/test-package && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/has-workspaces\.t (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "crates/super-crate/tests/test-package" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using crates/super-crate/tests/test-package as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/packages/ui-library/src && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/has-workspaces\.t (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "packages/ui-library/src" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using packages/ui-library/src as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + \ No newline at end of file diff --git a/cli/integration_tests/inference/has-workspaces/apps/docs/package.json b/cli/integration_tests/inference/has-workspaces/apps/docs/package.json new file mode 100644 index 0000000000000..0ae4dfd4810ce --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/apps/docs/package.json @@ -0,0 +1,3 @@ +{ + "name": "docs" +} diff --git a/cli/integration_tests/inference/has-workspaces/apps/web/package.json b/cli/integration_tests/inference/has-workspaces/apps/web/package.json new file mode 100644 index 0000000000000..81fca2803c019 --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/apps/web/package.json @@ -0,0 +1,3 @@ +{ + "name": "web" +} diff --git a/cli/integration_tests/inference/has-workspaces/crates/super-crate/tests/test-package/package.json b/cli/integration_tests/inference/has-workspaces/crates/super-crate/tests/test-package/package.json new file mode 100644 index 0000000000000..ad8ade827ae15 --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/crates/super-crate/tests/test-package/package.json @@ -0,0 +1,3 @@ +{ + "name": "test-package" +} diff --git a/cli/integration_tests/inference/has-workspaces/package.json b/cli/integration_tests/inference/has-workspaces/package.json new file mode 100644 index 0000000000000..3d10cd9d0844a --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/package.json @@ -0,0 +1,9 @@ +{ + "name": "inference", + "workspaces": [ + "apps/*", + "packages/*", + "crates/super-crate/tests/test-package" + ], + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/has-workspaces/packages/eslint-config-custom/package.json b/cli/integration_tests/inference/has-workspaces/packages/eslint-config-custom/package.json new file mode 100644 index 0000000000000..505c76aa0482e --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/packages/eslint-config-custom/package.json @@ -0,0 +1,3 @@ +{ + "name": "eslint-config-custom" +} diff --git a/cli/integration_tests/inference/has-workspaces/packages/ui-library/package.json b/cli/integration_tests/inference/has-workspaces/packages/ui-library/package.json new file mode 100644 index 0000000000000..4d3650c34aca2 --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/packages/ui-library/package.json @@ -0,0 +1,3 @@ +{ + "name": "ui-library" +} diff --git a/cli/integration_tests/inference/has-workspaces/packages/ui-library/src/.gitkeep b/cli/integration_tests/inference/has-workspaces/packages/ui-library/src/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/cli/integration_tests/inference/has-workspaces/packages/ui-library/turbo.json b/cli/integration_tests/inference/has-workspaces/packages/ui-library/turbo.json new file mode 100644 index 0000000000000..924a1fc613ae9 --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/packages/ui-library/turbo.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "pipeline": {} +} diff --git a/cli/integration_tests/inference/has-workspaces/turbo.json b/cli/integration_tests/inference/has-workspaces/turbo.json new file mode 100644 index 0000000000000..2fc9d06fe4d5a --- /dev/null +++ b/cli/integration_tests/inference/has-workspaces/turbo.json @@ -0,0 +1,7 @@ +// Has a comment! +{ + "$schema": "https://turbo.build/schema.json", + "pipeline": { + "build": {} + } +} diff --git a/cli/integration_tests/inference/nested-workspaces.t b/cli/integration_tests/inference/nested-workspaces.t new file mode 100644 index 0000000000000..a85ca3a265e1e --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces.t @@ -0,0 +1,228 @@ +Setup + $ . ${TESTDIR}/../setup.sh + $ . ${TESTDIR}/nested_workspaces_setup.sh $(pwd) + + $ cd $TARGET_DIR/outer && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer/apps && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "apps" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using apps as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer/inner && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer/inner (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer/inner/apps && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer/inner (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "apps" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using apps as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer/inner-no-turbo && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "inner-no-turbo" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using inner-no-turbo as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer/inner-no-turbo/apps && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "inner-no-turbo/apps" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using inner-no-turbo/apps as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer-no-turbo && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer-no-turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[ERROR] turbo: error: EXTRA_VALUE_AT_END="run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist" (re) + ERROR run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + Turbo error: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + [1] + + $ cd $TARGET_DIR/outer-no-turbo/apps && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer-no-turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "apps" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[ERROR] turbo: error: EXTRA_VALUE_AT_END="run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist" (re) + ERROR run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + Turbo error: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + [1] + + $ cd $TARGET_DIR/outer-no-turbo/inner && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer-no-turbo/inner (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer-no-turbo/inner/apps && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer-no-turbo/inner (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "apps" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Using apps as a basis for selecting packages (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=c1fb8f74a026cdb8 (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Packages in scope: (esc) + \xe2\x80\xa2 Running build in 0 packages (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/outer-no-turbo/inner-no-turbo && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer-no-turbo/inner-no-turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[ERROR] turbo: error: EXTRA_VALUE_AT_END="run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist" (re) + ERROR run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + Turbo error: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + [1] + + $ cd $TARGET_DIR/outer-no-turbo/inner-no-turbo/apps && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/nested-workspaces\.t/outer-no-turbo/inner-no-turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "apps" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[ERROR] turbo: error: EXTRA_VALUE_AT_END="run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist" (re) + ERROR run failed: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + Turbo error: Could not find turbo.json. Follow directions at https://turbo.build/repo/docs to create one: file does not exist + [1] diff --git a/cli/integration_tests/inference/nested-workspaces/README.md b/cli/integration_tests/inference/nested-workspaces/README.md new file mode 100644 index 0000000000000..a6ab30e08efbb --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/README.md @@ -0,0 +1 @@ +This is _not_ a valid configuration. It tests our behavior when given bad input. diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/docs/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/docs/package.json new file mode 100644 index 0000000000000..0ae4dfd4810ce --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/docs/package.json @@ -0,0 +1,3 @@ +{ + "name": "docs" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/web/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/web/package.json new file mode 100644 index 0000000000000..81fca2803c019 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/apps/web/package.json @@ -0,0 +1,3 @@ +{ + "name": "web" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/docs/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/docs/package.json new file mode 100644 index 0000000000000..0ae4dfd4810ce --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/docs/package.json @@ -0,0 +1,3 @@ +{ + "name": "docs" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/web/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/web/package.json new file mode 100644 index 0000000000000..81fca2803c019 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/apps/web/package.json @@ -0,0 +1,3 @@ +{ + "name": "web" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/package.json new file mode 100644 index 0000000000000..2f5423b2f9969 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/package.json @@ -0,0 +1,8 @@ +{ + "name": "inner-no-turbo", + "workspaces": [ + "apps/*", + "packages/*" + ], + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/eslint-config-custom/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/eslint-config-custom/package.json new file mode 100644 index 0000000000000..505c76aa0482e --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/eslint-config-custom/package.json @@ -0,0 +1,3 @@ +{ + "name": "eslint-config-custom" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/ui-library/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/ui-library/package.json new file mode 100644 index 0000000000000..4d3650c34aca2 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner-no-turbo/packages/ui-library/package.json @@ -0,0 +1,3 @@ +{ + "name": "ui-library" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/docs/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/docs/package.json new file mode 100644 index 0000000000000..0ae4dfd4810ce --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/docs/package.json @@ -0,0 +1,3 @@ +{ + "name": "docs" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/web/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/web/package.json new file mode 100644 index 0000000000000..81fca2803c019 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/apps/web/package.json @@ -0,0 +1,3 @@ +{ + "name": "web" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/package.json new file mode 100644 index 0000000000000..8d7eb237802c7 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/package.json @@ -0,0 +1,8 @@ +{ + "name": "inner", + "workspaces": [ + "apps/*", + "packages/*" + ], + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/eslint-config-custom/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/eslint-config-custom/package.json new file mode 100644 index 0000000000000..505c76aa0482e --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/eslint-config-custom/package.json @@ -0,0 +1,3 @@ +{ + "name": "eslint-config-custom" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/ui-library/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/ui-library/package.json new file mode 100644 index 0000000000000..4d3650c34aca2 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/packages/ui-library/package.json @@ -0,0 +1,3 @@ +{ + "name": "ui-library" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/turbo.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/turbo.json new file mode 100644 index 0000000000000..d4487028869da --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/inner/turbo.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://turbo.build/schema.json", + "pipeline": { + "build": {} + } +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package-lock.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package-lock.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package-lock.json @@ -0,0 +1 @@ +{} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package.json new file mode 100644 index 0000000000000..ab1d316fca125 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/package.json @@ -0,0 +1,8 @@ +{ + "name": "outer", + "workspaces": [ + "apps/*", + "packages/*" + ], + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/eslint-config-custom/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/eslint-config-custom/package.json new file mode 100644 index 0000000000000..505c76aa0482e --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/eslint-config-custom/package.json @@ -0,0 +1,3 @@ +{ + "name": "eslint-config-custom" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/ui-library/package.json b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/ui-library/package.json new file mode 100644 index 0000000000000..4d3650c34aca2 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer-no-turbo/packages/ui-library/package.json @@ -0,0 +1,3 @@ +{ + "name": "ui-library" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/apps/docs/package.json b/cli/integration_tests/inference/nested-workspaces/outer/apps/docs/package.json new file mode 100644 index 0000000000000..0ae4dfd4810ce --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/apps/docs/package.json @@ -0,0 +1,3 @@ +{ + "name": "docs" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/apps/web/package.json b/cli/integration_tests/inference/nested-workspaces/outer/apps/web/package.json new file mode 100644 index 0000000000000..81fca2803c019 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/apps/web/package.json @@ -0,0 +1,3 @@ +{ + "name": "web" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/docs/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/docs/package.json new file mode 100644 index 0000000000000..0ae4dfd4810ce --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/docs/package.json @@ -0,0 +1,3 @@ +{ + "name": "docs" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/web/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/web/package.json new file mode 100644 index 0000000000000..81fca2803c019 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/apps/web/package.json @@ -0,0 +1,3 @@ +{ + "name": "web" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/package.json new file mode 100644 index 0000000000000..2f5423b2f9969 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/package.json @@ -0,0 +1,8 @@ +{ + "name": "inner-no-turbo", + "workspaces": [ + "apps/*", + "packages/*" + ], + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/eslint-config-custom/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/eslint-config-custom/package.json new file mode 100644 index 0000000000000..505c76aa0482e --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/eslint-config-custom/package.json @@ -0,0 +1,3 @@ +{ + "name": "eslint-config-custom" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/ui-library/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/ui-library/package.json new file mode 100644 index 0000000000000..4d3650c34aca2 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner-no-turbo/packages/ui-library/package.json @@ -0,0 +1,3 @@ +{ + "name": "ui-library" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner/apps/docs/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner/apps/docs/package.json new file mode 100644 index 0000000000000..0ae4dfd4810ce --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner/apps/docs/package.json @@ -0,0 +1,3 @@ +{ + "name": "docs" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner/apps/web/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner/apps/web/package.json new file mode 100644 index 0000000000000..81fca2803c019 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner/apps/web/package.json @@ -0,0 +1,3 @@ +{ + "name": "web" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner/package.json new file mode 100644 index 0000000000000..8d7eb237802c7 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner/package.json @@ -0,0 +1,8 @@ +{ + "name": "inner", + "workspaces": [ + "apps/*", + "packages/*" + ], + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner/packages/eslint-config-custom/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner/packages/eslint-config-custom/package.json new file mode 100644 index 0000000000000..505c76aa0482e --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner/packages/eslint-config-custom/package.json @@ -0,0 +1,3 @@ +{ + "name": "eslint-config-custom" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner/packages/ui-library/package.json b/cli/integration_tests/inference/nested-workspaces/outer/inner/packages/ui-library/package.json new file mode 100644 index 0000000000000..4d3650c34aca2 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner/packages/ui-library/package.json @@ -0,0 +1,3 @@ +{ + "name": "ui-library" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/inner/turbo.json b/cli/integration_tests/inference/nested-workspaces/outer/inner/turbo.json new file mode 100644 index 0000000000000..d4487028869da --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/inner/turbo.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://turbo.build/schema.json", + "pipeline": { + "build": {} + } +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/package-lock.json b/cli/integration_tests/inference/nested-workspaces/outer/package-lock.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/package-lock.json @@ -0,0 +1 @@ +{} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/package.json b/cli/integration_tests/inference/nested-workspaces/outer/package.json new file mode 100644 index 0000000000000..ab1d316fca125 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/package.json @@ -0,0 +1,8 @@ +{ + "name": "outer", + "workspaces": [ + "apps/*", + "packages/*" + ], + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/packages/eslint-config-custom/package.json b/cli/integration_tests/inference/nested-workspaces/outer/packages/eslint-config-custom/package.json new file mode 100644 index 0000000000000..505c76aa0482e --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/packages/eslint-config-custom/package.json @@ -0,0 +1,3 @@ +{ + "name": "eslint-config-custom" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/packages/ui-library/package.json b/cli/integration_tests/inference/nested-workspaces/outer/packages/ui-library/package.json new file mode 100644 index 0000000000000..4d3650c34aca2 --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/packages/ui-library/package.json @@ -0,0 +1,3 @@ +{ + "name": "ui-library" +} diff --git a/cli/integration_tests/inference/nested-workspaces/outer/turbo.json b/cli/integration_tests/inference/nested-workspaces/outer/turbo.json new file mode 100644 index 0000000000000..d4487028869da --- /dev/null +++ b/cli/integration_tests/inference/nested-workspaces/outer/turbo.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://turbo.build/schema.json", + "pipeline": { + "build": {} + } +} diff --git a/cli/integration_tests/inference/nested_workspaces_setup.sh b/cli/integration_tests/inference/nested_workspaces_setup.sh new file mode 100644 index 0000000000000..0ddae3103b333 --- /dev/null +++ b/cli/integration_tests/inference/nested_workspaces_setup.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +SCRIPT_DIR=$(dirname ${BASH_SOURCE[0]}) +TARGET_DIR=$1 + +cp -a ${SCRIPT_DIR}/nested-workspaces/. ${TARGET_DIR}/ +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/outer +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/outer/inner +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/outer/inner-no-turbo + +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/outer-no-turbo +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/outer-no-turbo/inner +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/outer-no-turbo/inner-no-turbo diff --git a/cli/integration_tests/inference/no-workspaces.t b/cli/integration_tests/inference/no-workspaces.t new file mode 100644 index 0000000000000..b57cc7df2f97e --- /dev/null +++ b/cli/integration_tests/inference/no-workspaces.t @@ -0,0 +1,64 @@ +Setup + $ . ${TESTDIR}/../setup.sh + $ . ${TESTDIR}/no_workspaces_setup.sh $(pwd) "no-workspaces" + + $ cd $TARGET_DIR && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/no-workspaces\.t (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=4c73ae6c71119fad (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Running build (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/parent && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/no-workspaces\.t/parent (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=96793eaf8b145bde (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Running build (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + + $ cd $TARGET_DIR/parent/child && ${TURBO} run build --filter=nothing -vv + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Global turbo version: .* (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: No local turbo binary found at: .+node_modules/\.bin/turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Repository Root: .*/no-workspaces\.t/parent/child (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::shim: Running command as global turbo (re) + [-0-9:.TWZ+]+ \[DEBUG] turborepo_lib::cli: pkg_inference_root set to "" (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: Found go binary at "[\-\w\/]+" (re) + [-0-9:.TWZ+]+ \[INFO] turbo: skipping turbod since we appear to be in a non-interactive context (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash env vars: vars=\["VERCEL_ANALYTICS_ID"] (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: global hash: value=67527326c7931f8b (re) + [-0-9:.TWZ+]+ \[DEBUG] turbo: local cache folder: path="" (re) + \xe2\x80\xa2 Running build (esc) + \xe2\x80\xa2 Remote caching disabled (esc) + + No tasks were executed as part of this run. + + Tasks: 0 successful, 0 total + Cached: 0 cached, 0 total + Time:\s*[\.0-9]+m?s (re) + \ No newline at end of file diff --git a/cli/integration_tests/inference/no-workspaces/package.json b/cli/integration_tests/inference/no-workspaces/package.json new file mode 100644 index 0000000000000..550b58b06871d --- /dev/null +++ b/cli/integration_tests/inference/no-workspaces/package.json @@ -0,0 +1,4 @@ +{ + "name": "no-workspaces", + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/no-workspaces/parent/child/package.json b/cli/integration_tests/inference/no-workspaces/parent/child/package.json new file mode 100644 index 0000000000000..ad16470c8510f --- /dev/null +++ b/cli/integration_tests/inference/no-workspaces/parent/child/package.json @@ -0,0 +1,4 @@ +{ + "name": "child", + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/no-workspaces/parent/package.json b/cli/integration_tests/inference/no-workspaces/parent/package.json new file mode 100644 index 0000000000000..6be6cae031236 --- /dev/null +++ b/cli/integration_tests/inference/no-workspaces/parent/package.json @@ -0,0 +1,4 @@ +{ + "name": "parent", + "packageManager": "npm@8.0.0" +} diff --git a/cli/integration_tests/inference/no_workspaces_setup.sh b/cli/integration_tests/inference/no_workspaces_setup.sh new file mode 100644 index 0000000000000..049d83bb3c229 --- /dev/null +++ b/cli/integration_tests/inference/no_workspaces_setup.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +SCRIPT_DIR=$(dirname ${BASH_SOURCE[0]}) +TARGET_DIR=$1 + +cp -a ${SCRIPT_DIR}/no-workspaces/. ${TARGET_DIR}/ +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR} +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/parent +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR}/parent/child diff --git a/cli/integration_tests/inference/setup.sh b/cli/integration_tests/inference/setup.sh new file mode 100644 index 0000000000000..da909b2889ff3 --- /dev/null +++ b/cli/integration_tests/inference/setup.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +SCRIPT_DIR=$(dirname ${BASH_SOURCE[0]}) +TARGET_DIR=$1 +MONOREPO_DIR=$2 + +cp -a ${SCRIPT_DIR}/$MONOREPO_DIR/. ${TARGET_DIR}/ +${SCRIPT_DIR}/../setup_git.sh ${TARGET_DIR} diff --git a/crates/turborepo-lib/src/lib.rs b/crates/turborepo-lib/src/lib.rs index dfe3068a3beca..ca9d8ba0b4250 100644 --- a/crates/turborepo-lib/src/lib.rs +++ b/crates/turborepo-lib/src/lib.rs @@ -5,7 +5,6 @@ mod config; mod package_manager; mod retry; mod shim; -mod turbo_json; mod ui; use anyhow::Result; diff --git a/crates/turborepo-lib/src/shim.rs b/crates/turborepo-lib/src/shim.rs index ebb0695b5670d..c1bd5547fa403 100644 --- a/crates/turborepo-lib/src/shim.rs +++ b/crates/turborepo-lib/src/shim.rs @@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize}; use tiny_gradient::{GradientStr, RGB}; use turbo_updater::check_for_updates; -use crate::{cli, get_version, turbo_json::TurboJson, PackageManager, Payload}; +use crate::{cli, get_version, PackageManager, Payload}; static TURBO_JSON: &str = "turbo.json"; // all arguments that result in a stdout that much be directly parsable and @@ -235,41 +235,65 @@ impl RepoState { /// /// returns: Result pub fn infer(current_dir: &Path) -> Result { - // First we look for a `turbo.json`. This iterator returns the first ancestor - // that contains a `turbo.json` file. - let root_path = current_dir - .ancestors() - .find(|p| TurboJson::open(p.join(TURBO_JSON)).map_or(false, |t| t.no_extends())); + // What we look for first are all directories that contain both a `package.json` + // and a `turbo.json`. + let potential_turbo_roots = current_dir.ancestors().filter(|path| { + fs::metadata(path.join("package.json")).is_ok() + && fs::metadata(path.join("turbo.json")).is_ok() + }); + + let mut first_package_json_dir = None; + + // We loop through these directories and see if there are workspaces defined in + // them, either in the `package.json` or `pnm-workspaces.yml` + for dir in potential_turbo_roots { + if first_package_json_dir.is_none() { + first_package_json_dir = Some(dir) + } - // If that directory exists, then we figure out if there are workspaces defined - // in it NOTE: This may change with multiple `turbo.json` files - if let Some(root_path) = root_path { let pnpm = PackageManager::Pnpm; let npm = PackageManager::Npm; - let is_workspace = pnpm.get_workspace_globs(root_path).is_ok() - || npm.get_workspace_globs(root_path).is_ok(); + let is_workspace = + pnpm.get_workspace_globs(dir).is_ok() || npm.get_workspace_globs(dir).is_ok(); - let mode = if is_workspace { - RepoMode::MultiPackage - } else { - RepoMode::SinglePackage - }; + if is_workspace { + let local_turbo_state = LocalTurboState::infer(dir); - let local_turbo_state = LocalTurboState::infer(root_path); + return Ok(Self { + root: dir.to_path_buf(), + mode: RepoMode::MultiPackage, + local_turbo_state, + }); + } + } + // No dice? Time to see if there is a `turbo.json` for this set. + if first_package_json_dir.is_some() { + let root = first_package_json_dir + .ok_or_else(|| { + anyhow!( + "Unable to find `{}` or `package.json` in current path", + TURBO_JSON + ) + })? + .to_path_buf(); + + let local_turbo_state = LocalTurboState::infer(&root); return Ok(Self { - root: root_path.to_path_buf(), - mode, + root, + mode: RepoMode::SinglePackage, local_turbo_state, }); } - // What we look for next is a directory that contains a `package.json`. + // Well, you didn't create a turbo.json, so we're going to do the best we can + // from just package.json + + // Now we try to find the closest workspace. let potential_roots = current_dir .ancestors() .filter(|path| fs::metadata(path.join("package.json")).is_ok()); - let mut first_package_json_dir = None; // We loop through these directories and see if there are workspaces defined in // them, either in the `package.json` or `pnm-workspaces.yml` for dir in potential_roots { @@ -524,11 +548,15 @@ pub fn run() -> Result { // and `--cwd` flags. if is_turbo_binary_path_set() { let repo_state = RepoState::infer(&args.cwd)?; + debug!("Repository Root: {}", repo_state.root.to_string_lossy()); return cli::run(Some(repo_state)); } match RepoState::infer(&args.cwd) { - Ok(repo_state) => repo_state.run_correct_turbo(args), + Ok(repo_state) => { + debug!("Repository Root: {}", repo_state.root.to_string_lossy()); + repo_state.run_correct_turbo(args) + } Err(err) => { // If we cannot infer, we still run global turbo. This allows for global // commands like login/logout/link/unlink to still work diff --git a/crates/turborepo-lib/src/turbo_json.rs b/crates/turborepo-lib/src/turbo_json.rs deleted file mode 100644 index f803a11ae19fb..0000000000000 --- a/crates/turborepo-lib/src/turbo_json.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::{fs::File, path::Path}; - -use anyhow::Result; -use serde::Deserialize; - -#[derive(Debug, Deserialize)] -pub struct TurboJson { - extends: Option>, -} - -impl TurboJson { - pub fn open(path: impl AsRef) -> Result { - Ok(serde_json::from_reader(File::open(path)?)?) - } - pub fn no_extends(&self) -> bool { - self.extends.is_none() - } -} - -#[test] -fn test_turbo_json() { - let turbo_json: TurboJson = serde_json::from_str("{}").unwrap(); - assert_eq!(turbo_json.extends, None); - - let turbo_json: TurboJson = serde_json::from_str(r#"{ "extends": ["//"] }"#).unwrap(); - assert_eq!(turbo_json.extends, Some(vec!["//".to_string()])); - - let turbo_json: TurboJson = serde_json::from_str(r#"{ "extends": ["//", "~"] }"#).unwrap(); - assert_eq!( - turbo_json.extends, - Some(vec!["//".to_string(), "~".to_string()]) - ); -} From 50873a40bf2628e05e1224cbe3925e82a4eb7e75 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Mon, 27 Feb 2023 22:33:48 +0800 Subject: [PATCH 05/16] Add per-package-manager instructions to create-new (#3971) --- .../repo/docs/getting-started/create-new.mdx | 112 ++++++++++++++---- 1 file changed, 92 insertions(+), 20 deletions(-) diff --git a/docs/pages/repo/docs/getting-started/create-new.mdx b/docs/pages/repo/docs/getting-started/create-new.mdx index 5972d3f862fb3..e764165f2482b 100644 --- a/docs/pages/repo/docs/getting-started/create-new.mdx +++ b/docs/pages/repo/docs/getting-started/create-new.mdx @@ -18,9 +18,23 @@ import { Tabs, Tab } from "../../../../components/Tabs"; To create a new monorepo, use our [`create-turbo`](https://www.npmjs.com/package/create-turbo) npm package: -```sh -npx create-turbo@latest -``` + + + ```sh + npx create-turbo@latest + ``` + + + ```sh + yarn dlx create-turbo@latest + ``` + + + ```sh + pnpm dlx create-turbo@latest + ``` + + You can also clone a Turborepo starter repository to get a head start on your monorepo. To see Turborepo examples and starters, see the [Turborepo examples directory on GitHub](https://github.com/vercel/turbo/tree/main/examples). @@ -38,9 +52,23 @@ During this tutorial, some lines of code are omitted from the code samples. For First, run: -```sh -npx create-turbo@latest -``` + + + ```sh + npx create-turbo@latest + ``` + + + ```sh + yarn dlx create-turbo@latest + ``` + + + ```sh + pnpm dlx create-turbo@latest + ``` + + This installs the [`create-turbo`](https://www.npmjs.com/package/create-turbo) CLI, and runs it. You'll be asked several questions: @@ -88,13 +116,35 @@ Next, open `./apps/web/package.json`. You'll notice that this package's name is You'll see that `"web"` depends on a package called `"ui"`. If you're using `pnpm`, you'll see it's declared like this: -```json filename="apps/web/package.json" -{ - "dependencies": { - "ui": "workspace:*" - } -} -``` + + + ```json filename="apps/web/package.json" + { + "dependencies": { + "ui": "*" + } + } + ``` + + + ```json filename="apps/web/package.json" + { + "dependencies": { + "ui": "*" + } + } + ``` + + + ```json filename="apps/web/package.json" + { + "dependencies": { + "ui": "workspace:*" + } + } + ``` + + This means that our **web app depends on our local `ui` package**. @@ -177,13 +227,35 @@ Here, we specify three files to be exported, inside `files`. Packages which depe For instance, `packages/ui` depends on `tsconfig`: -```json filename="packages/ui/package.json" -{ - "devDependencies": { - "tsconfig": "workspace:*" - } -} -``` + + + ```json filename="apps/web/package.json" + { + "devDependencies": { + "tsconfig": "*" + } + } + ``` + + + ```json filename="apps/web/package.json" + { + "devDependencies": { + "tsconfig": "*" + } + } + ``` + + + ```json filename="apps/web/package.json" + { + "devDependencies": { + "tsconfig": "workspace:*" + } + } + ``` + + And inside its `tsconfig.json` file, it imports it using `extends`: From ff0d5ec58604a4eb8434c0432f73afbcfc2159b6 Mon Sep 17 00:00:00 2001 From: Alex Moore Date: Mon, 27 Feb 2023 06:42:51 -0800 Subject: [PATCH 06/16] Remove non-functional css property (#3968) --- docs/components/pages/landing/index.module.css | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/components/pages/landing/index.module.css b/docs/components/pages/landing/index.module.css index 19cbfffcae62a..ac18d80ca582f 100644 --- a/docs/components/pages/landing/index.module.css +++ b/docs/components/pages/landing/index.module.css @@ -106,7 +106,6 @@ backface-visibility: hidden; perspective: 1000; transform: translate3d(0, 0, 0); - transfom: translateZ(0); } .counter-border:hover { From 6535d6361542ed7f387cfadf4eb88796f3e9c07e Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Mon, 27 Feb 2023 06:48:31 -0800 Subject: [PATCH 07/16] fix: support prune without turbo.json (#3785) --- cli/internal/prune/prune.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli/internal/prune/prune.go b/cli/internal/prune/prune.go index d3085393769b0..d8b67f0534a3f 100644 --- a/cli/internal/prune/prune.go +++ b/cli/internal/prune/prune.go @@ -3,6 +3,7 @@ package prune import ( "bufio" "fmt" + "os" "strings" "github.com/vercel/turbo/cli/internal/cmdutil" @@ -209,7 +210,7 @@ func (p *prune) prune(opts *turbostate.PrunePayload) error { } turboJSON, err := fs.LoadTurboConfig(p.base.RepoRoot, rootPackageJSON, false) - if err != nil { + if err != nil && !errors.Is(err, os.ErrNotExist) { return errors.Wrap(err, "failed to read turbo.json") } if turboJSON != nil { From 953adf4f00f39001442c0e331f3c16c2ecf65eaa Mon Sep 17 00:00:00 2001 From: Thomas Knickman Date: Mon, 27 Feb 2023 09:50:01 -0500 Subject: [PATCH 08/16] fix(eslint): better messaging and bug fix (#3950 A few fixes for the eslint plugin. 1. Fix error message to remove the leading `$` since that was deprecated in 1.5 2. Provides more explicit error messaging 3. Fixes a bug that could cause the rule to exit early if no global deps were provided 4. Cleans up / standardizes tests and mocks This should also fix https://github.com/vercel/turbo/issues/3943 --- .eslintignore | 2 +- .../__fixtures__/configs/single/turbo.json | 25 +++ .../workspace-configs/apps/docs/index.js | 4 +- .../workspace-configs/apps/docs/package.json | 0 .../workspace-configs/apps/docs/turbo.json | 9 + .../workspace-configs/apps/web/index.js | 4 +- .../workspace-configs/apps/web/package.json | 0 .../workspace-configs/apps/web/turbo.json | 0 .../workspace-configs/package.json | 0 .../workspace-configs/packages/ui/index.js | 4 +- .../packages/ui/package.json | 0 .../workspace-configs/packages/ui/turbo.json | 0 .../workspace-configs/turbo.json | 0 .../workspace/.eslintrc.js | 0 .../__fixtures__/workspace/child/child.js | 2 + .../workspace/package-lock.json | 12 +- .../__fixtures__/workspace/package.json | 5 + .../__fixtures__/workspace/peer.js | 1 + .../workspace/turbo.json | 0 .../eslint-plugin-turbo/__tests__/cwd.test.ts | 69 +++---- .../fixtures/configs/single/turbo.json | 39 ---- .../fixtures/workspace/child/child.js | 2 - .../__tests__/fixtures/workspace/package.json | 5 - .../__tests__/fixtures/workspace/peer.js | 1 - .../lib/no-undeclared-env-vars.test.ts | 173 +++++++++++------- packages/eslint-plugin-turbo/jest.config.js | 3 +- .../lib/rules/no-undeclared-env-vars.ts | 43 +++-- packages/eslint-plugin-turbo/lib/types.ts | 10 - packages/eslint-plugin-turbo/package.json | 3 +- packages/eslint-plugin-turbo/tsup.config.ts | 1 + packages/turbo-test-utils/package.json | 1 + packages/turbo-test-utils/src/useFixtures.ts | 30 ++- packages/turbo-utils/package.json | 4 +- pnpm-lock.yaml | 11 +- 34 files changed, 252 insertions(+), 211 deletions(-) create mode 100644 packages/eslint-plugin-turbo/__fixtures__/configs/single/turbo.json rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/apps/docs/index.js (62%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/apps/docs/package.json (100%) create mode 100644 packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/turbo.json rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/apps/web/index.js (66%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/apps/web/package.json (100%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/apps/web/turbo.json (100%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/package.json (100%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/packages/ui/index.js (67%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/packages/ui/package.json (100%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/packages/ui/turbo.json (100%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace-configs/turbo.json (100%) rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace/.eslintrc.js (100%) create mode 100644 packages/eslint-plugin-turbo/__fixtures__/workspace/child/child.js rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace/package-lock.json (84%) create mode 100644 packages/eslint-plugin-turbo/__fixtures__/workspace/package.json create mode 100644 packages/eslint-plugin-turbo/__fixtures__/workspace/peer.js rename packages/eslint-plugin-turbo/{__tests__/fixtures => __fixtures__}/workspace/turbo.json (100%) delete mode 100644 packages/eslint-plugin-turbo/__tests__/fixtures/configs/single/turbo.json delete mode 100644 packages/eslint-plugin-turbo/__tests__/fixtures/workspace/child/child.js delete mode 100644 packages/eslint-plugin-turbo/__tests__/fixtures/workspace/package.json delete mode 100644 packages/eslint-plugin-turbo/__tests__/fixtures/workspace/peer.js delete mode 100644 packages/eslint-plugin-turbo/lib/types.ts diff --git a/.eslintignore b/.eslintignore index fc4703d1c2ad2..ee719fd421d5a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,7 +6,7 @@ dist/ /examples/ -packages/eslint-plugin-turbo/__tests__/fixtures +packages/eslint-plugin-turbo/__fixtures__ packages/create-turbo/templates packages/turbo-tracing-next-plugin/test/with-mongodb-mongoose crates/*/tests/** diff --git a/packages/eslint-plugin-turbo/__fixtures__/configs/single/turbo.json b/packages/eslint-plugin-turbo/__fixtures__/configs/single/turbo.json new file mode 100644 index 0000000000000..22b79b5524908 --- /dev/null +++ b/packages/eslint-plugin-turbo/__fixtures__/configs/single/turbo.json @@ -0,0 +1,25 @@ +{ + // new style, global env dependency + "globalEnv": ["NEW_STYLE_GLOBAL_ENV_KEY", "$NEW_STYLE_GLOBAL_ENV_KEY"], + // old style, global env dependency (deprecated) + "globalDependencies": ["$GLOBAL_ENV_KEY"], + "pipeline": { + "test": { + "outputs": ["coverage/**"], + "dependsOn": ["^build"] + }, + "lint": { + "outputs": [] + }, + "dev": { + "cache": false + }, + "build": { + "outputs": ["dist/**", ".next/**", "!.next/.cache/**"], + // task level env var deps + "env": ["NEW_STYLE_ENV_KEY"], + // old task level env var deps (deprecated) + "dependsOn": ["^build", "$TASK_ENV_KEY", "$ANOTHER_ENV_KEY"] + } + } +} diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/docs/index.js b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/index.js similarity index 62% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/docs/index.js rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/index.js index 76290455e51c1..4de53f5ec2caa 100644 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/docs/index.js +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/index.js @@ -1,6 +1,6 @@ export default function docs() { if (process.env.ENV_1 === undefined) { - return 'does not exist'; + return "does not exist"; } - return 'exists' + return "exists"; } diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/docs/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/package.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/docs/package.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/package.json diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/turbo.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/turbo.json new file mode 100644 index 0000000000000..a3713efab8eec --- /dev/null +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/docs/turbo.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "pipeline": { + "build": { + "env": ["ENV_3"] + } + } +} diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/web/index.js b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/index.js similarity index 66% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/web/index.js rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/index.js index a1541dbb707f7..bfd3ab817a0de 100644 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/web/index.js +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/index.js @@ -1,6 +1,6 @@ export default function web() { if (!process.env.ENV_2) { - return 'bar'; + return "bar"; } - return 'foo' + return "foo"; } diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/web/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/package.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/web/package.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/package.json diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/web/turbo.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/turbo.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/apps/web/turbo.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/apps/web/turbo.json diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/package.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/package.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/package.json diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/packages/ui/index.js b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/index.js similarity index 67% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/packages/ui/index.js rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/index.js index f3e1489d2876c..dee5e80cd6992 100644 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/packages/ui/index.js +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/index.js @@ -1,6 +1,6 @@ export default function foo() { if (!process.env.IS_SERVER) { - return 'bar'; + return "bar"; } - return 'foo' + return "foo"; } diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/packages/ui/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/package.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/packages/ui/package.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/package.json diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/packages/ui/turbo.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/turbo.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/packages/ui/turbo.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/packages/ui/turbo.json diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/turbo.json b/packages/eslint-plugin-turbo/__fixtures__/workspace-configs/turbo.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace-configs/turbo.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace-configs/turbo.json diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/.eslintrc.js b/packages/eslint-plugin-turbo/__fixtures__/workspace/.eslintrc.js similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace/.eslintrc.js rename to packages/eslint-plugin-turbo/__fixtures__/workspace/.eslintrc.js diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace/child/child.js b/packages/eslint-plugin-turbo/__fixtures__/workspace/child/child.js new file mode 100644 index 0000000000000..9e799a23c8a10 --- /dev/null +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace/child/child.js @@ -0,0 +1,2 @@ +process.env.NONEXISTENT; +process.env.CI; diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/package-lock.json b/packages/eslint-plugin-turbo/__fixtures__/workspace/package-lock.json similarity index 84% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace/package-lock.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace/package-lock.json index 3f1109cc7d19c..13278366e77d7 100644 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/package-lock.json +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace/package-lock.json @@ -5,11 +5,11 @@ "packages": { "": { "dependencies": { - "eslint-plugin-turbo": "../../.." + "eslint-plugin-turbo": "../../" } }, - "../../..": { - "version": "0.0.7", + "../..": { + "version": "0.0.8", "license": "MPL-2.0", "devDependencies": { "@types/eslint": "^8.4.5", @@ -21,6 +21,7 @@ "ts-jest": "^27.1.1", "tsconfig": "workspace:*", "tsup": "^6.2.0", + "turbo-test-utils": "workspace:*", "turbo-types": "workspace:*", "turbo-utils": "workspace:*", "typescript": "^4.7.4" @@ -30,13 +31,13 @@ } }, "node_modules/eslint-plugin-turbo": { - "resolved": "../../..", + "resolved": "../..", "link": true } }, "dependencies": { "eslint-plugin-turbo": { - "version": "file:../../..", + "version": "file:../..", "requires": { "@types/eslint": "^8.4.5", "@types/estree": "^1.0.0", @@ -47,6 +48,7 @@ "ts-jest": "^27.1.1", "tsconfig": "workspace:*", "tsup": "^6.2.0", + "turbo-test-utils": "workspace:*", "turbo-types": "workspace:*", "turbo-utils": "workspace:*", "typescript": "^4.7.4" diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace/package.json b/packages/eslint-plugin-turbo/__fixtures__/workspace/package.json new file mode 100644 index 0000000000000..a1b2929589dad --- /dev/null +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "eslint-plugin-turbo": "../../" + } +} diff --git a/packages/eslint-plugin-turbo/__fixtures__/workspace/peer.js b/packages/eslint-plugin-turbo/__fixtures__/workspace/peer.js new file mode 100644 index 0000000000000..16c8bb0522bbf --- /dev/null +++ b/packages/eslint-plugin-turbo/__fixtures__/workspace/peer.js @@ -0,0 +1 @@ +process.env.CI; diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/turbo.json b/packages/eslint-plugin-turbo/__fixtures__/workspace/turbo.json similarity index 100% rename from packages/eslint-plugin-turbo/__tests__/fixtures/workspace/turbo.json rename to packages/eslint-plugin-turbo/__fixtures__/workspace/turbo.json diff --git a/packages/eslint-plugin-turbo/__tests__/cwd.test.ts b/packages/eslint-plugin-turbo/__tests__/cwd.test.ts index 4fa4af233b1f3..235f063d86149 100644 --- a/packages/eslint-plugin-turbo/__tests__/cwd.test.ts +++ b/packages/eslint-plugin-turbo/__tests__/cwd.test.ts @@ -1,26 +1,18 @@ -import fs from "fs"; import path from "path"; import JSON5 from "json5"; import { execSync } from "child_process"; +import { Schema } from "turbo-types"; +import { setupTestFixtures } from "turbo-test-utils"; describe("eslint settings check", () => { - beforeAll(() => { - const cwd = path.join(__dirname, "fixtures", "workspace"); - execSync(`npm install`, { cwd }); - }); - - afterAll(() => { - const nodeModulesDir = path.join( - __dirname, - "fixtures", - "workspace", - "node_modules" - ); - fs.rmSync(nodeModulesDir, { force: true, recursive: true }); + const { useFixture } = setupTestFixtures({ + directory: path.join(__dirname, "../"), }); it("does the right thing for peers", () => { - const cwd = path.join(__dirname, "fixtures", "workspace"); + const { root: cwd } = useFixture({ fixture: "workspace" }); + execSync(`npm install`, { cwd }); + const configString = execSync(`eslint --print-config peer.js`, { cwd, encoding: "utf8", @@ -33,7 +25,10 @@ describe("eslint settings check", () => { }); it("does the right thing for child dirs", () => { - const cwd = path.join(__dirname, "fixtures", "workspace", "child"); + const { root } = useFixture({ fixture: "workspace" }); + execSync(`npm install`, { cwd: root }); + + const cwd = path.join(root, "child"); const configString = execSync(`eslint --print-config child.js`, { cwd, encoding: "utf8", @@ -47,38 +42,18 @@ describe("eslint settings check", () => { }); describe("eslint cache is busted", () => { - let turboJsonPath: string; - let originalString: string; - - beforeAll(() => { - const cwd = path.join(__dirname, "fixtures", "workspace"); - execSync(`npm install`, { cwd }); - - turboJsonPath = path.join(__dirname, "fixtures", "workspace", "turbo.json"); - originalString = fs.readFileSync(turboJsonPath, { encoding: "utf8" }); - }); - - afterEach(() => { - fs.writeFileSync(turboJsonPath, originalString); - }); - - afterAll(() => { - fs.writeFileSync(turboJsonPath, originalString); - - const nodeModulesDir = path.join( - __dirname, - "fixtures", - "workspace", - "node_modules" - ); - fs.rmSync(nodeModulesDir, { force: true, recursive: true }); + const { useFixture } = setupTestFixtures({ + directory: path.join(__dirname, "../"), }); it("catches a lint error after changing config", () => { expect.assertions(2); // ensure that we populate the cache with a failure. - const cwd = path.join(__dirname, "fixtures", "workspace", "child"); + const { root, readJson, write } = useFixture({ fixture: "workspace" }); + execSync(`npm install`, { cwd: root }); + + const cwd = path.join(root, "child"); try { execSync(`eslint --format=json child.js`, { cwd, encoding: "utf8" }); } catch (error: any) { @@ -88,7 +63,7 @@ describe("eslint cache is busted", () => { messages: [ { message: - "$NONEXISTENT is not listed as a dependency in any turbo.json", + "NONEXISTENT is not listed as a dependency in turbo.json", }, ], }, @@ -96,9 +71,11 @@ describe("eslint cache is busted", () => { } // change the configuration - const turboJson = JSON5.parse(originalString); - turboJson.globalEnv = ["CI", "NONEXISTENT"]; - fs.writeFileSync(turboJsonPath, JSON.stringify(turboJson, null, 2)); + const turboJson = readJson("turbo.json"); + if (turboJson && "globalEnv" in turboJson) { + turboJson.globalEnv = ["CI", "NONEXISTENT"]; + write("turbo.json", JSON5.stringify(turboJson, null, 2)); + } // test that we invalidated the eslint cache const output = execSync(`eslint --format=json child.js`, { diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/configs/single/turbo.json b/packages/eslint-plugin-turbo/__tests__/fixtures/configs/single/turbo.json deleted file mode 100644 index 2f2b46e3115bb..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/configs/single/turbo.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "globalEnv":[ - "NEW_STYLE_GLOBAL_ENV_KEY", - "$NEW_STYLE_GLOBAL_ENV_KEY" - ], - "globalDependencies":[ - "$GLOBAL_ENV_KEY" - ], - "pipeline":{ - "test":{ - "outputs":[ - "coverage/**" - ], - "dependsOn":[ - "^build" - ] - }, - "lint":{ - "outputs":[] - }, - "dev":{ - "cache":false - }, - "build":{ - "outputs":[ - "dist/**/*", - ".next/**/*" - ], - "env":[ - "NEW_STYLE_ENV_KEY" - ], - "dependsOn":[ - "^build", - "$TASK_ENV_KEY", - "$ANOTHER_ENV_KEY" - ] - } - } -} diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/child/child.js b/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/child/child.js deleted file mode 100644 index b410733f10373..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/child/child.js +++ /dev/null @@ -1,2 +0,0 @@ -process.env.NONEXISTENT -process.env.CI diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/package.json b/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/package.json deleted file mode 100644 index fd030e5bc6c36..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "eslint-plugin-turbo": "../../.." - } -} diff --git a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/peer.js b/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/peer.js deleted file mode 100644 index 26f81550a14ce..0000000000000 --- a/packages/eslint-plugin-turbo/__tests__/fixtures/workspace/peer.js +++ /dev/null @@ -1 +0,0 @@ -process.env.CI diff --git a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars.test.ts b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars.test.ts index 3faa9f1c63c45..5c753dd5356e4 100644 --- a/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars.test.ts +++ b/packages/eslint-plugin-turbo/__tests__/lib/no-undeclared-env-vars.test.ts @@ -13,20 +13,24 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { code: ` const { ENV_2 } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/workspace-configs") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/workspace-configs") }, + ], filename: path.join( __dirname, - "../fixtures/workspace-configs/apps/web/index.js" + "../../__fixtures__/workspace-configs/apps/web/index.js" ), }, { code: ` const { ENV_1 } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/workspace-configs") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/workspace-configs") }, + ], filename: path.join( __dirname, - "../fixtures/workspace-configs/apps/web/index.js" + "../../__fixtures__/workspace-configs/apps/web/index.js" ), }, { @@ -39,62 +43,80 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { code: ` const { CI } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/workspace-configs") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/workspace-configs") }, + ], filename: path.join( __dirname, - "../fixtures/workspace-configs/apps/web/index.js" + "../../__fixtures__/workspace-configs/apps/web/index.js" ), }, { code: ` const { TASK_ENV_KEY, ANOTHER_ENV_KEY } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: ` const { NEW_STYLE_ENV_KEY, TASK_ENV_KEY } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: ` const { NEW_STYLE_GLOBAL_ENV_KEY, TASK_ENV_KEY } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: ` - const val = process.env["$NEW_STYLE_GLOBAL_ENV_KEY"]; + const val = process.env["NEW_STYLE_GLOBAL_ENV_KEY"]; `, - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: ` const { TASK_ENV_KEY, ANOTHER_ENV_KEY } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: ` const x = process.env.GLOBAL_ENV_KEY; const { TASK_ENV_KEY, GLOBAL_ENV_KEY: renamedX } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: "var x = process.env.GLOBAL_ENV_KEY;", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: "let x = process.env.TASK_ENV_KEY;", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: "const x = process.env.ANOTHER_KEY_VALUE;", options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ANOTHER_KEY_[A-Z]+$"], }, ], @@ -106,7 +128,7 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ENV_VAR_[A-Z]+$"], }, ], @@ -118,7 +140,7 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ENV_VAR_O[A-Z]+$", "ENV_VAR_TWO"], }, ], @@ -130,7 +152,7 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ENV_VAR_[A-Z]+$"], }, ], @@ -143,7 +165,7 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ENV_VAR_[A-Z]+$"], }, ], @@ -156,7 +178,7 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ENV_VAR_[A-Z]+$"], }, ], @@ -169,7 +191,7 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ENV_VAR_[A-Z]+$"], }, ], @@ -182,22 +204,28 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ENV_VAR_[A-Z]+$"], }, ], }, { code: "const getEnv = (key) => process.env[key];", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: "function getEnv(key) { return process.env[key]; }", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, { code: "for (let x of ['ONE', 'TWO', 'THREE']) { console.log(process.env[x]); }", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], }, ], @@ -206,46 +234,57 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { code: ` const { ENV_2 } = process.env; `, - options: [{ cwd: path.join(__dirname, "../fixtures/workspace-configs") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/workspace-configs") }, + ], filename: path.join( __dirname, - "../fixtures/workspace-configs/apps/docs/index.js" + "../../__fixtures__/workspace-configs/apps/docs/index.js" ), errors: [ - { message: "$ENV_2 is not listed as a dependency in any turbo.json" }, + { + message: + "ENV_2 is not listed as a dependency in the root turbo.json or workspace (apps/docs) turbo.json", + }, ], }, { code: "let { X } = process.env;", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], - errors: [ - { message: "$X is not listed as a dependency in any turbo.json" }, + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, ], + errors: [{ message: "X is not listed as a dependency in turbo.json" }], }, { code: "const { X, Y, Z } = process.env;", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], errors: [ - { message: "$X is not listed as a dependency in any turbo.json" }, - { message: "$Y is not listed as a dependency in any turbo.json" }, - { message: "$Z is not listed as a dependency in any turbo.json" }, + { message: "X is not listed as a dependency in turbo.json" }, + { message: "Y is not listed as a dependency in turbo.json" }, + { message: "Z is not listed as a dependency in turbo.json" }, ], }, { code: "const { X, Y: NewName, Z } = process.env;", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], errors: [ - { message: "$X is not listed as a dependency in any turbo.json" }, - { message: "$Y is not listed as a dependency in any turbo.json" }, - { message: "$Z is not listed as a dependency in any turbo.json" }, + { message: "X is not listed as a dependency in turbo.json" }, + { message: "Y is not listed as a dependency in turbo.json" }, + { message: "Z is not listed as a dependency in turbo.json" }, ], }, { code: "var x = process.env.NOT_THERE;", - options: [{ cwd: path.join(__dirname, "../fixtures/configs/single") }], + options: [ + { cwd: path.join(__dirname, "../../__fixtures__/configs/single") }, + ], errors: [ { - message: "$NOT_THERE is not listed as a dependency in any turbo.json", + message: "NOT_THERE is not listed as a dependency in turbo.json", }, ], }, @@ -253,13 +292,11 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { code: "var x = process.env.KEY;", options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), allowList: ["^ANOTHER_KEY_[A-Z]+$"], }, ], - errors: [ - { message: "$KEY is not listed as a dependency in any turbo.json" }, - ], + errors: [{ message: "KEY is not listed as a dependency in turbo.json" }], }, { code: ` @@ -268,25 +305,23 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), }, ], errors: [ { message: - "$TASK_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$GLOBAL_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { - message: - "$ENV_VAR_ONE is not listed as a dependency in any turbo.json", + message: "ENV_VAR_ONE is not listed as a dependency in turbo.json", }, { - message: - "$ENV_VAR_TWO is not listed as a dependency in any turbo.json", + message: "ENV_VAR_TWO is not listed as a dependency in turbo.json", }, ], }, @@ -298,21 +333,21 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), }, ], errors: [ { message: - "$GLOBAL_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$TASK_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$ENV_VAR_NOT_ALLOWED is not listed as a dependency in any turbo.json", + "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", }, ], }, @@ -324,21 +359,21 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), }, ], errors: [ { message: - "$GLOBAL_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$TASK_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$ENV_VAR_NOT_ALLOWED is not listed as a dependency in any turbo.json", + "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", }, ], }, @@ -350,21 +385,21 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), }, ], errors: [ { message: - "$GLOBAL_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$TASK_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$ENV_VAR_NOT_ALLOWED is not listed as a dependency in any turbo.json", + "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", }, ], }, @@ -376,21 +411,21 @@ ruleTester.run(RULES.noUndeclaredEnvVars, rule, { `, options: [ { - cwd: path.join(__dirname, "../fixtures/configs/single"), + cwd: path.join(__dirname, "../../__fixtures__/configs/single"), }, ], errors: [ { message: - "$GLOBAL_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "GLOBAL_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$TASK_ENV_KEY_NEW is not listed as a dependency in any turbo.json", + "TASK_ENV_KEY_NEW is not listed as a dependency in turbo.json", }, { message: - "$ENV_VAR_NOT_ALLOWED is not listed as a dependency in any turbo.json", + "ENV_VAR_NOT_ALLOWED is not listed as a dependency in turbo.json", }, ], }, diff --git a/packages/eslint-plugin-turbo/jest.config.js b/packages/eslint-plugin-turbo/jest.config.js index 536bf3abb7485..102773e13b3de 100644 --- a/packages/eslint-plugin-turbo/jest.config.js +++ b/packages/eslint-plugin-turbo/jest.config.js @@ -4,7 +4,8 @@ module.exports = { transform: { "^.+\\.tsx?$": "ts-jest", }, - testPathIgnorePatterns: [".+/fixtures/.+"], + testPathIgnorePatterns: ["/__fixtures__/"], + coveragePathIgnorePatterns: ["/__fixtures__/"], moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], modulePathIgnorePatterns: ["/node_modules", "/dist"], preset: "ts-jest", diff --git a/packages/eslint-plugin-turbo/lib/rules/no-undeclared-env-vars.ts b/packages/eslint-plugin-turbo/lib/rules/no-undeclared-env-vars.ts index 5e3b2ff6fbabc..372d21a9e1c75 100644 --- a/packages/eslint-plugin-turbo/lib/rules/no-undeclared-env-vars.ts +++ b/packages/eslint-plugin-turbo/lib/rules/no-undeclared-env-vars.ts @@ -1,4 +1,5 @@ import type { Rule } from "eslint"; +import path from "path"; import { Node, MemberExpression } from "estree"; import { RULES } from "../constants"; import getEnvVarDependencies from "../utils/getEnvVarDependencies"; @@ -76,12 +77,20 @@ function create(context: Rule.RuleContext): Rule.RuleListener { options ); const filePath = getPhysicalFilename(); - const allTurboVars = - getEnvVarDependencies({ - cwd, - }) || {}; + const allTurboVars = getEnvVarDependencies({ + cwd, + }); + + // if allTurboVars is null, something went wrong reading from the turbo config + // (this is different from finding a config with no env vars present, which would + // return an empty set) - so there is no point continuing if we have nothing to check against + if (!allTurboVars) { + // return of {} bails early from a rule check + return {}; + } const globalTurboVars = allTurboVars["//"]; + const hasWorkspaceConfigs = Object.keys(allTurboVars).length > 1; // find any workspace configs that match the current file path // find workspace config (if any) that match the current file path @@ -94,14 +103,6 @@ function create(context: Rule.RuleContext): Rule.RuleListener { workspaceTurboVars = allTurboVars[workspaceKey]; } - // if this returns null, something went wrong reading from the turbo config - // (this is different from finding a config with no env vars present, which would - // return an empty set) - so there is no point continuing if we have nothing to check against - if (!globalTurboVars) { - // return of {} bails early from a rule check - return {}; - } - const checkKey = (node: Node, envKey?: string) => { if ( envKey && @@ -112,10 +113,24 @@ function create(context: Rule.RuleContext): Rule.RuleListener { if (workspaceTurboVars && workspaceTurboVars.has(envKey)) { return {}; } else { + let message = `{{ envKey }} is not listed as a dependency in ${ + hasWorkspaceConfigs ? "root turbo.json" : "turbo.json" + }`; + if (workspaceKey && workspaceTurboVars) { + if (cwd) { + // if we have a cwd, we can provide a relative path to the workspace config + message = `{{ envKey }} is not listed as a dependency in the root turbo.json or workspace (${path.relative( + cwd, + workspaceKey + )}) turbo.json`; + } else { + message = `{{ envKey }} is not listed as a dependency in the root turbo.json or workspace turbo.json`; + } + } + context.report({ node, - message: - "${{ envKey }} is not listed as a dependency in any turbo.json", + message, data: { envKey }, }); } diff --git a/packages/eslint-plugin-turbo/lib/types.ts b/packages/eslint-plugin-turbo/lib/types.ts deleted file mode 100644 index 3f4ea4675cef5..0000000000000 --- a/packages/eslint-plugin-turbo/lib/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface Pipeline { - outputs?: Array; - dependsOn?: Array; - inputs?: Array; -} - -export interface TurboConfig { - globalDependencies?: Array; - pipeline?: Record; -} diff --git a/packages/eslint-plugin-turbo/package.json b/packages/eslint-plugin-turbo/package.json index 15a9755c6c62c..7b0af03498d81 100644 --- a/packages/eslint-plugin-turbo/package.json +++ b/packages/eslint-plugin-turbo/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-turbo", - "version": "0.0.8", + "version": "0.0.9-canary.0", "description": "ESLint plugin for Turborepo", "keywords": [ "turbo", @@ -39,6 +39,7 @@ "ts-jest": "^27.1.1", "tsconfig": "workspace:*", "tsup": "^6.2.0", + "turbo-test-utils": "workspace:*", "turbo-types": "workspace:*", "turbo-utils": "workspace:*", "typescript": "^4.7.4" diff --git a/packages/eslint-plugin-turbo/tsup.config.ts b/packages/eslint-plugin-turbo/tsup.config.ts index 9d6079edd4b26..bbda8cb604ddc 100644 --- a/packages/eslint-plugin-turbo/tsup.config.ts +++ b/packages/eslint-plugin-turbo/tsup.config.ts @@ -3,5 +3,6 @@ import { defineConfig, Options } from "tsup"; export default defineConfig((options: Options) => ({ entry: ["lib/index.ts"], clean: true, + minify: true, ...options, })); diff --git a/packages/turbo-test-utils/package.json b/packages/turbo-test-utils/package.json index 908d71d4b6655..a81a71c6260d2 100644 --- a/packages/turbo-test-utils/package.json +++ b/packages/turbo-test-utils/package.json @@ -34,6 +34,7 @@ "dependencies": { "fs-extra": "^11.1.0", "js-yaml": "^4.1.0", + "json5": "^2.2.3", "uuid": "^9.0.0" } } diff --git a/packages/turbo-test-utils/src/useFixtures.ts b/packages/turbo-test-utils/src/useFixtures.ts index aafaec163a940..407f6fd7107fb 100644 --- a/packages/turbo-test-utils/src/useFixtures.ts +++ b/packages/turbo-test-utils/src/useFixtures.ts @@ -2,16 +2,17 @@ import { v4 as uuidv4 } from "uuid"; import path from "path"; import fs from "fs-extra"; import yaml from "js-yaml"; +import JSON5 from "json5"; export default function setupTestFixtures({ directory, - test, + test = "", }: { directory: string; - test: string; + test?: string; }) { const fixtures: Array = []; - const parentDirectory = path.join(directory, test); + const parentDirectory = path.join(directory, test ? test : "test-runs"); afterEach(() => { fixtures.forEach((fixture) => { @@ -33,7 +34,6 @@ export default function setupTestFixtures({ fixtures.push(testDirectory); // copy fixture to test directory - const fixturePath = path.join(directory, "__fixtures__", test, fixture); fs.copySync(fixturePath, testDirectory, { recursive: true, @@ -52,15 +52,33 @@ export default function setupTestFixtures({ }; }; + const write = ( + filename: string, + content: string | NodeJS.ArrayBufferView + ) => { + const filePath = path.isAbsolute(filename) + ? filename + : path.join(testDirectory, filename); + + fs.writeFileSync(filePath, content); + }; + const read = readGenerator((filePath) => fs.readFileSync(filePath, "utf8")); const readJson = readGenerator((filePath) => - fs.readJSONSync(filePath, "utf8") + JSON5.parse(fs.readFileSync(filePath, "utf8")) ); const readYaml = readGenerator((filePath) => yaml.load(fs.readFileSync(filePath, "utf8")) ); - return { root: testDirectory, read, readJson, readYaml, directoryName }; + return { + root: testDirectory, + read, + readJson, + readYaml, + write, + directoryName, + }; }; return { useFixture }; diff --git a/packages/turbo-utils/package.json b/packages/turbo-utils/package.json index 69b883b2ac62b..e938ddcfbb2d3 100644 --- a/packages/turbo-utils/package.json +++ b/packages/turbo-utils/package.json @@ -34,12 +34,12 @@ "globby": "11.1.0", "jest": "^27.4.3", "js-yaml": "^4.1.0", - "json5": "^2.2.1", + "json5": "^2.2.3", "ts-jest": "^27.1.1", "tsconfig": "workspace:*", "tsup": "^5.12.1", - "turbo-types": "workspace:*", "turbo-test-utils": "workspace:*", + "turbo-types": "workspace:*", "typescript": "^4.7.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2a10b3b0d300..46906a7dcd75f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -369,6 +369,7 @@ importers: ts-jest: ^27.1.1 tsconfig: workspace:* tsup: ^6.2.0 + turbo-test-utils: workspace:* turbo-types: workspace:* turbo-utils: workspace:* typescript: ^4.7.4 @@ -384,6 +385,7 @@ importers: ts-jest: 27.1.5_vwbkq6iekkdgzr33wjcnr3wuaq tsconfig: link:../tsconfig tsup: 6.2.3_typescript@4.7.4 + turbo-test-utils: link:../turbo-test-utils turbo-types: link:../turbo-types turbo-utils: link:../turbo-utils typescript: 4.7.4 @@ -497,6 +499,7 @@ importers: fs-extra: ^11.1.0 jest: ^27.4.3 js-yaml: ^4.1.0 + json5: ^2.2.3 ts-jest: ^27.1.1 tsconfig: workspace:* typescript: ^4.7.4 @@ -504,6 +507,7 @@ importers: dependencies: fs-extra: 11.1.0 js-yaml: 4.1.0 + json5: 2.2.3 uuid: 9.0.0 devDependencies: '@types/fs-extra': 9.0.13 @@ -564,7 +568,7 @@ importers: globby: 11.1.0 jest: ^27.4.3 js-yaml: ^4.1.0 - json5: ^2.2.1 + json5: ^2.2.3 ts-jest: ^27.1.1 tsconfig: workspace:* tsup: ^5.12.1 @@ -8150,7 +8154,7 @@ packages: '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.12 '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.12 '@babel/traverse': 7.20.12 - '@babel/types': 7.20.7 + '@babel/types': 7.21.0 '@jest/expect-utils': 29.4.1 '@jest/transform': 29.4.1 '@jest/types': 29.4.1 @@ -8374,6 +8378,7 @@ packages: resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} engines: {node: '>=6'} hasBin: true + dev: true /json5/2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} @@ -12330,7 +12335,7 @@ packages: '@types/json-schema': 7.0.11 commander: 9.5.0 glob: 8.0.3 - json5: 2.2.1 + json5: 2.2.3 normalize-path: 3.0.0 safe-stable-stringify: 2.4.0 typescript: 4.8.4 From e44f4dd7674054b7a0cb0fbf7440b92bb05d34ab Mon Sep 17 00:00:00 2001 From: Thomas Knickman Date: Mon, 27 Feb 2023 10:03:04 -0500 Subject: [PATCH 09/16] chore(eslint): bump version (#3976) --- packages/eslint-config-turbo/package.json | 2 +- packages/eslint-plugin-turbo/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-config-turbo/package.json b/packages/eslint-config-turbo/package.json index d0de4c853d07d..36b9a9f2077fd 100644 --- a/packages/eslint-config-turbo/package.json +++ b/packages/eslint-config-turbo/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-turbo", - "version": "0.0.8", + "version": "0.0.9", "description": "ESLint config for Turborepo", "repository": { "type": "git", diff --git a/packages/eslint-plugin-turbo/package.json b/packages/eslint-plugin-turbo/package.json index 7b0af03498d81..ee0e1c2e5a03b 100644 --- a/packages/eslint-plugin-turbo/package.json +++ b/packages/eslint-plugin-turbo/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-turbo", - "version": "0.0.9-canary.0", + "version": "0.0.9", "description": "ESLint plugin for Turborepo", "keywords": [ "turbo", From f572c304c30ad3c016849371fcfc51c5195b0951 Mon Sep 17 00:00:00 2001 From: Thomas Knickman Date: Mon, 27 Feb 2023 10:47:00 -0500 Subject: [PATCH 10/16] chore(renovate): ignore more turbopack tests (#3978) --- .github/renovate.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/renovate.json b/.github/renovate.json index c72bf617f4b64..c79e82d689f8d 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -36,7 +36,8 @@ "ignorePaths": [ "**/node_modules/**", "cli/integration_tests/**", - "crates/turbopack/tests/**" + "crates/turbopack/tests/**", + "crates/turbopack-tests/**" ], "prCreation": "not-pending", "prConcurrentLimit": 5, From fffcfa241dfb3d14e05185cd0dba202264a6c088 Mon Sep 17 00:00:00 2001 From: Will Binns-Smith Date: Mon, 27 Feb 2023 08:14:24 -0800 Subject: [PATCH 11/16] Automatic babel-loader followup (#3944) This: * Addresses feedback from https://github.com/vercel/turbo/pull/3862 * Exempts VirtualAssets from webpack loaders. This addresses a bug where next-hydrate.tsx could not be read. * Adds `ModuleRuleCondition::ResourceIsVirtualAsset` to filter these --------- Co-authored-by: Justin Ridgewell --- Cargo.lock | 12 ++++++ crates/next-core/src/babel.rs | 15 ++++--- .../metadata/input/app/[slug]/page.tsx | 0 .../metadata/input/app/layout.tsx | 0 .../metadata/input/app/page.tsx | 0 .../metadata/input/app/test.tsx | 0 .../metadata/input/app/triangle-black.png | Bin .../metadata/input/next.config.js | 0 crates/turbopack/Cargo.toml | 1 + crates/turbopack/src/lib.rs | 2 +- crates/turbopack/src/module_options/mod.rs | 5 ++- .../src/module_options/module_rule.rs | 13 ++++-- .../src/module_options/rule_condition.rs | 40 +++++++++++++++--- 13 files changed, 71 insertions(+), 17 deletions(-) rename crates/next-dev-tests/tests/integration/next/app/{ => __flakey__}/metadata/input/app/[slug]/page.tsx (100%) rename crates/next-dev-tests/tests/integration/next/app/{ => __flakey__}/metadata/input/app/layout.tsx (100%) rename crates/next-dev-tests/tests/integration/next/app/{ => __flakey__}/metadata/input/app/page.tsx (100%) rename crates/next-dev-tests/tests/integration/next/app/{ => __flakey__}/metadata/input/app/test.tsx (100%) rename crates/next-dev-tests/tests/integration/next/app/{ => __flakey__}/metadata/input/app/triangle-black.png (100%) rename crates/next-dev-tests/tests/integration/next/app/{ => __flakey__}/metadata/input/next.config.js (100%) diff --git a/Cargo.lock b/Cargo.lock index 7d3683a58061d..1c9c2a046b69f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,17 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "async-recursion" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.107", +] + [[package]] name = "async-std" version = "1.12.0" @@ -7717,6 +7728,7 @@ name = "turbopack" version = "0.1.0" dependencies = [ "anyhow", + "async-recursion", "criterion 0.3.6", "difference", "futures", diff --git a/crates/next-core/src/babel.rs b/crates/next-core/src/babel.rs index c5d8d1d0328dc..95c36bdf935d2 100644 --- a/crates/next-core/src/babel.rs +++ b/crates/next-core/src/babel.rs @@ -3,7 +3,7 @@ use turbo_tasks::{ primitives::{BoolVc, StringVc}, Value, }; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_fs::{FileSystemEntryType, FileSystemPathVc}; use turbopack::{ module_options::WebpackLoadersOptionsVc, resolve_options, resolve_options_context::ResolveOptionsContext, @@ -37,8 +37,8 @@ pub async fn maybe_add_babel_loader( let has_babel_config = { let mut has_babel_config = false; for filename in BABEL_CONFIG_FILES { - let metadata = project_root.join(filename).metadata().await; - if metadata.is_ok() { + let filetype = *project_root.join(filename).get_type().await?; + if matches!(filetype, FileSystemEntryType::File) { has_babel_config = true; break; } @@ -48,6 +48,7 @@ pub async fn maybe_add_babel_loader( if has_babel_config { let mut options = (*webpack_options.await?).clone(); + let mut has_emitted_babel_resolve_issue = false; for ext in [".js", ".jsx", ".ts", ".tsx", ".cjs", ".mjs"] { let configs = options.extension_to_loaders.get(ext); let has_babel_loader = match configs { @@ -73,7 +74,9 @@ pub async fn maybe_add_babel_loader( }; if !has_babel_loader { - if !*(is_babel_loader_available(project_root).await?) { + if !has_emitted_babel_resolve_issue + && !*is_babel_loader_available(project_root).await? + { BabelIssue { path: project_root, title: StringVc::cell( @@ -88,7 +91,9 @@ pub async fn maybe_add_babel_loader( } .cell() .as_issue() - .emit() + .emit(); + + has_emitted_babel_resolve_issue = true; } let loader = WebpackLoaderConfigItem::LoaderName("babel-loader".to_owned()); diff --git a/crates/next-dev-tests/tests/integration/next/app/metadata/input/app/[slug]/page.tsx b/crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/[slug]/page.tsx similarity index 100% rename from crates/next-dev-tests/tests/integration/next/app/metadata/input/app/[slug]/page.tsx rename to crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/[slug]/page.tsx diff --git a/crates/next-dev-tests/tests/integration/next/app/metadata/input/app/layout.tsx b/crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/layout.tsx similarity index 100% rename from crates/next-dev-tests/tests/integration/next/app/metadata/input/app/layout.tsx rename to crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/layout.tsx diff --git a/crates/next-dev-tests/tests/integration/next/app/metadata/input/app/page.tsx b/crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/page.tsx similarity index 100% rename from crates/next-dev-tests/tests/integration/next/app/metadata/input/app/page.tsx rename to crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/page.tsx diff --git a/crates/next-dev-tests/tests/integration/next/app/metadata/input/app/test.tsx b/crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/test.tsx similarity index 100% rename from crates/next-dev-tests/tests/integration/next/app/metadata/input/app/test.tsx rename to crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/test.tsx diff --git a/crates/next-dev-tests/tests/integration/next/app/metadata/input/app/triangle-black.png b/crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/triangle-black.png similarity index 100% rename from crates/next-dev-tests/tests/integration/next/app/metadata/input/app/triangle-black.png rename to crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/app/triangle-black.png diff --git a/crates/next-dev-tests/tests/integration/next/app/metadata/input/next.config.js b/crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/next.config.js similarity index 100% rename from crates/next-dev-tests/tests/integration/next/app/metadata/input/next.config.js rename to crates/next-dev-tests/tests/integration/next/app/__flakey__/metadata/input/next.config.js diff --git a/crates/turbopack/Cargo.toml b/crates/turbopack/Cargo.toml index 2f5e46383ad2d..d9459f8f831f2 100644 --- a/crates/turbopack/Cargo.toml +++ b/crates/turbopack/Cargo.toml @@ -15,6 +15,7 @@ bench_against_node_nft = [] [dependencies] anyhow = "1.0.47" +async-recursion = "1.0.2" indexmap = { workspace = true, features = ["serde"] } lazy_static = "1.4.0" regex = "1.5.4" diff --git a/crates/turbopack/src/lib.rs b/crates/turbopack/src/lib.rs index 4137bee7bb720..a0fe58b28692b 100644 --- a/crates/turbopack/src/lib.rs +++ b/crates/turbopack/src/lib.rs @@ -172,7 +172,7 @@ async fn module( let mut current_source = source; let mut current_module_type = None; for rule in options.await?.rules.iter() { - if rule.matches(&*path.await?, &reference_type) { + if rule.matches(source, &*path.await?, &reference_type).await? { for effect in rule.effects() { match effect { ModuleRuleEffect::SourceTransforms(transforms) => { diff --git a/crates/turbopack/src/module_options/mod.rs b/crates/turbopack/src/module_options/mod.rs index 3339a7b932c44..62755c7a80864 100644 --- a/crates/turbopack/src/module_options/mod.rs +++ b/crates/turbopack/src/module_options/mod.rs @@ -264,7 +264,10 @@ impl ModuleOptionsVc { }; for (ext, loaders) in webpack_loaders_options.extension_to_loaders.iter() { rules.push(ModuleRule::new( - ModuleRuleCondition::ResourcePathEndsWith(ext.to_string()), + ModuleRuleCondition::All(vec![ + ModuleRuleCondition::ResourcePathEndsWith(ext.to_string()), + ModuleRuleCondition::not(ModuleRuleCondition::ResourceIsVirtualAsset), + ]), vec![ ModuleRuleEffect::ModuleType(ModuleType::Ecmascript(app_transforms)), ModuleRuleEffect::SourceTransforms(SourceTransformsVc::cell(vec![ diff --git a/crates/turbopack/src/module_options/module_rule.rs b/crates/turbopack/src/module_options/module_rule.rs index 5507ebccb525f..1a2c5a008019b 100644 --- a/crates/turbopack/src/module_options/module_rule.rs +++ b/crates/turbopack/src/module_options/module_rule.rs @@ -2,7 +2,9 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use turbo_tasks::trace::TraceRawVcs; use turbo_tasks_fs::FileSystemPath; -use turbopack_core::{reference_type::ReferenceType, source_transform::SourceTransformsVc}; +use turbopack_core::{ + asset::AssetVc, reference_type::ReferenceType, source_transform::SourceTransformsVc, +}; use turbopack_css::CssInputTransformsVc; use turbopack_ecmascript::EcmascriptInputTransformsVc; @@ -23,8 +25,13 @@ impl ModuleRule { self.effects.iter() } - pub fn matches(&self, path: &FileSystemPath, reference_type: &ReferenceType) -> bool { - self.condition.matches(path, reference_type) + pub async fn matches( + &self, + source: AssetVc, + path: &FileSystemPath, + reference_type: &ReferenceType, + ) -> Result { + self.condition.matches(source, path, reference_type).await } } diff --git a/crates/turbopack/src/module_options/rule_condition.rs b/crates/turbopack/src/module_options/rule_condition.rs index 9ae98605417b9..6e7f54c6437f1 100644 --- a/crates/turbopack/src/module_options/rule_condition.rs +++ b/crates/turbopack/src/module_options/rule_condition.rs @@ -1,7 +1,11 @@ +use anyhow::Result; +use async_recursion::async_recursion; use serde::{Deserialize, Serialize}; use turbo_tasks::{primitives::Regex, trace::TraceRawVcs}; use turbo_tasks_fs::{FileSystemPath, FileSystemPathReadRef}; -use turbopack_core::reference_type::ReferenceType; +use turbopack_core::{ + asset::AssetVc, reference_type::ReferenceType, virtual_asset::VirtualAssetVc, +}; #[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq)] pub enum ModuleRuleCondition { @@ -9,6 +13,7 @@ pub enum ModuleRuleCondition { Any(Vec), Not(Box), ReferenceType(ReferenceType), + ResourceIsVirtualAsset, ResourcePathEquals(FileSystemPathReadRef), ResourcePathHasNoExtension, ResourcePathEndsWith(String), @@ -33,15 +38,33 @@ impl ModuleRuleCondition { } impl ModuleRuleCondition { - pub fn matches(&self, path: &FileSystemPath, reference_type: &ReferenceType) -> bool { - match self { + #[async_recursion] + pub async fn matches( + &self, + source: AssetVc, + path: &FileSystemPath, + reference_type: &ReferenceType, + ) -> Result { + Ok(match self { ModuleRuleCondition::All(conditions) => { - conditions.iter().all(|c| c.matches(path, reference_type)) + for condition in conditions { + if !condition.matches(source, path, reference_type).await? { + return Ok(false); + } + } + true } ModuleRuleCondition::Any(conditions) => { - conditions.iter().any(|c| c.matches(path, reference_type)) + for condition in conditions { + if condition.matches(source, path, reference_type).await? { + return Ok(true); + } + } + false + } + ModuleRuleCondition::Not(condition) => { + !condition.matches(source, path, reference_type).await? } - ModuleRuleCondition::Not(condition) => !condition.matches(path, reference_type), ModuleRuleCondition::ResourcePathEquals(other) => path == &**other, ModuleRuleCondition::ResourcePathEndsWith(end) => path.path.ends_with(end), ModuleRuleCondition::ResourcePathHasNoExtension => { @@ -64,7 +87,10 @@ impl ModuleRuleCondition { ModuleRuleCondition::ReferenceType(condition_ty) => { condition_ty.includes(reference_type) } + ModuleRuleCondition::ResourceIsVirtualAsset => { + VirtualAssetVc::resolve_from(source).await?.is_some() + } _ => todo!("not implemented yet"), - } + }) } } From 3572201b46be9978aa25ab962b960f768c373183 Mon Sep 17 00:00:00 2001 From: Thomas Knickman Date: Mon, 27 Feb 2023 11:43:47 -0500 Subject: [PATCH 12/16] chore(owners): remove pnpm-lock.yaml (#3977) --- .github/CODEOWNERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9c2bcdce11705..ca5d84b1d180c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -17,8 +17,9 @@ /version.txt @vercel/turbo-oss .github/turborepo-release.yml @vercel/turbo-oss -# Nobody owns this file, so nobody should get tagged on changes +# Nobody owns these files, so nobody should get tagged on changes Cargo.lock +pnpm-lock.yaml # Turbopack-specific things /.config/nextest.toml From a38e00aa80d2f4bc74c0fcecf284515a51cc5bfd Mon Sep 17 00:00:00 2001 From: Mehul Kar Date: Mon, 27 Feb 2023 09:13:08 -0800 Subject: [PATCH 13/16] Add more notes to release.md (#3980) --- release.md | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/release.md b/release.md index 78e27fadc48e4..edf7329d37f1b 100644 --- a/release.md +++ b/release.md @@ -50,10 +50,32 @@ We have a multi step release process for Turborepo right now. **NOTE**: The steps below _must_ be run serially, in the order specified. -1. Create a release branch by triggering the [1. Turborepo Release (release branch)](https://github.com/vercel/turbo/actions/workflows/turborepo-release-step-1.yml) workflow - 1. Specify the semver increment using the SemVer Increment field -1. Build the Go Binary by triggering the [2. Turborepo Release (go binary)](https://github.com/vercel/turbo/actions/workflows/turborepo-release-step-2.yml) workflow. +1. Create a release branch by triggering the [1. Turborepo Release (release branch)][1] workflow + + - Specify the semver increment using the SemVer Increment field (start with `prerelease`) + +2. Build the Go Binary by triggering the [2. Turborepo Release (go binary)][2] workflow. + 1. Specify the release branch (example: `staging-1.7.0-canary.1`) in _both_ the "use workflow from", and "Staging branch to release from" fields. -1. Build the Rust Wrapper by triggering the [3. Turborepo Release (rust binary & publish)](https://github.com/vercel/turbo/actions/workflows/turborepo-release-step-3.yml) workflow. + +3. Build the Rust Wrapper by triggering the [3. Turborepo Release (rust binary & publish)][3] workflow. 1. Specify the release branch (example: `staging-1.7.0-canary.1`) in _both_ the "use workflow from", and "Staging branch to release from" fields. (this should match step 2.1 above) -1. After publish, open a PR to merge the release branch created in step 1 back into `main` +4. A PR is automatically opened to merge the release branch created in step 1 back into `main` + + 1. ⚠️ Merge this in! You don't need to wait for tests to pass. + + It's important to merge this branch soon after the publish is succesful + +5. `turbo-orchestrator.yml` polls `npm` every 5 mins. When a new version is detected, + [`turborepo-smoke-published.yml`][4] runs against `@latest` and `@canary` tags. + +### Notes + +- Github Release Notes are published on their own using config from `turborepo-release.yml`, + triggered by the `turbo-orchestrator` bot. +- `eslint-plugin-turbo` and `eslint-config-turbo` need to be published separately. + +[1]: https://github.com/vercel/turbo/actions/workflows/turborepo-release-step-1.yml +[2]: https://github.com/vercel/turbo/actions/workflows/turborepo-release-step-2.yml +[3]: https://github.com/vercel/turbo/actions/workflows/turborepo-release-step-3.yml +[3]: https://github.com/vercel/turbo/actions/workflows/turborepo-smoke-published.yml From 9d276af91113468d5aca6f37f4b7ac304a7eabd3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 12:23:37 -0500 Subject: [PATCH 14/16] release(turborepo): 1.8.3-canary.0 (#3981) Co-authored-by: Turbobot --- cli/cmd/turbo/version.go | 2 +- packages/create-turbo/package.json | 2 +- packages/turbo-codemod/package.json | 2 +- packages/turbo-ignore/package.json | 2 +- packages/turbo/package.json | 14 +++++++------- version.txt | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cli/cmd/turbo/version.go b/cli/cmd/turbo/version.go index 71e3a257708ed..b6ff200c2e920 100644 --- a/cli/cmd/turbo/version.go +++ b/cli/cmd/turbo/version.go @@ -1,3 +1,3 @@ package main -const turboVersion = "1.8.2" +const turboVersion = "1.8.3-canary.0" diff --git a/packages/create-turbo/package.json b/packages/create-turbo/package.json index 7e121096d81ab..309ae1df801af 100644 --- a/packages/create-turbo/package.json +++ b/packages/create-turbo/package.json @@ -1,6 +1,6 @@ { "name": "create-turbo", - "version": "1.8.2", + "version": "1.8.3-canary.0", "description": "Create a new Turborepo", "homepage": "https://turbo.build/repo", "license": "MPL-2.0", diff --git a/packages/turbo-codemod/package.json b/packages/turbo-codemod/package.json index ce9aff3c3b049..8e47677c4e367 100644 --- a/packages/turbo-codemod/package.json +++ b/packages/turbo-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@turbo/codemod", - "version": "1.8.2", + "version": "1.8.3-canary.0", "description": "Provides Codemod transformations to help upgrade your Turborepo codebase when a feature is deprecated.", "homepage": "https://turbo.build/repo", "license": "MPL-2.0", diff --git a/packages/turbo-ignore/package.json b/packages/turbo-ignore/package.json index 031475e738c9b..5600b974d5345 100644 --- a/packages/turbo-ignore/package.json +++ b/packages/turbo-ignore/package.json @@ -1,6 +1,6 @@ { "name": "turbo-ignore", - "version": "1.8.2", + "version": "1.8.3-canary.0", "description": "", "homepage": "https://turbo.build/repo", "keywords": [], diff --git a/packages/turbo/package.json b/packages/turbo/package.json index 9dc998f7d568a..9afd5af28675a 100644 --- a/packages/turbo/package.json +++ b/packages/turbo/package.json @@ -1,6 +1,6 @@ { "name": "turbo", - "version": "1.8.2", + "version": "1.8.3-canary.0", "description": "Turborepo is a high-performance build system for JavaScript and TypeScript codebases.", "repository": "https://github.com/vercel/turbo", "bugs": "https://github.com/vercel/turbo/issues", @@ -19,11 +19,11 @@ "install.js" ], "optionalDependencies": { - "turbo-darwin-64": "1.8.2", - "turbo-darwin-arm64": "1.8.2", - "turbo-linux-64": "1.8.2", - "turbo-linux-arm64": "1.8.2", - "turbo-windows-64": "1.8.2", - "turbo-windows-arm64": "1.8.2" + "turbo-darwin-64": "1.8.3-canary.0", + "turbo-darwin-arm64": "1.8.3-canary.0", + "turbo-linux-64": "1.8.3-canary.0", + "turbo-linux-arm64": "1.8.3-canary.0", + "turbo-windows-64": "1.8.3-canary.0", + "turbo-windows-arm64": "1.8.3-canary.0" } } diff --git a/version.txt b/version.txt index ebe5ee5d8d052..994ba8c209b58 100644 --- a/version.txt +++ b/version.txt @@ -1,2 +1,2 @@ -1.8.2 -latest +1.8.3-canary.0 +canary From b7c3082a2e90594b81d39bf917c2be02e2657ff8 Mon Sep 17 00:00:00 2001 From: OJ Kwon <1210596+kwonoj@users.noreply.github.com> Date: Mon, 27 Feb 2023 09:39:12 -0800 Subject: [PATCH 15/16] ci(workflow): daily next.js test runs against default branch (#3949) This PR switches daily next.js integration test to use latest default branch (canary) instead of specific published version. --- .github/CODEOWNERS | 3 +++ .github/actions/next-integration-stat/index.js | 6 ++++-- .github/actions/next-integration-stat/src/index.ts | 6 ++++-- .github/workflows/daily-nextjs-integration-test.yml | 12 ++++++++++-- .github/workflows/nextjs-integration-test.yml | 13 +++++++++---- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ca5d84b1d180c..73c65e7c24510 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -26,6 +26,9 @@ pnpm-lock.yaml /docs/pages/pack @vercel/web-tooling /xtask @vercel/web-tooling .github/release.yml @vercel/web-tooling +.github/workflows/on-nextjs-release-publish.yml @vercel/web-tooling +.github/workflows/setup-nextjs-build.yml @vercel/web-tooling +.github/workflows/daily-nextjs-integration-test.yml @vercel/web-tooling # crates in alphabetical order /crates @vercel/web-tooling diff --git a/.github/actions/next-integration-stat/index.js b/.github/actions/next-integration-stat/index.js index 2095c2c4e2016..9e13dface1e3c 100644 --- a/.github/actions/next-integration-stat/index.js +++ b/.github/actions/next-integration-stat/index.js @@ -16785,8 +16785,10 @@ // determine if we want to report summary into slack channel. // As a first step, we'll only report summary when the test is run against release-to-release. (no main branch regressions yet) const shouldReportSlack = - process.env.NEXT_TURBO_FORCE_SLACK_UPDATE === "true" || - (!prNumber && !shouldDiffWithMain); + process.env.NEXT_TURBO_FORCE_SKIP_SLACK_UPDATE === "true" + ? false + : process.env.NEXT_TURBO_FORCE_SLACK_UPDATE === "true" || + (!prNumber && !shouldDiffWithMain); // Collect current PR's failed test results const failedJobResults = yield getFailedJobResults(octokit, token, sha); // Get the base to compare against diff --git a/.github/actions/next-integration-stat/src/index.ts b/.github/actions/next-integration-stat/src/index.ts index 16a82e4488581..ac677eb0560d0 100644 --- a/.github/actions/next-integration-stat/src/index.ts +++ b/.github/actions/next-integration-stat/src/index.ts @@ -919,8 +919,10 @@ async function run() { // determine if we want to report summary into slack channel. // As a first step, we'll only report summary when the test is run against release-to-release. (no main branch regressions yet) const shouldReportSlack = - process.env.NEXT_TURBO_FORCE_SLACK_UPDATE === "true" || - (!prNumber && !shouldDiffWithMain); + process.env.NEXT_TURBO_FORCE_SKIP_SLACK_UPDATE === "true" + ? false + : process.env.NEXT_TURBO_FORCE_SLACK_UPDATE === "true" || + (!prNumber && !shouldDiffWithMain); // Collect current PR's failed test results const failedJobResults = await getFailedJobResults(octokit, token, sha); diff --git a/.github/workflows/daily-nextjs-integration-test.yml b/.github/workflows/daily-nextjs-integration-test.yml index 39bccea0f905f..7e75013f38285 100644 --- a/.github/workflows/daily-nextjs-integration-test.yml +++ b/.github/workflows/daily-nextjs-integration-test.yml @@ -7,9 +7,15 @@ on: - cron: "0 8 * * *" workflow_dispatch: inputs: - force_post_to_slack: + version: + description: Next.js version, sha, branch to test + type: string + default: "canary" + + post_to_slack: description: Post test results to Slack type: boolean + default: false jobs: # Trigger actual next.js integration tests. @@ -20,12 +26,14 @@ jobs: uses: ./.github/workflows/nextjs-integration-test.yml with: diff_base: "none" - force_post_to_slack: ${{ inputs.force_post_to_slack || false }} + version: ${{ inputs.version }} + skip_post_to_slack: ${{ inputs.post_to_slack != true }} # Upload test results to branch. upload_test_results: name: Upload test results needs: [next_js_integration] + if: ${{ github.event_name == 'schedule' }} uses: ./.github/workflows/upload-nextjs-integration-test-results.yml with: is_main_branch: true diff --git a/.github/workflows/nextjs-integration-test.yml b/.github/workflows/nextjs-integration-test.yml index 3ca963beb7e93..293e427cf88a9 100644 --- a/.github/workflows/nextjs-integration-test.yml +++ b/.github/workflows/nextjs-integration-test.yml @@ -18,6 +18,10 @@ on: default: "main" force_post_to_slack: type: boolean + # Skip posting to slack regardless of the conditions. + skip_post_to_slack: + type: boolean + default: false jobs: # First, build next-dev and Next.js both to execute across tests. @@ -65,7 +69,7 @@ jobs: # Sets `NEXT_TEST_SKIP_RETRY_MANIFEST`, `NEXT_TEST_CONTINUE_ON_ERROR` to continue on error but do not retry on the known failed tests. # Do not set --timings flag - run: | - docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && ls && curl https://install-node.vercel.app/v${{ matrix.node }} | FORCE=1 bash && node -v && npm i -g pnpm@${PNPM_VERSION} && /work/next-dev --display-version && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_E2E_TEST_TIMEOUT=40000 NEXT_TEST_JOB=1 NEXT_TEST_MODE=dev xvfb-run node run-tests.js --type development -g ${{ matrix.group }}/4 -c 1 >> /proc/1/fd/1" + docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && ls && curl https://install-node.vercel.app/v${{ matrix.node }} | FORCE=1 bash && node -v && npm i -g pnpm@${PNPM_VERSION} && /work/next-dev --display-version && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_E2E_TEST_TIMEOUT=240000 NEXT_TEST_JOB=1 NEXT_TEST_MODE=dev xvfb-run node run-tests.js --type development -g ${{ matrix.group }}/4 -c 1 >> /proc/1/fd/1" name: Run test/development # It is currently expected to fail some of next.js integration test, do not fail CI check. continue-on-error: true @@ -105,7 +109,7 @@ jobs: fail-on-cache-miss: true - run: | - docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && ls && curl https://install-node.vercel.app/v${{ matrix.node }} | FORCE=1 bash && node -v && npm i -g pnpm@${PNPM_VERSION} && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_TEST_JOB=1 NEXT_TEST_MODE=dev xvfb-run node run-tests.js --type e2e -g ${{ matrix.group }}/7 -c 1 >> /proc/1/fd/1" + docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && ls && curl https://install-node.vercel.app/v${{ matrix.node }} | FORCE=1 bash && node -v && npm i -g pnpm@${PNPM_VERSION} && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_E2E_TEST_TIMEOUT=240000 NEXT_TEST_JOB=1 NEXT_TEST_MODE=dev xvfb-run node run-tests.js --type e2e -g ${{ matrix.group }}/7 -c 1 >> /proc/1/fd/1" name: Run test/e2e (dev) continue-on-error: true env: @@ -143,7 +147,7 @@ jobs: # TODO: This test currently seems to load wasm/swc and does not load the next-dev binary. # Temporary disabled until figure out details. #- run: | - # docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && curl -s https://install-node.vercel.app/v16 | FORCE=1 bash && npm i -g pnpm@${PNPM_VERSION} > /dev/null && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_TEST_JOB=1 NEXT_TEST_CNA=1 xvfb-run node run-tests.js test/integration/create-next-app/index.test.ts test/integration/create-next-app/templates.test.ts -c 1 >> /proc/1/fd/1" + # docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && curl -s https://install-node.vercel.app/v16 | FORCE=1 bash && npm i -g pnpm@${PNPM_VERSION} > /dev/null && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_E2E_TEST_TIMEOUT=240000 NEXT_TEST_JOB=1 NEXT_TEST_CNA=1 xvfb-run node run-tests.js test/integration/create-next-app/index.test.ts test/integration/create-next-app/templates.test.ts -c 1 >> /proc/1/fd/1" # name: Run test/e2e (create-next-app) # continue-on-error: true # env: @@ -210,7 +214,7 @@ jobs: fail-on-cache-miss: true - run: | - docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && ls && curl https://install-node.vercel.app/v16 | FORCE=1 bash && node -v && npm i -g pnpm@${PNPM_VERSION} && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_TEST_JOB=1 xvfb-run node run-tests.js -g ${{ matrix.group }}/25 -c 1 >> /proc/1/fd/1" + docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.28.1-focal /bin/bash -c "cd /work && ls && curl https://install-node.vercel.app/v16 | FORCE=1 bash && node -v && npm i -g pnpm@${PNPM_VERSION} && __INTERNAL_CUSTOM_TURBOPACK_BINARY=${NEXT_DEV_BIN} __INTERNAL_NEXT_DEV_TEST_TURBO_GLOB_MATCH=${NEXT_DEV_TEST_GLOB} NEXT_TEST_SKIP_RETRY_MANIFEST=${FAILED_TEST_LIST_PATH} NEXT_TEST_CONTINUE_ON_ERROR=TRUE NEXT_E2E_TEST_TIMEOUT=240000 NEXT_TEST_JOB=1 xvfb-run node run-tests.js -g ${{ matrix.group }}/25 -c 1 >> /proc/1/fd/1" name: Test Integration continue-on-error: true env: @@ -235,6 +239,7 @@ jobs: diff_base: ${{ inputs.diff_base }} env: NEXT_TURBO_FORCE_SLACK_UPDATE: "${{ inputs.force_post_to_slack }}" + NEXT_TURBO_FORCE_SKIP_SLACK_UPDATE: "${{ inputs.skip_post_to_slack }}" - name: Store artifacts uses: actions/upload-artifact@v3 From e4a4aa32b5c6285fef3d4229b2f24c2ec4c12c2a Mon Sep 17 00:00:00 2001 From: Will Binns-Smith Date: Mon, 27 Feb 2023 10:04:06 -0800 Subject: [PATCH 16/16] Snapshot issues in next-dev-tests (#3774) This: * Adds issue snapshot support to next-dev-tests. This will allow us to assert that certain issues are raised in tests that require next-dev. * Extracts common snapshot code into a new crates, `turbopack-test-utils`, which is shared between snapshot tests and next-dev-tests. * Implements an issue reporter that emits issues in a channel to the the integration test code, where they are snapshotted. * Fixes an issue where next-dev tests that were not Next.js apps would emit non-fatal issues for a missing `pages/` directory. Co-authored-by: Justin Ridgewell --------- Co-authored-by: Justin Ridgewell --- Cargo.lock | 19 +- crates/next-core/src/next_config.rs | 10 +- crates/next-core/src/router_source.rs | 12 +- crates/next-dev-tests/Cargo.toml | 2 +- crates/next-dev-tests/build.rs | 3 +- crates/next-dev-tests/tests/integration.rs | 108 +++++++++- .../resolve-alias/basic/input/pages/.gitkeep | 0 ...tar__0__star__) is very dynamic-c19e79.txt | 25 +++ ...__utf-8__quo__) is very dynamic-58d7af.txt | 25 +++ ...tar__0__star__) is very dynamic-667243.txt | 25 +++ .../basic-options/input/index.js | 5 - .../input/{ => pages}/hello.replace | 0 .../basic-options/input/pages/index.js | 17 ++ .../webpack-loaders/no-options/input/index.js | 5 - .../no-options/input/{ => pages}/hello.raw | 0 .../no-options/input/pages/index.js | 17 ++ .../Error evaluating Node.js code-b780fa.txt | 11 + ...rror resolving commonjs request-6b96ad.txt | 11 + ...ving EcmaScript Modules request-1a1150.txt | 11 + ...ving EcmaScript Modules request-431056.txt | 11 + ...ving EcmaScript Modules request-a3050d.txt | 11 + ...rror resolving commonjs request-92a826.txt | 11 + ...rror resolving commonjs request-354825.txt | 11 + ...__.__b__quo__]) is very dynamic-8bc115.txt | 25 +++ ...rror resolving commonjs request-86b73f.txt | 11 + ...__.__c__quo__]) is very dynamic-80ea5a.txt | 25 +++ crates/next-dev/src/lib.rs | 4 +- crates/turbo-tasks/src/debug/mod.rs | 1 + crates/turbo-tasks/src/state.rs | 44 +++- crates/turbopack-cli-utils/src/issue.rs | 12 +- crates/turbopack-core/src/issue/mod.rs | 62 +++--- crates/turbopack-dev-server/src/lib.rs | 4 +- .../src/update/protocol.rs | 2 +- crates/turbopack-node/src/evaluate.rs | 12 +- crates/turbopack-node/src/lib.rs | 13 +- crates/turbopack-test-utils/Cargo.toml | 22 ++ crates/turbopack-test-utils/build.rs | 5 + crates/turbopack-test-utils/src/lib.rs | 4 + crates/turbopack-test-utils/src/snapshot.rs | 189 ++++++++++++++++ crates/turbopack-tests/Cargo.toml | 3 +- crates/turbopack-tests/tests/snapshot.rs | 204 +++--------------- 41 files changed, 730 insertions(+), 262 deletions(-) create mode 100644 crates/next-dev-tests/tests/integration/next/resolve-alias/basic/input/pages/.gitkeep create mode 100644 crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt create mode 100644 crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt create mode 100644 crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt delete mode 100644 crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/index.js rename crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/{ => pages}/hello.replace (100%) create mode 100644 crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/pages/index.js delete mode 100644 crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/index.js rename crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/{ => pages}/hello.raw (100%) create mode 100644 crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js create mode 100644 crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-b780fa.txt create mode 100644 crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-6b96ad.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-1a1150.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-431056.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-a3050d.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-92a826.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-86b73f.txt create mode 100644 crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt create mode 100644 crates/turbopack-test-utils/Cargo.toml create mode 100644 crates/turbopack-test-utils/build.rs create mode 100644 crates/turbopack-test-utils/src/lib.rs create mode 100644 crates/turbopack-test-utils/src/snapshot.rs diff --git a/Cargo.lock b/Cargo.lock index 1c9c2a046b69f..0c02866e4bb65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3813,7 +3813,6 @@ dependencies = [ "mime", "next-core", "next-dev", - "once_cell", "owo-colors", "parking_lot", "rand", @@ -3833,6 +3832,7 @@ dependencies = [ "turbopack-core", "turbopack-dev-server", "turbopack-node", + "turbopack-test-utils", "url", "webbrowser 0.7.1", ] @@ -7991,6 +7991,20 @@ dependencies = [ "turbopack-core", ] +[[package]] +name = "turbopack-test-utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "once_cell", + "similar", + "turbo-tasks", + "turbo-tasks-build", + "turbo-tasks-fs", + "turbo-tasks-hash", + "turbopack-core", +] + [[package]] name = "turbopack-tests" version = "0.1.0" @@ -8000,18 +8014,17 @@ dependencies = [ "once_cell", "serde", "serde_json", - "similar", "test-generator", "tokio", "turbo-tasks", "turbo-tasks-build", "turbo-tasks-env", "turbo-tasks-fs", - "turbo-tasks-hash", "turbo-tasks-memory", "turbopack", "turbopack-core", "turbopack-env", + "turbopack-test-utils", ] [[package]] diff --git a/crates/next-core/src/next_config.rs b/crates/next-core/src/next_config.rs index 2e161aab70cc4..2b6ace3720314 100644 --- a/crates/next-core/src/next_config.rs +++ b/crates/next-core/src/next_config.rs @@ -8,7 +8,7 @@ use turbo_tasks::{ CompletionVc, Value, }; use turbo_tasks_env::EnvMapVc; -use turbo_tasks_fs::json::parse_json_rope_with_source_context; +use turbo_tasks_fs::{json::parse_json_rope_with_source_context, FileSystemPathVc}; use turbopack::evaluate_context::node_evaluate_asset_context; use turbopack_core::{ asset::Asset, @@ -603,3 +603,11 @@ pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result Result { + Ok(BoolVc::cell(!matches!( + *find_context_file(context, next_configs()).await?, + FindContextFileResult::NotFound(_) + ))) +} diff --git a/crates/next-core/src/router_source.rs b/crates/next-core/src/router_source.rs index 66ae50c512fd6..de22d55e03e71 100644 --- a/crates/next-core/src/router_source.rs +++ b/crates/next-core/src/router_source.rs @@ -12,7 +12,7 @@ use turbopack_dev_server::source::{ use turbopack_node::execution_context::ExecutionContextVc; use crate::{ - next_config::NextConfigVc, + next_config::{has_next_config, NextConfigVc}, router::{route, RouterRequest, RouterResult}, }; @@ -74,6 +74,16 @@ impl ContentSource for NextRouterContentSource { ) -> Result { let this = self_vc.await?; + // The next-dev server can currently run against projects as simple as + // `index.js`. If this isn't a Next.js project, don't try to use the Next.js + // router. + let project_root = this.execution_context.await?.project_root; + if !(*has_next_config(project_root).await?) { + return Ok(this + .inner + .get(path, Value::new(ContentSourceData::default()))); + } + let ContentSourceData { method: Some(method), raw_headers: Some(raw_headers), diff --git a/crates/next-dev-tests/Cargo.toml b/crates/next-dev-tests/Cargo.toml index bf1420a445c5f..b1dea860a299d 100644 --- a/crates/next-dev-tests/Cargo.toml +++ b/crates/next-dev-tests/Cargo.toml @@ -30,7 +30,6 @@ lazy_static = "1.4.0" mime = "0.3.16" next-core = { path = "../next-core" } next-dev = { path = "../next-dev" } -once_cell = "1.13.0" owo-colors = "3" parking_lot = "0.12.1" rand = "0.8.5" @@ -53,6 +52,7 @@ turbopack-cli-utils = { path = "../turbopack-cli-utils" } turbopack-core = { path = "../turbopack-core" } turbopack-dev-server = { path = "../turbopack-dev-server" } turbopack-node = { path = "../turbopack-node" } +turbopack-test-utils = { path = "../turbopack-test-utils" } url = "2.2.2" webbrowser = "0.7.1" diff --git a/crates/next-dev-tests/build.rs b/crates/next-dev-tests/build.rs index 09dd315050872..1cfa867e95d55 100644 --- a/crates/next-dev-tests/build.rs +++ b/crates/next-dev-tests/build.rs @@ -1,6 +1,7 @@ -use turbo_tasks_build::rerun_if_glob; +use turbo_tasks_build::{generate_register, rerun_if_glob}; fn main() { + generate_register(); // The test/integration crate need to be rebuilt if any test input is changed. // Unfortunately, we can't have the build.rs file operate differently on // each file, so the entire next-dev crate needs to be rebuilt. diff --git a/crates/next-dev-tests/tests/integration.rs b/crates/next-dev-tests/tests/integration.rs index c75afd8beaf7d..9eed0bcd845bd 100644 --- a/crates/next-dev-tests/tests/integration.rs +++ b/crates/next-dev-tests/tests/integration.rs @@ -1,3 +1,4 @@ +#![feature(min_specialization)] #![cfg(test)] extern crate test_generator; @@ -25,16 +26,31 @@ use chromiumoxide::{ }; use futures::StreamExt; use lazy_static::lazy_static; -use next_dev::{register, EntryRequest, NextDevServerBuilder}; +use next_dev::{EntryRequest, NextDevServerBuilder}; use owo_colors::OwoColorize; use serde::Deserialize; use test_generator::test_resources; -use tokio::{net::TcpSocket, task::JoinSet}; +use tokio::{ + net::TcpSocket, + sync::mpsc::{channel, Sender}, + task::JoinSet, +}; use tungstenite::{error::ProtocolError::ResetWithoutClosingHandshake, Error::Protocol}; -use turbo_tasks::TurboTasks; -use turbo_tasks_fs::util::sys_to_unix; +use turbo_tasks::{ + debug::{ValueDebug, ValueDebugStringReadRef}, + primitives::BoolVc, + NothingVc, RawVc, ReadRef, State, TransientInstance, TransientValue, TurboTasks, +}; +use turbo_tasks_fs::{DiskFileSystemVc, FileSystem}; use turbo_tasks_memory::MemoryBackend; use turbo_tasks_testing::retry::retry_async; +use turbopack_core::issue::{CapturedIssues, IssueReporter, IssueReporterVc, PlainIssueReadRef}; +use turbopack_test_utils::snapshot::snapshot_issues; + +fn register() { + next_dev::register(); + include!(concat!(env!("OUT_DIR"), "/register_test_integration.rs")); +} #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] @@ -155,18 +171,27 @@ async fn run_test(resource: &str) -> JestRunResult { ); let package_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let workspace_root = package_root.parent().unwrap().parent().unwrap(); - let project_dir = workspace_root.join(resource).join("input"); + let workspace_root = package_root + .parent() + .unwrap() + .parent() + .unwrap() + .to_path_buf(); + let test_dir = workspace_root.join(resource); + let project_dir = test_dir.join("input"); let requested_addr = get_free_local_addr().unwrap(); let mock_dir = path.join("__httpmock__"); let mock_server_future = get_mock_server_future(&mock_dir); - let turbo_tasks = TurboTasks::new(MemoryBackend::default()); + let (issue_tx, mut issue_rx) = channel(u16::MAX as usize); + let issue_tx = TransientInstance::new(issue_tx); + + let tt = TurboTasks::new(MemoryBackend::default()); let server = NextDevServerBuilder::new( - turbo_tasks, - sys_to_unix(&project_dir.to_string_lossy()).to_string(), - sys_to_unix(&workspace_root.to_string_lossy()).to_string(), + tt.clone(), + project_dir.to_string_lossy().to_string(), + workspace_root.to_string_lossy().to_string(), ) .entry_request(EntryRequest::Module( "@turbo/pack-test-harness".to_string(), @@ -178,6 +203,9 @@ async fn run_test(resource: &str) -> JestRunResult { .port(requested_addr.port()) .log_level(turbopack_core::issue::IssueSeverity::Warning) .log_detail(true) + .issue_reporter(Box::new(move || { + TestIssueReporterVc::new(issue_tx.clone()).into() + })) .show_all(true) .build() .await @@ -198,6 +226,29 @@ async fn run_test(resource: &str) -> JestRunResult { env::remove_var("TURBOPACK_TEST_ONLY_MOCK_SERVER"); + let task = tt.spawn_once_task(async move { + let issues_fs = DiskFileSystemVc::new( + "issues".to_string(), + test_dir.join("issues").to_string_lossy().to_string(), + ) + .as_file_system(); + + let mut issues = vec![]; + while let Ok(issue) = issue_rx.try_recv() { + issues.push(issue); + } + + snapshot_issues( + issues.iter().cloned(), + issues_fs.root(), + &workspace_root.to_string_lossy(), + ) + .await?; + + Ok(NothingVc::new().into()) + }); + tt.wait_task_completion(task, true).await.unwrap(); + result } @@ -414,3 +465,40 @@ async fn get_mock_server_future(mock_dir: &Path) -> Result<(), String> { std::future::pending::>().await } } + +#[turbo_tasks::value(shared)] +struct TestIssueReporter { + #[turbo_tasks(trace_ignore, debug_ignore)] + pub issue_tx: State>, +} + +#[turbo_tasks::value_impl] +impl TestIssueReporterVc { + #[turbo_tasks::function] + fn new( + issue_tx: TransientInstance>, + ) -> Self { + TestIssueReporter { + issue_tx: State::new((*issue_tx).clone()), + } + .cell() + } +} + +#[turbo_tasks::value_impl] +impl IssueReporter for TestIssueReporter { + #[turbo_tasks::function] + async fn report_issues( + &self, + captured_issues: TransientInstance>, + _source: TransientValue, + ) -> Result { + let issue_tx = self.issue_tx.get_untracked().clone(); + for issue in captured_issues.iter() { + let plain = issue.into_plain(); + issue_tx.send((plain.await?, plain.dbg().await?)).await?; + } + + Ok(BoolVc::cell(false)) + } +} diff --git a/crates/next-dev-tests/tests/integration/next/resolve-alias/basic/input/pages/.gitkeep b/crates/next-dev-tests/tests/integration/next/resolve-alias/basic/input/pages/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt new file mode 100644 index 0000000000000..0acc69df7766a --- /dev/null +++ b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.existsSync(__q____q____q____star__0__star__) is very dynamic-c19e79.txt @@ -0,0 +1,25 @@ +PlainIssue { + severity: Warning, + context: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + category: "parse", + title: "lint TP1004 fs.existsSync(???*0*) is very dynamic", + description: "- *0* arguments[0]\n ⚠\u{fe0f} function calls are not analysed yet", + detail: "", + documentation_link: "", + source: Some( + PlainIssueSource { + asset: PlainAsset { + path: "node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + }, + start: SourcePos { + line: 87, + column: 8, + }, + end: SourcePos { + line: 87, + column: 8, + }, + }, + ), + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt new file mode 100644 index 0000000000000..866db710e5a72 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1004 fs.readFileSync(__q____q____q____star__0__star__, __quo__utf-8__quo__) is very dynamic-58d7af.txt @@ -0,0 +1,25 @@ +PlainIssue { + severity: Warning, + context: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + category: "parse", + title: "lint TP1004 fs.readFileSync(???*0*, \"utf-8\") is very dynamic", + description: "- *0* arguments[0]\n ⚠\u{fe0f} function calls are not analysed yet", + detail: "", + documentation_link: "", + source: Some( + PlainIssueSource { + asset: PlainAsset { + path: "node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/previous-map.js", + }, + start: SourcePos { + line: 89, + column: 13, + }, + end: SourcePos { + line: 89, + column: 13, + }, + }, + ), + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt new file mode 100644 index 0000000000000..848737ac7abdc --- /dev/null +++ b/crates/next-dev-tests/tests/integration/next/tailwind/basic/issues/lint TP1006 path.resolve(__q____q____q____star__0__star__) is very dynamic-667243.txt @@ -0,0 +1,25 @@ +PlainIssue { + severity: Warning, + context: "[project-with-next]/node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/input.js", + category: "parse", + title: "lint TP1006 path.resolve(???*0*) is very dynamic", + description: "- *0* ???*1*[\"from\"]\n ⚠\u{fe0f} unknown object\n- *1* opts\n ⚠\u{fe0f} pattern without value", + detail: "", + documentation_link: "", + source: Some( + PlainIssueSource { + asset: PlainAsset { + path: "node_modules/.pnpm/postcss@8.4.20/node_modules/postcss/lib/input.js", + }, + start: SourcePos { + line: 43, + column: 20, + }, + end: SourcePos { + line: 43, + column: 20, + }, + }, + ), + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/index.js b/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/index.js deleted file mode 100644 index 02dbf512a5a01..0000000000000 --- a/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import source from "./hello.replace"; - -it("runs a loader with basic options", () => { - expect(source).toBe(3); -}); diff --git a/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/hello.replace b/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/pages/hello.replace similarity index 100% rename from crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/hello.replace rename to crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/pages/hello.replace diff --git a/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/pages/index.js b/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/pages/index.js new file mode 100644 index 0000000000000..e150264eb5543 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/pages/index.js @@ -0,0 +1,17 @@ +import { useEffect } from "react"; +import source from "./hello.replace"; + +export default function Home() { + useEffect(() => { + // Only run on client + import("@turbo/pack-test-harness").then(runTests); + }); + + return null; +} + +function runTests() { + it("runs a loader with basic options", () => { + expect(source).toBe(3); + }); +} diff --git a/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/index.js b/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/index.js deleted file mode 100644 index 400c55352f579..0000000000000 --- a/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import source from "./hello.raw"; - -it("runs a simple loader", () => { - expect(source).toBe("Hello World"); -}); diff --git a/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/hello.raw b/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw similarity index 100% rename from crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/hello.raw rename to crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw diff --git a/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js b/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js new file mode 100644 index 0000000000000..4df1f68aab843 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js @@ -0,0 +1,17 @@ +import { useEffect } from "react"; +import source from "./hello.raw"; + +export default function Home() { + useEffect(() => { + // Only run on client + import("@turbo/pack-test-harness").then(runTests); + }); + + return null; +} + +function runTests() { + it("runs a simple loader", () => { + expect(source).toBe("Hello World"); + }); +} diff --git a/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-b780fa.txt b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-b780fa.txt new file mode 100644 index 0000000000000..726fe7cc5ae68 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error evaluating Node.js code-b780fa.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input", + category: "build", + title: "Error evaluating Node.js code", + description: "Error: > Couldn't find a `pages` directory. Please create one under the project root\n at Object.findPagesDir (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/lib/find-pages-dir.js:86:19)\n at DevServer.getRoutes (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/dev/next-dev-server.js:130:59)\n at new Server (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/base-server.js:108:47)\n at new NextNodeServer (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/next-server.js:69:9)\n at new DevServer (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/dev/next-dev-server.js:96:9)\n at Object.makeResolver (node_modules/.pnpm/next@13.1.7-canary.28_pjwopsidmaokadturxaafygjp4/node_modules/next/dist/server/lib/route-resolver.js:39:23)\n at getResolveRoute (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/router.js:170:97)\n at async Module.route (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/router.js:173:36)\n at async Module.run (crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/.next/build/router/chunks/[turbopack-node]_ipc_evaluate.ts._.js:142:39)\n", + detail: "", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-6b96ad.txt b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-6b96ad.txt new file mode 100644 index 0000000000000..05cbde4138bc6 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/issues/Error resolving commonjs request-6b96ad.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/index.js", + category: "resolve", + title: "Error resolving commonjs request", + description: "unable to resolve relative \"./not-existing-file\"", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./not-existing-file\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/turbopack/basic/comptime/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-1a1150.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-1a1150.txt new file mode 100644 index 0000000000000..cd5c8c3160753 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-1a1150.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", + category: "resolve", + title: "Error resolving EcmaScript Modules request", + description: "unable to resolve relative \"./empty?import2-in-chunk1\"", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import2-in-chunk1\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-431056.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-431056.txt new file mode 100644 index 0000000000000..12b6a9c3d414e --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-431056.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", + category: "resolve", + title: "Error resolving EcmaScript Modules request", + description: "unable to resolve relative \"./empty?import1-in-chunk1\"", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import1-in-chunk1\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-a3050d.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-a3050d.txt new file mode 100644 index 0000000000000..7bf04d0b03b36 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/issues/Error resolving EcmaScript Modules request-a3050d.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js", + category: "resolve", + title: "Error resolving EcmaScript Modules request", + description: "unable to resolve relative \"./empty?import3-in-chunk2\"", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?import3-in-chunk2\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/named-chunks/input/index.js\nType of request: EcmaScript Modules request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-92a826.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-92a826.txt new file mode 100644 index 0000000000000..a1e0386bd6a3f --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/issues/Error resolving commonjs request-92a826.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/input/index.js", + category: "resolve", + title: "Error resolving commonjs request", + description: "unable to resolve relative \"./empty?require.ensure:test\"", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: relative \"./empty?require.ensure:test\"\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/parsing/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt new file mode 100644 index 0000000000000..c7ffb33ad07b7 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/Error resolving commonjs request-354825.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", + category: "resolve", + title: "Error resolving commonjs request", + description: "unable to resolve dynamic", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: dynamic\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt new file mode 100644 index 0000000000000..9f61ddd73dd8d --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/issues/lint TP1002 require([__quo__.__b__quo__]) is very dynamic-8bc115.txt @@ -0,0 +1,25 @@ +PlainIssue { + severity: Warning, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", + category: "parse", + title: "lint TP1002 require([\"./b\"]) is very dynamic", + description: "", + detail: "", + documentation_link: "", + source: Some( + PlainIssueSource { + asset: PlainAsset { + path: "crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies-context/input/index.js", + }, + start: SourcePos { + line: 13, + column: 2, + }, + end: SourcePos { + line: 13, + column: 2, + }, + }, + ), + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-86b73f.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-86b73f.txt new file mode 100644 index 0000000000000..ecf350a66844a --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/Error resolving commonjs request-86b73f.txt @@ -0,0 +1,11 @@ +PlainIssue { + severity: Error, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", + category: "resolve", + title: "Error resolving commonjs request", + description: "unable to resolve dynamic", + detail: "It was not possible to find the requested file.\nParsed request as written in source code: dynamic\nPath where resolving has started: [project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js\nType of request: commonjs request\nImport map: No import map entry\n", + documentation_link: "", + source: None, + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt new file mode 100644 index 0000000000000..2340dffe7ab21 --- /dev/null +++ b/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/issues/lint TP1002 require([__quo__.__c__quo__]) is very dynamic-80ea5a.txt @@ -0,0 +1,25 @@ +PlainIssue { + severity: Warning, + context: "[project-with-next]/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", + category: "parse", + title: "lint TP1002 require([\"./c\"]) is very dynamic", + description: "", + detail: "", + documentation_link: "", + source: Some( + PlainIssueSource { + asset: PlainAsset { + path: "crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/weak-dependencies/input/index.js", + }, + start: SourcePos { + line: 5, + column: 2, + }, + end: SourcePos { + line: 5, + column: 2, + }, + }, + ), + sub_issues: [], +} \ No newline at end of file diff --git a/crates/next-dev/src/lib.rs b/crates/next-dev/src/lib.rs index 4116b462ee126..e960c670a2c43 100644 --- a/crates/next-dev/src/lib.rs +++ b/crates/next-dev/src/lib.rs @@ -247,12 +247,12 @@ async fn handle_issues + CollectiblesSource + Copy>( .strongly_consistent() .await?; - issue_reporter.report_issues( + let has_fatal = issue_reporter.report_issues( TransientInstance::new(issues.clone()), TransientValue::new(source.into()), ); - if issues.has_fatal().await? { + if *has_fatal.await? { Err(anyhow!("Fatal issue(s) occurred")) } else { Ok(()) diff --git a/crates/turbo-tasks/src/debug/mod.rs b/crates/turbo-tasks/src/debug/mod.rs index 51cd2e0c577b7..7844a2e3d7224 100644 --- a/crates/turbo-tasks/src/debug/mod.rs +++ b/crates/turbo-tasks/src/debug/mod.rs @@ -14,6 +14,7 @@ use internal::PassthroughDebug; /// /// We don't use `StringVc` directly because we don't want the `Debug`/`Display` /// representations to be escaped. +#[derive(Clone)] #[turbo_tasks::value] pub struct ValueDebugString(String); diff --git a/crates/turbo-tasks/src/state.rs b/crates/turbo-tasks/src/state.rs index 5f49d51511f69..1adc34fce1d6a 100644 --- a/crates/turbo-tasks/src/state.rs +++ b/crates/turbo-tasks/src/state.rs @@ -1,4 +1,8 @@ -use std::{fmt::Debug, mem::take}; +use std::{ + fmt::Debug, + mem::take, + ops::{Deref, DerefMut}, +}; use auto_hash_map::AutoSet; use parking_lot::{Mutex, MutexGuard}; @@ -17,6 +21,7 @@ struct StateInner { pub struct StateRef<'a, T> { inner: MutexGuard<'a, StateInner>, + mutated: bool, } impl Debug for State { @@ -47,7 +52,7 @@ impl PartialEq for State { } impl Eq for State {} -impl Serialize for State { +impl Serialize for State { fn serialize(&self, _serializer: S) -> Result { // For this to work at all we need to do more. Changing the the state need to // invalidate the serialization of the task that contains the state. So we @@ -57,7 +62,7 @@ impl Serialize for State { } } -impl<'de, T: Deserialize<'de>> Deserialize<'de> for State { +impl<'de, T> Deserialize<'de> for State { fn deserialize>(_deserializer: D) -> Result { panic!("State serialization is not implemented yet"); } @@ -90,7 +95,19 @@ impl State { let invalidator = get_invalidator(); let mut inner = self.inner.lock(); inner.invalidators.insert(invalidator); - StateRef { inner } + StateRef { + inner, + mutated: false, + } + } + + /// Gets the current value of the state. Untracked. + pub fn get_untracked(&self) -> StateRef<'_, T> { + let inner = self.inner.lock(); + StateRef { + inner, + mutated: false, + } } /// Sets the current state without comparing it with the old value. This @@ -133,10 +150,27 @@ impl State { } } -impl<'a, T> std::ops::Deref for StateRef<'a, T> { +impl<'a, T> Deref for StateRef<'a, T> { type Target = T; fn deref(&self) -> &Self::Target { &self.inner.value } } + +impl<'a, T> DerefMut for StateRef<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.mutated = true; + &mut self.inner.value + } +} + +impl<'a, T> Drop for StateRef<'a, T> { + fn drop(&mut self) { + if self.mutated { + for invalidator in take(&mut self.inner.invalidators) { + invalidator.invalidate(); + } + } + } +} diff --git a/crates/turbopack-cli-utils/src/issue.rs b/crates/turbopack-cli-utils/src/issue.rs index 52f8a6bd4f310..9fed3d3a04369 100644 --- a/crates/turbopack-cli-utils/src/issue.rs +++ b/crates/turbopack-cli-utils/src/issue.rs @@ -11,7 +11,8 @@ use anyhow::{anyhow, Result}; use crossterm::style::{StyledContent, Stylize}; use owo_colors::{OwoColorize as _, Style}; use turbo_tasks::{ - RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, ValueToString, + primitives::BoolVc, RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, + ValueToString, }; use turbo_tasks_fs::{ attach::AttachedFileSystemVc, @@ -433,7 +434,7 @@ impl IssueReporter for ConsoleUi { &self, issues: TransientInstance>, source: TransientValue, - ) -> Result<()> { + ) -> Result { let issues = &*issues; let LogOptions { ref current_dir, @@ -465,12 +466,17 @@ impl IssueReporter for ConsoleUi { .unwrap() .new_ids(source.into_value(), issue_ids); + let mut has_fatal = false; for (plain_issue, path, context, id) in issues { if !new_ids.remove(&id) { continue; } let severity = plain_issue.severity; + if severity == IssueSeverity::Fatal { + has_fatal = true; + } + let context_path = make_relative_to_cwd(context, current_dir).await?; let category = &plain_issue.category; let title = &plain_issue.title; @@ -606,7 +612,7 @@ impl IssueReporter for ConsoleUi { } } - Ok(()) + Ok(BoolVc::cell(has_fatal)) } } diff --git a/crates/turbopack-core/src/issue/mod.rs b/crates/turbopack-core/src/issue/mod.rs index 17e425e1510c5..a681f4882f8b3 100644 --- a/crates/turbopack-core/src/issue/mod.rs +++ b/crates/turbopack-core/src/issue/mod.rs @@ -21,8 +21,7 @@ use turbo_tasks::{ ValueToString, ValueToStringVc, }; use turbo_tasks_fs::{ - FileContent, FileContentReadRef, FileLine, FileLinesContent, FileSystemPathReadRef, - FileSystemPathVc, + FileContent, FileContentReadRef, FileLine, FileLinesContent, FileSystemPathVc, }; use turbo_tasks_hash::{DeterministicHash, Xxh3Hash64Hasher}; @@ -341,21 +340,6 @@ pub struct CapturedIssues { processing_path: ItemIssueProcessingPathVc, } -impl CapturedIssues { - pub async fn has_fatal(&self) -> Result { - let mut has_fatal = false; - - for issue in self.issues.iter() { - let severity = *issue.severity().await?; - if severity == IssueSeverity::Fatal { - has_fatal = true; - break; - } - } - Ok(has_fatal) - } -} - #[turbo_tasks::value_impl] impl CapturedIssuesVc { #[turbo_tasks::function] @@ -471,24 +455,24 @@ pub struct PlainIssue { pub sub_issues: Vec, } -#[turbo_tasks::value_impl] -impl PlainIssueVc { +impl PlainIssue { /// We need deduplicate issues that can come from unique paths, but /// represent the same underlying problem. Eg, a parse error for a file /// that is compiled in both client and server contexts. - #[turbo_tasks::function] - pub async fn internal_hash(self) -> Result { - let this = self.await?; + pub fn internal_hash(&self) -> u64 { let mut hasher = Xxh3Hash64Hasher::new(); - hasher.write_ref(&this.severity); - hasher.write_ref(&this.context); - hasher.write_ref(&this.category); - hasher.write_ref(&this.title); - hasher.write_ref(&this.description); - hasher.write_ref(&this.detail); - hasher.write_ref(&this.documentation_link); - - if let Some(source) = &this.source { + hasher.write_ref(&self.severity); + hasher.write_ref(&self.context); + hasher.write_ref(&self.category); + hasher.write_ref(&self.title); + hasher.write_ref( + // Normalize syspaths from Windows. These appear in stack traces. + &self.description.replace("\\", "/"), + ); + hasher.write_ref(&self.detail); + hasher.write_ref(&self.documentation_link); + + if let Some(source) = &self.source { hasher.write_value(1_u8); // I'm assuming we don't need to hash the contents. Not 100% correct, but // probably 99%. @@ -498,7 +482,15 @@ impl PlainIssueVc { hasher.write_value(0_u8); } - Ok(U64Vc::cell(hasher.finish())) + hasher.finish() + } +} + +#[turbo_tasks::value_impl] +impl PlainIssueVc { + #[turbo_tasks::function] + pub async fn internal_hash(self) -> Result { + Ok(U64Vc::cell(self.await?.internal_hash())) } } @@ -562,7 +554,7 @@ impl IssueSourceVc { #[turbo_tasks::value(serialization = "none")] #[derive(Clone, Debug)] pub struct PlainAsset { - pub path: FileSystemPathReadRef, + pub path: String, #[turbo_tasks(debug_ignore)] pub content: FileContentReadRef, } @@ -578,7 +570,7 @@ impl PlainAssetVc { }; Ok(PlainAsset { - path: asset.path().await?, + path: asset.path().await?.to_string(), content, } .cell()) @@ -591,5 +583,5 @@ pub trait IssueReporter { &self, issues: TransientInstance>, source: TransientValue, - ); + ) -> BoolVc; } diff --git a/crates/turbopack-dev-server/src/lib.rs b/crates/turbopack-dev-server/src/lib.rs index 9851b65ff5682..17df99beda059 100644 --- a/crates/turbopack-dev-server/src/lib.rs +++ b/crates/turbopack-dev-server/src/lib.rs @@ -78,12 +78,12 @@ async fn handle_issues + CollectiblesSource + Copy>( .strongly_consistent() .await?; - issue_reporter.report_issues( + let has_fatal = issue_reporter.report_issues( TransientInstance::new(issues.clone()), TransientValue::new(source.into()), ); - if issues.has_fatal().await? { + if *has_fatal.await? { Err(anyhow!("Fatal issue(s) occurred in {path} ({operation})")) } else { Ok(()) diff --git a/crates/turbopack-dev-server/src/update/protocol.rs b/crates/turbopack-dev-server/src/update/protocol.rs index 23145b137131e..c99d1d258c830 100644 --- a/crates/turbopack-dev-server/src/update/protocol.rs +++ b/crates/turbopack-dev-server/src/update/protocol.rs @@ -129,7 +129,7 @@ impl<'a> From<&'a PlainIssue> for Issue<'a> { fn from(plain: &'a PlainIssue) -> Self { let source = plain.source.as_deref().map(|source| IssueSource { asset: Asset { - path: &source.asset.path.path, + path: &source.asset.path, }, start: source.start, end: source.end, diff --git a/crates/turbopack-node/src/evaluate.rs b/crates/turbopack-node/src/evaluate.rs index 376f8cd390bda..fc1d91e0d14ff 100644 --- a/crates/turbopack-node/src/evaluate.rs +++ b/crates/turbopack-node/src/evaluate.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, collections::HashMap, thread::available_parallelism, time::Duration}; -use anyhow::Result; +use anyhow::{Context, Result}; use futures_retry::{FutureRetry, RetryPolicy}; use turbo_tasks::{ primitives::{JsonValueVc, StringVc}, @@ -226,6 +226,7 @@ pub async fn evaluate( EvaluationIssue { error, context_path: context_path_for_issue, + cwd, } .cell() .as_issue() @@ -279,6 +280,7 @@ pub async fn evaluate( #[turbo_tasks::value(shared)] pub struct EvaluationIssue { pub context_path: FileSystemPathVc, + pub cwd: FileSystemPathVc, pub error: StructuredError, } @@ -301,8 +303,14 @@ impl Issue for EvaluationIssue { #[turbo_tasks::function] async fn description(&self) -> Result { + let cwd = to_sys_path(self.cwd.root()) + .await? + .context("Must have path on disk")?; + Ok(StringVc::cell( - self.error.print(Default::default(), None).await?, + self.error + .print(Default::default(), &cwd.to_string_lossy()) + .await?, )) } } diff --git a/crates/turbopack-node/src/lib.rs b/crates/turbopack-node/src/lib.rs index 3d7c3b75978e5..2e6e6b7cd64fa 100644 --- a/crates/turbopack-node/src/lib.rs +++ b/crates/turbopack-node/src/lib.rs @@ -264,18 +264,17 @@ pub struct StructuredError { } impl StructuredError { - async fn print( - &self, - assets: HashMap, - root: Option, - ) -> Result { + async fn print(&self, assets: HashMap, root: &str) -> Result { let mut message = String::new(); writeln!(message, "{}: {}", self.name, self.message)?; for frame in &self.stack { if let Some((line, column)) = frame.get_pos() { - if let Some(path) = root.as_ref().and_then(|r| frame.file.strip_prefix(r)) { + if let Some(path) = frame.file.strip_prefix( + // Add a trailing slash so paths don't lead with `/`. + &format!("{}{}", root, std::path::MAIN_SEPARATOR), + ) { if let Some(map) = assets.get(path) { let trace = SourceMapTraceVc::new(*map, line, column, frame.name.clone()) .trace() @@ -333,7 +332,7 @@ pub async fn trace_stack( .flatten() .collect::>(); - error.print(assets, Some(root)).await + error.print(assets, &root).await } pub fn register() { diff --git a/crates/turbopack-test-utils/Cargo.toml b/crates/turbopack-test-utils/Cargo.toml new file mode 100644 index 0000000000000..9a3c35ae1aed3 --- /dev/null +++ b/crates/turbopack-test-utils/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "turbopack-test-utils" +version = "0.1.0" +description = "TBD" +license = "MPL-2.0" +edition = "2021" +autobenches = false + +[lib] +bench = false + +[dependencies] +anyhow = "1.0.47" +once_cell = "1.13.0" +similar = "2.2.0" +turbo-tasks = { path = "../turbo-tasks" } +turbo-tasks-fs = { path = "../turbo-tasks-fs" } +turbo-tasks-hash = { path = "../turbo-tasks-hash" } +turbopack-core = { path = "../turbopack-core" } + +[build-dependencies] +turbo-tasks-build = { path = "../turbo-tasks-build" } diff --git a/crates/turbopack-test-utils/build.rs b/crates/turbopack-test-utils/build.rs new file mode 100644 index 0000000000000..1673efed59cce --- /dev/null +++ b/crates/turbopack-test-utils/build.rs @@ -0,0 +1,5 @@ +use turbo_tasks_build::generate_register; + +fn main() { + generate_register(); +} diff --git a/crates/turbopack-test-utils/src/lib.rs b/crates/turbopack-test-utils/src/lib.rs new file mode 100644 index 0000000000000..bd283f6a618fb --- /dev/null +++ b/crates/turbopack-test-utils/src/lib.rs @@ -0,0 +1,4 @@ +#![feature(min_specialization)] +#![feature(str_split_as_str)] + +pub mod snapshot; diff --git a/crates/turbopack-test-utils/src/snapshot.rs b/crates/turbopack-test-utils/src/snapshot.rs new file mode 100644 index 0000000000000..c69ad42a6a493 --- /dev/null +++ b/crates/turbopack-test-utils/src/snapshot.rs @@ -0,0 +1,189 @@ +use std::{ + collections::{HashMap, HashSet}, + env, fs, +}; + +use anyhow::{anyhow, bail, Context, Result}; +use once_cell::sync::Lazy; +use similar::TextDiff; +use turbo_tasks::{debug::ValueDebugStringReadRef, TryJoinIterExt, ValueToString}; +use turbo_tasks_fs::{ + DirectoryContent, DirectoryEntry, DiskFileSystemVc, File, FileContent, FileSystemEntryType, + FileSystemPathVc, +}; +use turbo_tasks_hash::encode_hex; +use turbopack_core::{ + asset::{AssetContent, AssetContentVc}, + issue::PlainIssueReadRef, +}; + +// Updates the existing snapshot outputs with the actual outputs of this run. +// e.g. `UPDATE=1 cargo test -p turbopack-tests -- test_my_pattern` +static UPDATE: Lazy = Lazy::new(|| env::var("UPDATE").unwrap_or_default() == "1"); + +pub async fn snapshot_issues< + I: IntoIterator, +>( + captured_issues: I, + issues_path: FileSystemPathVc, + workspace_root: &str, +) -> Result<()> { + let expected_issues = expected(issues_path).await?; + let mut seen = HashSet::new(); + for (plain_issue, debug_string) in captured_issues.into_iter() { + let hash = encode_hex(plain_issue.internal_hash()); + + let path = issues_path.join(&format!( + "{}-{}.txt", + plain_issue + .title + .replace('/', "__") + // We replace "*", "?", and '"' because they're not allowed in filenames on Windows. + .replace('*', "__star__") + .replace('"', "__quo__") + .replace('?', "__q__"), + &hash[0..6] + )); + seen.insert(path); + + // Annoyingly, the PlainIssue.source -> PlainIssueSource.asset -> + // PlainAsset.path -> FileSystemPath.fs -> DiskFileSystem.root changes + // for everyone. + let content = debug_string + .as_str() + .replace(workspace_root, "WORKSPACE_ROOT") + // Normalize syspaths from Windows. These appear in stack traces. + .replace("\\\\", "/"); + let asset = File::from(content).into(); + + diff(path, asset).await?; + } + + matches_expected(expected_issues, seen).await +} + +pub async fn expected(dir: FileSystemPathVc) -> Result> { + let mut expected = HashSet::new(); + let entries = dir.read_dir().await?; + if let DirectoryContent::Entries(entries) = &*entries { + for (file, entry) in entries { + match entry { + DirectoryEntry::File(file) => { + expected.insert(*file); + } + _ => bail!( + "expected file at {}, found {:?}", + file, + FileSystemEntryType::from(entry) + ), + } + } + } + Ok(expected) +} + +pub async fn matches_expected( + expected: HashSet, + seen: HashSet, +) -> Result<()> { + for path in diff_paths(&expected, &seen).await? { + let p = &path.await?.path; + if *UPDATE { + remove_file(path).await?; + println!("removed file {}", p); + } else { + bail!("expected file {}, but it was not emitted", p); + } + } + Ok(()) +} + +pub async fn diff(path: FileSystemPathVc, actual: AssetContentVc) -> Result<()> { + let path_str = &path.await?.path; + let expected = path.read().into(); + + let actual = match get_contents(actual, path).await? { + Some(s) => s, + None => bail!("could not generate {} contents", path_str), + }; + let expected = get_contents(expected, path).await?; + + if Some(&actual) != expected.as_ref() { + if *UPDATE { + let content = File::from(actual).into(); + path.write(content).await?; + println!("updated contents of {}", path_str); + } else { + if expected.is_none() { + eprintln!("new file {path_str} detected:"); + } else { + eprintln!("contents of {path_str} did not match:"); + } + let expected = expected.unwrap_or_default(); + let diff = TextDiff::from_lines(&expected, &actual); + eprintln!( + "{}", + diff.unified_diff() + .context_radius(3) + .header("expected", "actual") + ); + bail!("contents of {path_str} did not match"); + } + } + + Ok(()) +} + +async fn get_contents(file: AssetContentVc, path: FileSystemPathVc) -> Result> { + Ok( + match &*file.await.context(format!( + "Unable to read AssetContent of {}", + path.to_string().await? + ))? { + AssetContent::File(file) => match &*file.await.context(format!( + "Unable to read FileContent of {}", + path.to_string().await? + ))? { + FileContent::NotFound => None, + FileContent::Content(expected) => { + Some(expected.content().to_str()?.trim().to_string()) + } + }, + AssetContent::Redirect { target, link_type } => Some(format!( + "Redirect {{ target: {target}, link_type: {:?} }}", + link_type + )), + }, + ) +} + +async fn remove_file(path: FileSystemPathVc) -> Result<()> { + let fs = DiskFileSystemVc::resolve_from(path.fs()) + .await? + .context(anyhow!("unexpected fs type"))? + .await?; + let sys_path = fs.to_sys_path(path).await?; + fs::remove_file(&sys_path).context(format!("remove file {} error", sys_path.display()))?; + Ok(()) +} + +/// Values in left that are not in right. +/// FileSystemPathVc hashes as a Vc, not as the file path, so we need to get the +/// path to properly diff. +async fn diff_paths( + left: &HashSet, + right: &HashSet, +) -> Result> { + let mut map = left + .iter() + .map(|p| async move { Ok((p.await?.path.clone(), *p)) }) + .try_join() + .await? + .iter() + .cloned() + .collect::>(); + for p in right { + map.remove(&p.await?.path); + } + Ok(map.values().copied().collect()) +} diff --git a/crates/turbopack-tests/Cargo.toml b/crates/turbopack-tests/Cargo.toml index fc13864e5afb4..6a00d047b921f 100644 --- a/crates/turbopack-tests/Cargo.toml +++ b/crates/turbopack-tests/Cargo.toml @@ -18,16 +18,15 @@ next-core = { path = "../next-core", features = ['native-tls'] } once_cell = "1.13.0" serde = "1.0.136" serde_json = "1.0.85" -similar = "2.2.0" test-generator = "0.3.0" tokio = "1.21.2" turbo-tasks = { path = "../turbo-tasks" } turbo-tasks-env = { path = "../turbo-tasks-env" } turbo-tasks-fs = { path = "../turbo-tasks-fs" } -turbo-tasks-hash = { path = "../turbo-tasks-hash" } turbo-tasks-memory = { path = "../turbo-tasks-memory" } turbopack-core = { path = "../turbopack-core" } turbopack-env = { path = "../turbopack-env" } +turbopack-test-utils = { path = "../turbopack-test-utils" } [build-dependencies] turbo-tasks-build = { path = "../turbo-tasks-build" } diff --git a/crates/turbopack-tests/tests/snapshot.rs b/crates/turbopack-tests/tests/snapshot.rs index 1e833f075563a..0a9b7dec3064d 100644 --- a/crates/turbopack-tests/tests/snapshot.rs +++ b/crates/turbopack-tests/tests/snapshot.rs @@ -6,19 +6,16 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{anyhow, bail, Context, Result}; +use anyhow::{anyhow, Context, Result}; use once_cell::sync::Lazy; use serde::Deserialize; -use similar::TextDiff; use test_generator::test_resources; use turbo_tasks::{debug::ValueDebug, NothingVc, TryJoinIterExt, TurboTasks, Value, ValueToString}; use turbo_tasks_env::DotenvProcessEnvVc; use turbo_tasks_fs::{ - json::parse_json_with_source_context, util::sys_to_unix, DirectoryContent, DirectoryEntry, - DiskFileSystemVc, File, FileContent, FileSystem, FileSystemEntryType, FileSystemPathVc, - FileSystemVc, + json::parse_json_with_source_context, util::sys_to_unix, DiskFileSystemVc, FileSystem, + FileSystemPathVc, FileSystemVc, }; -use turbo_tasks_hash::encode_hex; use turbo_tasks_memory::MemoryBackend; use turbopack::{ condition::ContextCondition, @@ -29,7 +26,7 @@ use turbopack::{ ModuleAssetContextVc, }; use turbopack_core::{ - asset::{Asset, AssetContent, AssetContentVc, AssetVc}, + asset::{Asset, AssetVc}, chunk::{dev::DevChunkingContextVc, ChunkableAsset, ChunkableAssetVc}, compile_time_defines, compile_time_info::CompileTimeInfo, @@ -41,16 +38,13 @@ use turbopack_core::{ source_asset::SourceAssetVc, }; use turbopack_env::ProcessEnvAssetVc; +use turbopack_test_utils::snapshot::{diff, expected, matches_expected, snapshot_issues}; fn register() { turbopack::register(); include!(concat!(env!("OUT_DIR"), "/register_test_snapshot.rs")); } -// Updates the existing snapshot outputs with the actual outputs of this run. -// `UPDATE=1 cargo test -p turbopack -- test_my_pattern` -static UPDATE: Lazy = Lazy::new(|| env::var("UPDATE").unwrap_or_default() == "1"); - static WORKSPACE_ROOT: Lazy = Lazy::new(|| { let package_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); package_root @@ -104,16 +98,35 @@ async fn run(resource: &'static str) -> Result<()> { let tt = TurboTasks::new(MemoryBackend::default()); let task = tt.spawn_once_task(async move { let out = run_test(resource.to_string()); - handle_issues(out) - .await - .context("Unable to handle issues")?; + let captured_issues = IssueVc::peek_issues_with_path(out) + .await? + .strongly_consistent() + .await?; + + let plain_issues = captured_issues + .iter() + .map(|issue_vc| async move { + Ok(( + issue_vc.into_plain().await?, + issue_vc.into_plain().dbg().await?, + )) + }) + .try_join() + .await?; + + snapshot_issues( + plain_issues.into_iter(), + out.join("issues"), + &WORKSPACE_ROOT, + ) + .await + .context("Unable to handle issues")?; Ok(NothingVc::new().into()) }); tt.wait_task_completion(task, true).await?; Ok(()) } - #[turbo_tasks::function] async fn run_test(resource: String) -> Result { let test_path = Path::new(&resource) @@ -269,16 +282,6 @@ async fn run_test(resource: String) -> Result { Ok(path) } -async fn remove_file(path: FileSystemPathVc) -> Result<()> { - let fs = DiskFileSystemVc::resolve_from(path.fs()) - .await? - .context(anyhow!("unexpected fs type"))? - .await?; - let sys_path = fs.to_sys_path(path).await?; - fs::remove_file(&sys_path).context(format!("remove file {} error", sys_path.display()))?; - Ok(()) -} - async fn walk_asset( asset: AssetVc, seen: &mut HashSet, @@ -296,65 +299,6 @@ async fn walk_asset( Ok(()) } -async fn get_contents(file: AssetContentVc, path: FileSystemPathVc) -> Result> { - Ok( - match &*file.await.context(format!( - "Unable to read AssetContent of {}", - path.to_string().await? - ))? { - AssetContent::File(file) => match &*file.await.context(format!( - "Unable to read FileContent of {}", - path.to_string().await? - ))? { - FileContent::NotFound => None, - FileContent::Content(expected) => { - Some(expected.content().to_str()?.trim().to_string()) - } - }, - AssetContent::Redirect { target, link_type } => Some(format!( - "Redirect {{ target: {target}, link_type: {:?} }}", - link_type - )), - }, - ) -} - -async fn diff(path: FileSystemPathVc, actual: AssetContentVc) -> Result<()> { - let path_str = &path.await?.path; - let expected = path.read().into(); - - let actual = match get_contents(actual, path).await? { - Some(s) => s, - None => bail!("could not generate {} contents", path_str), - }; - let expected = get_contents(expected, path).await?; - - if Some(&actual) != expected.as_ref() { - if *UPDATE { - let content = File::from(actual).into(); - path.write(content).await?; - println!("updated contents of {}", path_str); - } else { - if expected.is_none() { - eprintln!("new file {path_str} detected:"); - } else { - eprintln!("contents of {path_str} did not match:"); - } - let expected = expected.unwrap_or_default(); - let diff = TextDiff::from_lines(&expected, &actual); - eprintln!( - "{}", - diff.unified_diff() - .context_radius(3) - .header("expected", "actual") - ); - bail!("contents of {path_str} did not match"); - } - } - - Ok(()) -} - async fn maybe_load_env( project_fs: FileSystemVc, path: &Path, @@ -373,95 +317,3 @@ async fn maybe_load_env( asset.as_ecmascript_chunk_placeable() ]))) } - -async fn expected(dir: FileSystemPathVc) -> Result> { - let mut expected = HashSet::new(); - let entries = dir.read_dir().await?; - if let DirectoryContent::Entries(entries) = &*entries { - for (file, entry) in entries { - match entry { - DirectoryEntry::File(file) => { - expected.insert(*file); - } - _ => bail!( - "expected file at {}, found {:?}", - file, - FileSystemEntryType::from(entry) - ), - } - } - } - Ok(expected) -} - -/// Values in left that are not in right. -/// FileSystemPathVc hashes as a Vc, not as the file path, so we need to get the -/// path to properly diff. -async fn diff_paths( - left: &HashSet, - right: &HashSet, -) -> Result> { - let mut map = left - .iter() - .map(|p| async move { Ok((p.await?.path.clone(), *p)) }) - .try_join() - .await? - .iter() - .cloned() - .collect::>(); - for p in right { - map.remove(&p.await?.path); - } - Ok(map.values().copied().collect()) -} - -async fn matches_expected( - expected: HashSet, - seen: HashSet, -) -> Result<()> { - for path in diff_paths(&expected, &seen).await? { - let p = &path.await?.path; - if *UPDATE { - remove_file(path).await?; - println!("removed file {}", p); - } else { - bail!("expected file {}, but it was not emitted", p); - } - } - Ok(()) -} - -async fn handle_issues(source: FileSystemPathVc) -> Result<()> { - let issues_path = source.join("issues"); - let expected_issues = expected(issues_path).await?; - - let mut seen = HashSet::new(); - let issues = IssueVc::peek_issues_with_path(source) - .await? - .strongly_consistent() - .await?; - - for issue in issues.iter() { - let plain_issue = issue.into_plain(); - let hash = encode_hex(*plain_issue.internal_hash().await?); - - // We replace "*" because it's not allowed for filename on Windows. - let path = issues_path.join(&format!( - "{}-{}.txt", - plain_issue.await?.title.replace('*', "__star__"), - &hash[0..6] - )); - seen.insert(path); - - // Annoyingly, the PlainIssue.source -> PlainIssueSource.asset -> - // PlainAsset.path -> FileSystemPath.fs -> DiskFileSystem.root changes - // for everyone. - let content = - format!("{}", plain_issue.dbg().await?).replace(&*WORKSPACE_ROOT, "WORKSPACE_ROOT"); - let asset = File::from(content).into(); - - diff(path, asset).await?; - } - - matches_expected(expected_issues, seen).await -}