Skip to content

Commit

Permalink
fix installing npm, pnpm, and yarn by using corepack and detecting in…
Browse files Browse the repository at this point in the history
…stalled raw version
  • Loading branch information
kbukum1 committed Nov 16, 2024
1 parent 82f8d59 commit 49db410
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 21 deletions.
76 changes: 66 additions & 10 deletions npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def self.yarn_berry?(yarn_lock)
false
end

sig { returns(Integer) }
sig { returns(T.any(Integer, T.noreturn)) }
def self.yarn_major_version
retries = 0
output = run_single_yarn_command("--version")
Expand All @@ -171,6 +171,7 @@ def self.yarn_major_version
handle_subprocess_failure(e)
end

sig { params(error: StandardError).returns(T.noreturn) }
def self.handle_subprocess_failure(error)
message = error.message
if YARN_PATH_NOT_FOUND.match?(message)
Expand Down Expand Up @@ -224,6 +225,7 @@ def self.yarn_4_or_higher?
yarn_major_version >= 4
end

sig { returns(T.nilable(String)) }
def self.setup_yarn_berry
# Always disable immutable installs so yarn's CI detection doesn't prevent updates.
run_single_yarn_command("config set enableImmutableInstalls false")
Expand Down Expand Up @@ -255,29 +257,83 @@ def self.run_yarn_commands(*commands)
commands.each { |cmd, fingerprint| run_single_yarn_command(cmd, fingerprint: fingerprint) }
end

# Setup yarn and run a single yarn command returning stdout/stderr
sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
def self.run_yarn_command(command, fingerprint: nil)
setup_yarn_berry
run_single_yarn_command(command, fingerprint: fingerprint)
end

# Run single npm command returning stdout/stderr.
#
# NOTE: Needs to be explicitly run through corepack to respect the
# `packageManager` setting in `package.json`, because corepack does not
# add shims for NPM.
sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
def self.run_npm_command(command, fingerprint: command)
SharedHelpers.run_shell_command("corepack npm #{command}", fingerprint: "corepack npm #{fingerprint}")
end

# Setup yarn and run a single yarn command returning stdout/stderr
def self.run_yarn_command(command, fingerprint: nil)
setup_yarn_berry
run_single_yarn_command(command, fingerprint: fingerprint)
package_manager_run_command(NpmPackageManager::NAME, command, fingerprint: fingerprint)
end

# Run single pnpm command returning stdout/stderr
sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
def self.run_pnpm_command(command, fingerprint: nil)
SharedHelpers.run_shell_command("pnpm #{command}", fingerprint: "pnpm #{fingerprint || command}")
package_manager_run_command(PNPMPackageManager::NAME, command, fingerprint: fingerprint)
end

# Run single yarn command returning stdout/stderr
sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
def self.run_single_yarn_command(command, fingerprint: nil)
SharedHelpers.run_shell_command("yarn #{command}", fingerprint: "yarn #{fingerprint || command}")
package_manager_run_command(YarnPackageManager::NAME, command, fingerprint: fingerprint)
end

# Install the package manager for specified version by using corepack
# and prepare it for use by using corepack
sig { params(name: String, version: String).void }
def self.install(name, version)
package_manager_install(name, version)
package_manager_activate(name, version)
installed_version = package_manager_version(name)

Dependabot.logger.info("Installed version of #{name}: #{installed_version}")
end

# Install the package manager for specified version by using corepack
sig { params(name: String, version: String).void }
def self.package_manager_install(name, version)
SharedHelpers.run_shell_command(
"corepack install #{name}@#{version} --global --cache-only",
fingerprint: "corepack install <name>@<version> --global --cache-only"
)
end

# Prepare the package manager for use by using corepack
sig { params(name: String, version: String).void }
def self.package_manager_activate(name, version)
SharedHelpers.run_shell_command(
"corepack prepare #{name}@#{version} --activate",
fingerprint: "corepack prepare --activate"
)
end

# Get the version of the package manager by using corepack
sig { params(name: String).returns(String) }
def self.package_manager_version(name)
package_manager_run_command(name, "-v")
end

# Run single command on package manager returning stdout/stderr
sig do
params(
name: String,
command: String,
fingerprint: T.nilable(String)
).returns(String)
end
def self.package_manager_run_command(name, command, fingerprint: nil)
SharedHelpers.run_shell_command(
"corepack #{name} #{command}",
fingerprint: "corepack #{name} #{fingerprint || command}"
)
end
private_class_method :run_single_yarn_command

Expand Down
13 changes: 2 additions & 11 deletions npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,14 @@ def setup(name)
if version
raise_if_unsupported!(name, version)

install(name, version)
Helpers.install(name, version.to_s)
else
version = guessed_version(name)

if version
raise_if_unsupported!(name, version.to_s)

install(name, version) if name == PNPMPackageManager::NAME
Helpers.install(name, version.to_s) if name == PNPMPackageManager::NAME
end
end

Expand Down Expand Up @@ -298,15 +298,6 @@ def raise_if_unsupported!(name, version)
raise ToolVersionNotSupported.new(PNPMPackageManager::NAME.upcase, version, "7.*, 8.*")
end

def install(name, version)
Dependabot.logger.info("Installing \"#{name}@#{version}\"")

SharedHelpers.run_shell_command(
"corepack install #{name}@#{version} --global --cache-only",
fingerprint: "corepack install <name>@<version> --global --cache-only"
)
end

def requested_version(name)
return unless @manifest_package_manager

Expand Down

0 comments on commit 49db410

Please sign in to comment.