Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix monorepo support by allowing import to do what it's good at (and … #2359

Conversation

NullVoxPopuli
Copy link
Contributor

…ignoring paths 🙃)

let plugin;

try {
let importedModule = await import(pluginName);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without trying this first, we can't actually use plugins from node_modules 🙈

For example, prior to this change, we'd get this error:

<repo>/node_modules/resolve/lib/sync.js:102
    var err = new Error("Cannot find module '" + x + "' from '" + parent + "'");
              ^

Error: Cannot find module 'ember-template-lint-plugin-tailwindcss' from '<repo>/frontend'
    at Function.resolveSync [as sync] (<repo>/node_modules/resolve/lib/sync.js:102:15)
    at requirePlugin (file://<repo>/node_modules/ember-template-lint/lib/get-config.js:31:28)
    at processPlugins (file://<repo>/node_modules/ember-template-lint/lib/get-config.js:150:22)
    at getProjectConfig (file://<repo>/node_modules/ember-template-lint/lib/get-config.js:396:28)
    at async Linter.loadConfig (file://<repo>/node_modules/ember-template-lint/lib/linter.js:48:19)
    at async Linter.verify (file://<repo>/node_modules/ember-template-lint/lib/linter.js:304:7)
    at async run (file://<repo>/node_modules/ember-template-lint/bin/ember-template-lint.js:211:21) {
  code: 'MODULE_NOT_FOUND'
}
error Command failed with exit code 1.    }

Copy link
Member

Choose a reason for hiding this comment

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

Can you explain more about how the monorepo is setup?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue is present in any monorepo where the ember project is not at the root, where the root's node_modules contains ember-template-lint (so almost every monorepo)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the reproduction is very easy:

  • clone any monorepo
  • cd into the monorepo
  • cd into the ember project
  • swap out template lint for v4
  • add a template-lint plugin that is compat with v4
  • error

Copy link
Member

Choose a reason for hiding this comment

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

Are you suggesting that your monorepo has ember-template-lint in the root (presumably as a devDep), and the plugins in subdirs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wouldn't say typically. If you have a small enough monorepo where you can have the same version of a tool everywhere and every package in the monorepo needed it, it may make sense.
But monorepo conventions are orthogonal to the issue here 🙃

It's perfectly reasonable for only one package in a monorepo to need template lint, and therefor, it'd be local to that package, yet potentially still hoisted

Copy link
Member

Choose a reason for hiding this comment

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

OK sure. I suppose from my perspective that's part of the benefit of monorepos - minimizing tool dependencies so you have less maintenance. But of course that's not super relevant, though what I was getting at was trying to first determine if this was an issue that could be handled via a recommended setup vs. a code change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense -- important question though -- why were we not relying on the built-in node resolution algo (which happens for us via import/require) and trying to find deps ourselves?

Copy link
Member

@rwjblue rwjblue Apr 14, 2022

Choose a reason for hiding this comment

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

why were we not relying on the built-in node resolution algo (which happens for us via import/require) and trying to find deps ourselves?

Because the node resolution algorithm is actually wrong in this case 😸. We don't want to resolve the plugin name relative to ember-template-lint. Specifically, the node modules algorithm would suggest that the plugin must be resolvable from whatever location ember-template-lint itself is installed at. Which is not correct! The plugin will be installed somewhere relative to the .template-lintrc.js file not where ever** ember-template-lint happens to be installed. This is the point of the current resolve.sync code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I disagree. And in the mean time, all plugin usage is broken in monorepos 😢

@bmish
Copy link
Member

bmish commented Jan 29, 2022

We'll need tests for this that fail before the change and pass after.

@bmish bmish added the bug label Jan 29, 2022
@NullVoxPopuli
Copy link
Contributor Author

We'll need tests for this that fail before the change and pass after.

How do you want that to happen?
Are there existing tests where you generate whole projects and additional plugins?

@bmish
Copy link
Member

bmish commented Jan 29, 2022

@NullVoxPopuli yes we have tests / test fixtures that set up fake projects and plugins. We will need to do something similar for this monorepo situation.

@NullVoxPopuli
Copy link
Contributor Author

@bmish I've added the beginnings of a test, the main thing is that I need to set the baseDir of a Project and that's not supported in the current version of fixurify project -- and "just upgrading" breaks a bunch of stuff.

@NullVoxPopuli
Copy link
Contributor Author

@bmish anyway to move forward without the test? or is there some other way to simulate monorepo? I suppose I could not use fixturify-project for the monorepo test 🤔

This is just blocking adoption within all monorepos 🙃

imo, letting node do the module resolution by default (instead of via file path) is the more correct thing to do anyway 🥳

@bmish
Copy link
Member

bmish commented Jan 30, 2022

Having tests for all changes is very important to me, especially for a change like this. I made sure all the changes that went into the v4 release were comprehensively tested. So it will be great for us to get this monorepo scenario tested. I can try to help with the fixturify-project upgrade over the next few days if you haven't figured that out. Thanks for starting on the monorepo test in the meantime.

@NullVoxPopuli
Copy link
Contributor Author

Having tests for all changes is very important to me

I'm with ya there -- especially with big projects.

I don't think I want to deal with fixturify changes 🙃
Should I wait for you to upgrade that? or should I proceed with these tests without fixturify?

@bmish
Copy link
Member

bmish commented Jan 31, 2022

My preferred path is that we get the fixturify-project upgrade in so we can utilize that. However, I spent a bit of time trying to figure it out but didn't make much progress and it was not fun...I wish there was a better migration guide for it. I'll see if I can try again in next few days.

@bmish
Copy link
Member

bmish commented Mar 4, 2022

Tests for this should hopefully be unblocked now that this has been merged:

@rwjblue
Copy link
Member

rwjblue commented Apr 14, 2022

Taking another crack at this over in #2471

@rwjblue
Copy link
Member

rwjblue commented Apr 14, 2022

More tests being added in #2473

@rwjblue
Copy link
Member

rwjblue commented Apr 14, 2022

At the moment, I'm not able to reproduce a failure (in either #2471 or #2473). I think we need a better understanding of the failure (preferably via a reproduction in the "clone this, npm install, npm test" form) that @NullVoxPopuli was trying to fix.

@NullVoxPopuli
Copy link
Contributor Author

NullVoxPopuli commented Apr 14, 2022

full repro steps:

Terminal 1

git clone git@github.com:NullVoxPopuli/limber.git
cd limber
git checkout etl-repro
yarn

This branch, etl-repro has a template-lint plugin and ember-template-lint@^4.4.0.

Below is where we get the ESM version of the plugin, as plugins gotta be ESM

Terminal 2

git@gitlab.com:NullVoxPopuli/ember-template-lint-plugin-tailwindcss.git
cd ember-template-lint-plugin-tailwindcss
git checkout vitest
yarn
yarn build
yarn link

Back in Terminal 1

yarn link ember-template-lint-plugin-tailwindcss
cd frontend
yarn link ember-template-lint-plugin-tailwindcss
yarn lint:hbs

Expected Error:

❯ yarn ember-template-lint .
yarn run v1.22.17
$ <repo>/node_modules/.bin/ember-template-lint .
<repo>/node_modules/resolve/lib/sync.js:111
    var err = new Error("Cannot find module '" + x + "' from '" + parent + "'");
              ^

Error: Cannot find module 'ember-template-lint-plugin-tailwindcss' from '<repo>/frontend'
    at Function.resolveSync [as sync] (<repo>/node_modules/resolve/lib/sync.js:111:15)
    at requirePlugin (file://<repo>/node_modules/ember-template-lint/lib/get-config.js:39:28)
    at processPlugins (file://<repo>/node_modules/ember-template-lint/lib/get-config.js:159:22)
    at getProjectConfig (file://<repo>/node_modules/ember-template-lint/lib/get-config.js:419:28)
    at async Linter.loadConfig (file://<repo>/node_modules/ember-template-lint/lib/linter.js:45:19)
    at async Linter.verify (file://<repo>/node_modules/ember-template-lint/lib/linter.js:301:7)
    at async run (file://<repo>/node_modules/ember-template-lint/bin/ember-template-lint.js:219:21) {
  code: 'MODULE_NOT_FOUND'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.}

@rwjblue
Copy link
Member

rwjblue commented Apr 15, 2022

Thank you @NullVoxPopuli! Finally reproduced this style of failure over in #2475.

The good news is that it is specifically limited to cases where resolve.sync does not find a main entry point, but import() would. That is mostly going to be when you have exports setup but no main (but not only that scenario, that just seems like the most likely one).

@NullVoxPopuli
Copy link
Contributor Author

NullVoxPopuli commented May 19, 2022

The good news is that it is specifically limited to cases where resolve.sync does not find a main entry point, but import() would. That is mostly going to be when you have exports setup but no main (but not only that scenario, that just seems like the most likely one).

I missed this.
Hmm.

This doesn't seem as bad as i thought
Will need to take a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants