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

feat(Yarn): Add basic support for Corepack [1]. #8703

Merged

Conversation

oheger-bosch
Copy link
Member

According to the Yarn 2+ documentation, Corepack is the preferred way to install this package manager. If this method is used, the name of the executable has to be determined differently.

Please ensure that your pull request adheres to our contribution guidelines. Thank you!

@oheger-bosch oheger-bosch requested a review from a team as a code owner May 27, 2024 15:50
@oheger-bosch oheger-bosch force-pushed the yarn_corepack_support branch 2 times, most recently from 2119800 to c664182 Compare May 27, 2024 15:58
Copy link

codecov bot commented May 27, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 67.85%. Comparing base (1765a15) to head (b45d3a1).
Report is 21 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##               main    #8703   +/-   ##
=========================================
  Coverage     67.85%   67.85%           
  Complexity     1165     1165           
=========================================
  Files           244      244           
  Lines          7736     7736           
  Branches        865      865           
=========================================
  Hits           5249     5249           
  Misses         2128     2128           
  Partials        359      359           
Flag Coverage Δ
funTest-non-docker 34.17% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

analyzer/src/funTest/kotlin/Yarn2Test.kt Outdated Show resolved Hide resolved
/**
* The name of the option that determines whether Yarn 2+ was installed via Corepack.
*/
const val OPTION_COREPACK_ENABLED = "corepackEnabled"
Copy link
Member

Choose a reason for hiding this comment

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

commit-message: Can you explain why you choose to implement this as an option as opposed to adding detection whether Corepack is enabled? Looking at [1] it says:

 You can quickly check whether Corepack is enabled by
running `yarn exec env`: if you get a path as output, Corepack
 is properly installed. If not, something may be messing with
how the shims are installed.

^[1]: https://yarnpkg.com/corepack

Copy link
Member Author

Choose a reason for hiding this comment

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

See my other comment.

import org.ossreviewtoolkit.model.config.RepositoryConfiguration
import org.ossreviewtoolkit.plugins.packagemanagers.node.Yarn2

class Yarn2Test : WordSpec({
Copy link
Member

Choose a reason for hiding this comment

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

The class should be named Yarn2FunTest.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, IntelliJ has created the class at a completely wrong path. I moved it to the test folder of the Node package manager plugin. It is acutally a unit test.

analyzer/src/funTest/kotlin/Yarn2Test.kt Outdated Show resolved Hide resolved
analyzer/src/funTest/kotlin/Yarn2Test.kt Outdated Show resolved Hide resolved
analyzer/src/funTest/kotlin/Yarn2Test.kt Outdated Show resolved Hide resolved
analyzer/src/funTest/kotlin/Yarn2Test.kt Outdated Show resolved Hide resolved
@@ -157,6 +171,8 @@ class Yarn2(
override fun command(workingDir: File?): String {
if (workingDir == null) return ""

if (options[OPTION_COREPACK_ENABLED].toBoolean()) return DEFAULT_EXECUTABLE_NAME
Copy link
Member

Choose a reason for hiding this comment

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

IMO it would be nicer if this could be (reliably) auto-detected. Does the yarn exec env approach mentioned over here work for that?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is an interesting point, I was also thinking about this, but am not sure how to handle this in the best way. It would also be possible to even go a step further and design the Yarn2 class in a way that it - optionally - executes the corepack enable command, which is required to use Corepack.

My line of thinking was that ORT is rather low-level. It should focus on obtaining the dependencies from package managers and assume that the environment is properly set up. The setup of the environment falls in the responsibility of integrators, e.g. ORT Server. (This is also related to the discussion we had in the last ORT Community meeting.) Now, the integration environment typically knows whether Corepack should be used or not and can directly provide the information to Yarn2; so there is no need to do an additional check.

But I am open for other opinions.

Copy link
Member Author

Choose a reason for hiding this comment

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

Any other opinions or comments on that?

Copy link
Member

Choose a reason for hiding this comment

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

Coincidentally, I've read about Corepack today also in the context of #8715. Could we simply auto-enable the use of Corepack if package.json has the packageManager node?

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, this does not really play well with the API: Whether Corepack is enabled or not affects the command function of Yarn2. However, this function has no obvious way to check the status of Corepack. It is called early in the analysis process to determine the tool version. IIUC, at that time, Yarn2 does not know about the definition files it will have to process.

Copy link
Member

@sschuberth sschuberth May 29, 2024

Choose a reason for hiding this comment

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

Ah, yes, I forgot to reply to that earlier:

My line of thinking was that ORT is rather low-level. It should focus on obtaining the dependencies from package managers and assume that the environment is properly set up.

I'd agree to the second sentence, but not so much to the former. Whenever feasible to detect and apply, ORT should use the correct tools and versions automatically. Just out of pure pragmatism we deviated from this rule of thumb for ecosystems where there's no single defined way to declare the tool version, or bootstrapping the tool (on all supported platform) would be infeasible / too much effort.

Or phrased differently: Development teams that take ORT into use should not be required to configure their tools / version for ORT again if they already did so in their build system, as we'd want to avoid teams to maintain basically the same information in multiple different places. That thinking is also the motivation behind the already linked #8715.

However, whether the auto-detection implementation is feasible needs to be decided on a case-by-case basis. And for this particular Yarn / Corepack case, I'm not yet convinced that it is not feasible.

Copy link
Member Author

Choose a reason for hiding this comment

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

Then I propose the following: The default behavior is to auto-detect whether Corepack is enabled based on the content of the package.json file. But this behavior can be overridden with the configuration property; then this mechanism can be disabled if it is not needed.

Would this be okay?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have changed the implementation accordingly.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks. But I wonder whether we really needs this:

But this behavior can be overridden with the configuration property

IMO too many things in ORT are configurable already, not always with a proven use-case (anymore). So, you do already see a concrete case where one would opt-out of auto-detection, or was the configuration added "just in case"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, for ORT Server (at least our installation), we will probably enable Corepack by default. So, the result of the auto-detection must be overridden. The reason for this is that Corepack does not support other installation options; for instance, it refuses to work with a version of yarn that was installed via the package manager of the OS. This means in our case that if we want to support Corepack, we cannot provide default installations of certain package managers, but must rely on Corepack to do the installation.

@oheger-bosch oheger-bosch force-pushed the yarn_corepack_support branch 2 times, most recently from 843b27a to 53abdfa Compare June 3, 2024 11:08
/**
* The name of the manifest file used by Yarn 2+.
*/
private const val MANIFEST = "package.json"
Copy link
Member

@sschuberth sschuberth Jun 3, 2024

Choose a reason for hiding this comment

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

Maybe prefer MANIFEST_NAME or MANIFEST_FILENAME (but not MANIFEST_FILE_NAME, also see f9c5095).

PS: I was tempted to say that we should use ORT terminology here and call it DEFINITION_FILENAME, but Yarn indeed calls this a manifest (file), so let's stick to that.

Copy link
Member

Choose a reason for hiding this comment

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

Also, to make the introduction of this constant a bit more worthwhile, I'd propose to also use it in line 159.

Copy link
Member

Choose a reason for hiding this comment

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

And one more thing: While the trend has not been started with this PR, we should not continue adding private constants to a companion object. Using a companion object makes sense to scope public constants only.

IMO these should become private top-level constants (some applies to the function), but this can be addressed separately.

@@ -87,6 +88,9 @@ private enum class YarnDependencyType(val type: String) {
* - *disableRegistryCertificateVerification*: If true, the `yarn npm info` commands called by this package manager will
* not verify the server certificate of the HTTPS connection to the NPM registry. This allows to replace the latter by
* a local one, e.g. for intercepting the requests or replaying them.
* - *corepackEnabled*: If true, this implementation assumes that Yarn has been installed via
Copy link
Member

Choose a reason for hiding this comment

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

IMO the name of the property (and also partly the description) is a bit misleading now, as it sounds as if Corepack would only be supported at all if corepackEnabled is set to true.

I'd rather propose to rename this e.g. to corepackOverride or forceCorepack and explain that Corepack support is usually auto-detected, but can be overridden / enforced using this property.

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed the property and reworded the description.

According to the Yarn 2+ documentation, Corepack [1] is the preferred
way to install this package manager. If this method is used, the name
of the executable has to be determined differently.

[1]: https://yarnpkg.com/corepack

Signed-off-by: Oliver Heger <oliver.heger@bosch.io>
@sschuberth sschuberth dismissed fviernau’s stale review June 3, 2024 14:02

Comments addressed.

@sschuberth
Copy link
Member

Test failures are related to outdated Pub tests only, see #8722.

@sschuberth sschuberth merged commit 3e9d8f4 into oss-review-toolkit:main Jun 3, 2024
18 of 20 checks passed
@oheger-bosch oheger-bosch deleted the yarn_corepack_support branch June 3, 2024 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants