vercel / turborepo

Build system optimized for JavaScript and TypeScript, written in Rust
https://turbo.build/repo/docs
MIT License
26k stars 1.79k forks source link

Cache is extracted to wrong destination #8476

Open markbrockhoff opened 3 months ago

markbrockhoff commented 3 months ago

Verify canary release

Link to code that reproduces this issue

https://github.com/markbrockhoff/turbo-repo-bug-repro

What package manager are you using / does the bug impact?

pnpm

What operating system are you using?

Mac

Which canary version will you have in your reproduction?

2.0.4-canary.3

Describe the Bug

Whenever I execute a build using turborepo for the first time everything is generated correctly and cached. But when running the same build again the existing cache is restored to the wrong directory causing build files to end up in the src directory.

Expected Behavior

I'd expect turborepo to restore the build cache in the exact same location where it came from.

To Reproduce

I created a minimal reproduction using the latest version of turborepo containing only one package which is the default starter for creating a Nuxt module (That's where I encountered the issue)

To reproduce the issue do the following steps:

  1. Clone the repro: git clone https://github.com/markbrockhoff/turbo-repo-bug-repro
  2. Install the dependencies pnpm i
  3. Run a first build: pnpm build
  4. Run a second build: pnpm build

After the second build you'll see that two new files were created within /packages/nuxt-test/src/runtime. These files should be placed inside the dist folder but somehow seem to be restored into the src folder. I think the issue has something to do with the fact that the build task depends on the dev:prepare task and both habe the dist folder as output, however it's still very strange to me that the files end up in a totally different place.

Additional context

I'm using pnpm v9.3.0 and node 20.11.0, any help with this issue would be appreciated. Thanks

chris-olszewski commented 3 months ago

I can confirm that this is due to the overlapping outputs interacting in a very weird way. It appears that something in dev:prepare is creating a symlink from dist/runtime -> src/runtime:

[0 olszewski@chriss-mbp] /tmp/turbo-repo-bug-repro/packages/nuxt-test $ pnpm dev:prepare

> my-module@1.0.0 dev:prepare /private/tmp/turbo-repo-bug-repro/packages/nuxt-test
> nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground

ℹ Stubbing my-module                                                                                                                         11:30:47 AM
ℹ Cleaning dist directory: ./dist                                                                                                            11:30:47 AM
✔ Types generated in .nuxt                                                                                                                   11:30:49 AM
✔ Types generated in playground/.nuxt                                                                                                        11:30:50 AM
[0 olszewski@chriss-mbp] /tmp/turbo-repo-bug-repro/packages/nuxt-test $ ls -lh dist 
total 48
-rw-r--r--  1 olszewski  wheel   227B Jun 13 11:30 module.cjs
-rw-r--r--  1 olszewski  wheel   171B Jun 13 11:30 module.d.ts
-rw-r--r--  1 olszewski  wheel   156B Jun 13 11:30 module.json
-rw-r--r--  1 olszewski  wheel   477B Jun 13 11:30 module.mjs
lrwxr-xr-x  1 olszewski  wheel    64B Jun 13 11:30 runtime -> /private/tmp/turbo-repo-bug-repro/packages/nuxt-test/src/runtime
-rw-r--r--  1 olszewski  wheel   918B Jun 13 11:30 types.d.mts
-rw-r--r--  1 olszewski  wheel   912B Jun 13 11:30 types.d.ts

This leads to the issue when we there's a cache hit for my-module#build and we attempt to restore dist/runtime/plugin.js and dist/runtime/plugin.d.ts to dist/runtime which now points to src/runtime due to the symlink created by dev:prepare

[0 olszewski@chriss-mbp] /tmp/turbo-repo-bug-repro $ tar --use-compress-program=unzstd -tvf .turbo/cache/72cffa046a69ae97.tar.zst 
-rw-r--r--  0 0      0        1257 Dec 31  1969 packages/nuxt-test/.turbo/turbo-build.log
drwxr-xr-x  0 0      0           0 Dec 31  1969 packages/nuxt-test/dist/
-rw-r--r--  0 0      0         227 Dec 31  1969 packages/nuxt-test/dist/module.cjs
-rw-r--r--  0 0      0         192 Dec 31  1969 packages/nuxt-test/dist/module.d.mts
-rw-r--r--  0 0      0         192 Dec 31  1969 packages/nuxt-test/dist/module.d.ts
-rw-r--r--  0 0      0         156 Dec 31  1969 packages/nuxt-test/dist/module.json
-rw-r--r--  0 0      0         415 Dec 31  1969 packages/nuxt-test/dist/module.mjs
drwxr-xr-x  0 0      0           0 Dec 31  1969 packages/nuxt-test/dist/runtime/
-rw-r--r--  0 0      0         152 Dec 31  1969 packages/nuxt-test/dist/runtime/plugin.d.ts
-rw-r--r--  0 0      0         141 Dec 31  1969 packages/nuxt-test/dist/runtime/plugin.js
drwxr-xr-x  0 0      0           0 Dec 31  1969 packages/nuxt-test/dist/runtime/server/
-rw-r--r--  0 0      0          56 Dec 31  1969 packages/nuxt-test/dist/runtime/server/tsconfig.json
-rw-r--r--  0 0      0         425 Dec 31  1969 packages/nuxt-test/dist/types.d.mts
-rw-r--r--  0 0      0         419 Dec 31  1969 packages/nuxt-test/dist/types.d.ts
markbrockhoff commented 3 months ago

Ah, that makes sense that the symlik is causing the issue. Thanks for the explanation. I was able to fix the issue inside my project by avoiding the duplicate caching of the dist folder. However I still wanted to report the strange behavior as it might also affect other people.

chris-olszewski commented 3 months ago

@markbrockhoff Thanks for the report!

I think this is still a bug on our end as we should be removing the dist/runtime symlink and creating a new directory instead of just placing files in it.

Now having two tasks who disagree on what a file (dist/runtime) should be is to be avoided as running one task will effectively "undo" the other.