Skip to content

Commit

Permalink
feat: attempt to resolve exact npm package version from lockfiles for…
Browse files Browse the repository at this point in the history
… constraint checking (shakacode#170)

* feat: attempt to resolve exact npm package version from lockfiles for constraint checking
* fix: adjust version checker failure message
  • Loading branch information
G-Rath authored Aug 15, 2022
1 parent f0f1cb5 commit 291e8e3
Show file tree
Hide file tree
Showing 39 changed files with 58,099 additions and 33 deletions.
81 changes: 72 additions & 9 deletions lib/webpacker/version_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ def raise_if_gem_and_node_package_versions_differ

if !Webpacker.config.ensure_consistent_versioning? && (uses_wildcard || !versions_match)
check_failed = if uses_wildcard
"Semver wildcard detected"
"Semver wildcard without a lockfile detected"
else
"Version mismatch detected"
end

warn <<-MSG.strip_heredoc
Webpacker::VersionChecker - #{check_failed}
You are currently not checking for consistent versions of shakapacker gem and npm package. A version mismatch or usage of semantic versioning wildcard (~ or ^) has been detected.
You are currently not checking for consistent versions of shakapacker gem and npm package. A version mismatch or usage of semantic versioning wildcard (~ or ^) without a lockfile has been detected.
Version mismatch can lead to incorrect behavior and bugs. You should ensure that both the gem and npm package dependencies are locked to the same version.
Expand All @@ -61,9 +61,9 @@ def common_error_msg
Detected: #{node_package_version.raw}
gem: #{gem_version}
Ensure the installed version of the gem is the same as the version of
your installed node package. Do not use >= or ~> in your Gemfile for shakapacker.
Do not use ^ or ~ in your package.json for shakapacker.
Run `yarn add shakapacker --exact` in the directory containing folder node_modules.
your installed node package.
Do not use >= or ~> in your Gemfile for shakapacker without a lockfile.
Do not use ^ or ~ in your package.json for shakapacker without a lockfile.
MSG
end

Expand Down Expand Up @@ -91,20 +91,29 @@ class NodePackageVersion
attr_reader :package_json

def self.build
new(package_json_path)
new(package_json_path, yarn_lock_path, package_lock_path)
end

def self.package_json_path
Rails.root.join("package.json")
end

def initialize(package_json)
def self.yarn_lock_path
Rails.root.join("yarn.lock")
end

def self.package_lock_path
Rails.root.join("package-lock.json")
end

def initialize(package_json, yarn_lock, package_lock)
@package_json = package_json
@yarn_lock = yarn_lock
@package_lock = package_lock
end

def raw
parsed_package_contents = JSON.parse(package_json_contents)
parsed_package_contents.dig("dependencies", "shakapacker").to_s
@raw ||= find_version
end

def semver_wildcard?
Expand Down Expand Up @@ -147,6 +156,60 @@ def github_url?
def package_json_contents
@package_json_contents ||= File.read(package_json)
end

def find_version
if File.exist?(@yarn_lock)
version = from_yarn_lock

return version unless version.nil?
end

if File.exist?(@package_lock)
version = from_package_lock

return version unless version.nil?
end

parsed_package_contents = JSON.parse(package_json_contents)
parsed_package_contents.dig("dependencies", "shakapacker").to_s
end

def from_package_lock
package_lock_contents = File.read(@package_lock)
parsed_lock_contents = JSON.parse(package_lock_contents)

pkg = parsed_lock_contents.dig("packages", "node_modules/shakapacker")
pkg = parsed_lock_contents.dig("dependencies", "shakapacker") if pkg.nil?

pkg&.fetch("version", nil)
end

def from_yarn_lock
found_pkg = false
version = nil
matcher = /\A"?shakapacker@.+:/

File.foreach(@yarn_lock, chomp: true) do |line|
next if line.start_with?("#")

# if we've found the start of the packages details and then come across
# a line that is not indented we've hit the end of the package details
break if found_pkg && !line.start_with?(" ")

if found_pkg
m = line.match(/\A {2}version:? "?(?<package_version>[\w.-]+)"?\z/)

next unless m

version = m[:package_version]
break
end

found_pkg = true if matcher.match(line)
end

version
end
end
end
end
119 changes: 119 additions & 0 deletions test/fixtures/beta_package-lock.v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
{
"name": "test_app",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"requires": {
"argparse": "^2.0.1"
}
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"requires": {
"wrappy": "1"
}
},
"path-complete-extname": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/path-complete-extname/-/path-complete-extname-1.0.0.tgz",
"integrity": "sha512-CVjiWcMRdGU8ubs08YQVzhutOR5DEfO97ipRIlOGMK5Bek5nQySknBpuxVAVJ36hseTNs+vdIcv57ZrWxH7zvg=="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
},
"right-pad": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/right-pad/-/right-pad-1.0.1.tgz",
"integrity": "sha512-bYBjgxmkvTAfgIYy328fmkwhp39v8lwVgWhhrzxPV3yHtcSqyYKe9/XOhvW48UFjATg3VuJbpsp5822ACNvkmw==",
"dev": true
},
"shakapacker": {
"version": "6.1.0-beta.0",
"resolved": "https://registry.npmjs.org/shakapacker/-/shakapacker-6.1.0-beta.0.tgz",
"integrity": "sha512-SakBrvrL1x4Y/H1pc40P+rgQDIv54wnuGVflClHEIzCbPI6uQ7ehlgiropXjVkRX9495yCGGgqnXeEAihdJ4dg==",
"requires": {
"glob": "^7.2.0",
"js-yaml": "^4.1.0",
"path-complete-extname": "^1.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
}
}
Loading

0 comments on commit 291e8e3

Please sign in to comment.