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

repo: fix implicit dependencies #7303

Closed
wants to merge 2 commits into from
Closed

repo: fix implicit dependencies #7303

wants to merge 2 commits into from

Conversation

paul-marechal
Copy link
Member

What it does

Not explicitly declaring dependencies is being a really bad NPM citizen.

Static tools like `Webpack` might be able to infer dependencies based on
actual imports done from the scripts, but other tools such as
`electron-builder` will fail since they seem to analyze the manifest
files.

This commit does 2 things:

- Add a new script that will check for duplicate dependencies and ensure
that all packages here are using the same ranges. This should minimize
typing issues.
- Add explicit declaration of dependencies, as enforced by the
no-extraenous-dependencies from eslint.

Fixes #7079

How to test

Build and tests should pass, no regressions.

Review checklist

Reminder for reviewers

Copy link
Member

@vince-fugnitto vince-fugnitto left a comment

Choose a reason for hiding this comment

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

I verified the changes by removing a dependency from an ext package.json and confirming that it fails the build. 👍 Please rebase the changes to pick up both #7119, and #6933 (there are extensions present which are deprecated and have been removed).

@vince-fugnitto vince-fugnitto added dependencies pull requests that update a dependency file quality issues related to code and application quality labels Mar 10, 2020
@@ -0,0 +1,85 @@
// @ts-check
Copy link
Member

Choose a reason for hiding this comment

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

theia cli tool has a command to check it, we should use it instead:

.command({
command: 'check:hoisted',
describe: 'check that all dependencies are hoisted',
builder: {
'suppress': {
alias: 's',
describe: 'suppress exiting with failure code',
boolean: true,
default: false
}
},
handler: args => {
try {
checkHoisted(args);
} catch (err) {
console.error(err);
process.exit(1);
}
}
})

It is important, since downstream electron projects should be able to run the same check.

Copy link
Member Author

Choose a reason for hiding this comment

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

The thing is, electron-builder seems to create its own dependency layout when bundling, which would be different from what yarn does.

Example: yarn was correctly hoisting fs-extra, but when bundled it was not. This made the app fail at runtime. The solution was to have whatever extension depending on fs-extra to explicitly declare so, then tooling was able to correctly install things.

My conclusion is that we should not rely on hoisting.

Copy link
Member

@akosyakov akosyakov Mar 10, 2020

Choose a reason for hiding this comment

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

It is not about electron-builder only. Someone develops a product and wants to check whether there is not duplicate dependencies for custom and core extensions then he should run exactly the same script which we run to check duplicate dependencies in this repo. check:hoisted is the script

cc @kittaakos

Copy link
Member Author

Choose a reason for hiding this comment

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

If we want singleton packages, then we would have to deal with peer dependencies

https://classic.yarnpkg.com/blog/2018/04/18/dependencies-done-right/

I might open an issue later to discuss that more in detail, I really think that our current system is too fragile.

Copy link
Member

@akosyakov akosyakov Mar 14, 2020

Choose a reason for hiding this comment

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

I don't really care about peer dependencies. The point is that we don't need 2 scripts doing the same things. Please use check:hoisted. If everything is hoisted it means that there are no duplicates.

Copy link
Contributor

@RomanNikitenko RomanNikitenko left a comment

Choose a reason for hiding this comment

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

It's strange, but I have some problems related to task schema support for this branch.

Actual:
task_schema_actual

Expected:
task_schema_expected

The same problem for settings.json file.
Could someone check it.

thanks in advance!

`@theia/core` and `@theia/filesystem` both used to depend on the same
package, but required different ranges. We want to align most of our
dependencies.

Add a script to fail `yarn prepare` if the same dependency is found with
different ranges within our repository.

Signed-off-by: Paul Maréchal <paul.marechal@ericsson.com>
Not explicitly declaring dependencies is being a really bad NPM citizen.

Static tools like `Webpack` might be able to infer dependencies based on
actual imports done from the scripts, but other tools such as
`electron-builder` will fail since they seem to analyze the manifest
files.

This commit does 2 things:

- Add a new script that will check for duplicate dependencies and ensure
that all packages here are using the same ranges. This should minimize
typing issues.
- Add explicit declaration of dependencies, as enforced by the
no-extraenous-dependencies from eslint.

Signed-off-by: Paul Maréchal <paul.marechal@ericsson.com>
@paul-marechal
Copy link
Member Author

@RomanNikitenko I think it should be fixed now.

Turns out we don't need the resolutions field anymore? Tell me if I missed anything.

@RomanNikitenko RomanNikitenko self-requested a review March 14, 2020 05:07
Copy link
Contributor

@RomanNikitenko RomanNikitenko left a comment

Choose a reason for hiding this comment

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

Tested after update: the bug described above has been fixed

@@ -3,9 +3,14 @@
"version": "0.16.0",
"description": "Theia - Console Extension",
"dependencies": {
"@phosphor/domutils": "1",
Copy link
Member

Choose a reason for hiding this comment

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

Why do we do exact match and don't use caret ranges as we do it usually?

Copy link
Member Author

@paul-marechal paul-marechal Mar 15, 2020

Choose a reason for hiding this comment

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

PhosphorJS is broken up in several bits, and we used to only import one bit and implicitly import the others. If we want to make everything explicit, I was looking for an easy way of declaring it. Just putting 1 means "any version with the major number being 1". This always targets the latest version for major 1, so it is equivalent to ^1.0.0. I don't see the use of being more precise about it, like ^1.2.3, since we mostly want the latest anyway.

Copy link
Member Author

Choose a reason for hiding this comment

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

If PhosphorJS releases a version 2.0.0, Theia will most likely not be compatible without us updating the API used. This to me essentially mean that we are compatible with v1 in a general manner, hence why it is easier to just say 1.

Copy link
Member

Choose a reason for hiding this comment

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

There won't Phosphor.JS 2. It was deprecated and we going to copy relevant bits in @theia/core eventually and inverisfy them.

Copy link
Member

@akosyakov akosyakov left a comment

Choose a reason for hiding this comment

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

I am not sure about it. It does not seem to solve any real issue, but cause a lot of boilerplate and requires scripts to support such boilerplate. It would be also ill advised to redeclare dependencies to inversify.js and phosphor for down stream projects, they have to rely on versions coming with @theia/core always. Otherwise we will break them whenever we bump up versions. It is not acceptable for us, especially after v1.

I think we should rather invest time to create custom linting rules which does not require reduplicating dependencies and can be reused by downstream projects. We have a need for rules not only to avoid duplicate depenencies, see #5873 and #1238

@paul-marechal
Copy link
Member Author

This PR is supposed to fix shady issues like reported in Spectrum: https://spectrum.chat/theia/general/our-theia-electron-builder-app-no-longer-starts~f5cf09a0-6d88-448b-8818-24ad0ec2ee7c?m=MTU3MDcxNjg1OTMwNA==

If we keep things implicit, we'll keep having to dance around whatever yarn is doing. Explicitly entering dependencies removes this kind of issues, since we tell yarn who needs what in order to always meet dependency requirements. Less headaches this way IMO.

@kittaakos kittaakos mentioned this pull request May 6, 2020
1 task
@kittaakos kittaakos mentioned this pull request Feb 26, 2021
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies pull requests that update a dependency file quality issues related to code and application quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

eslint: bring back no-implicit-dependencies rule
4 participants