class Dependabot::NpmAndYarn::FileUpdater::NpmrcBuilder
Build a .npmrc file from the lockfile content, credentials, and any committed .npmrc
Constants
- CENTRAL_REGISTRIES
- SCOPED_REGISTRY
Attributes
credentials[R]
dependency_files[R]
Public Class Methods
new(dependency_files:, credentials:)
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 18 def initialize(dependency_files:, credentials:) @dependency_files = dependency_files @credentials = credentials end
Public Instance Methods
npmrc_content()
click to toggle source
PROXY WORK
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 24 def npmrc_content initial_content = if npmrc_file then complete_npmrc_from_credentials elsif yarnrc_file then build_npmrc_from_yarnrc else build_npmrc_content_from_lockfile end return initial_content || "" unless registry_credentials.any? ([initial_content] + credential_lines_for_npmrc).compact.join("\n") end
Private Instance Methods
build_npmrc_content_from_lockfile()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 40 def build_npmrc_content_from_lockfile return unless yarn_lock || package_lock return unless global_registry "registry = https://#{global_registry['registry']}\n"\ "#{global_registry_auth_line}"\ "always-auth = true" end
build_npmrc_from_yarnrc()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 119 def build_npmrc_from_yarnrc yarnrc_global_registry = yarnrc_file.content. lines.find { |line| line.match?(/^\s*registry\s/) }&. match(/^\s*registry\s+"(?<registry>[^"]+)"/)&. named_captures&.fetch("registry") return "registry = #{yarnrc_global_registry}\n" if yarnrc_global_registry build_npmrc_content_from_lockfile end
complete_npmrc_from_credentials()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 107 def complete_npmrc_from_credentials initial_content = npmrc_file.content. gsub(/^.*\$\{.*\}.*/, "").strip + "\n" return initial_content unless yarn_lock || package_lock return initial_content unless global_registry initial_content + "registry = https://#{global_registry['registry']}\n"\ "#{global_registry_auth_line}"\ "always-auth = true\n" end
credential_lines_for_npmrc()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 131 def credential_lines_for_npmrc lines = [] registry_credentials.each do |cred| registry = cred.fetch("registry").sub(%r{\/?$}, "/") lines += registry_scopes(registry) if registry_scopes(registry) token = cred.fetch("token", nil) next unless token if token.include?(":") encoded_token = Base64.encode64(token).delete("\n") lines << "//#{registry}:_auth=#{encoded_token}" elsif Base64.decode64(token).ascii_only? && Base64.decode64(token).include?(":") lines << %(//#{registry}:_auth=#{token.delete("\n")}) else lines << "//#{registry}:_authToken=#{token}" end end return lines unless lines.any? { |str| str.include?("auth=") } # Work around a suspected yarn bug ["always-auth = true"] + lines end
dependency_urls()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 82 def dependency_urls return @dependency_urls if defined?(@dependency_urls) @dependency_urls = [] if package_lock @dependency_urls += parsed_package_lock.fetch("dependencies", {}). map { |_, details| details["resolved"] }.compact. select { |url| url.is_a?(String) }. reject { |url| url.start_with?("git") } end if yarn_lock @dependency_urls += yarn_lock.content.scan(/ resolved "(.*?)"/).flatten end # The registry URL for Bintray goes into the lockfile in a # modified format, so we modify it back before checking against # our credentials @dependency_urls = @dependency_urls.map do |url| url.gsub("dl.bintray.com//", "api.bintray.com/npm/") end end
global_registry()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 49 def global_registry # rubocop:disable Metrics/PerceivedComplexity @global_registry ||= registry_credentials.find do |cred| next false if CENTRAL_REGISTRIES.include?(cred["registry"]) # If all the URLs include this registry, it's global next true if dependency_urls.all? { |url| url.include?(cred["registry"]) } # Check if this registry has already been defined in .npmrc as a scoped registry next false if npmrc_scoped_registries.any? { |sr| sr.include?(cred["registry"]) } # If any unscoped URLs include this registry, assume it's global dependency_urls. reject { |u| u.include?("@") || u.include?("%40") }. any? { |url| url.include?(cred["registry"]) } end end
global_registry_auth_line()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 67 def global_registry_auth_line token = global_registry.fetch("token", nil) return "" unless token if token.include?(":") encoded_token = Base64.encode64(token).delete("\n") "_auth = #{encoded_token}\n" elsif Base64.decode64(token).ascii_only? && Base64.decode64(token).include?(":") "_auth = #{token.delete("\n")}\n" else "_authToken = #{token}\n" end end
npmrc_file()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 204 def npmrc_file @npmrc_file ||= dependency_files. find { |f| f.name.end_with?(".npmrc") } end
npmrc_scoped_registries()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 158 def npmrc_scoped_registries return [] unless npmrc_file @npmrc_scoped_registries ||= npmrc_file.content.lines.select { |line| line.match?(SCOPED_REGISTRY) }. map { |line| line.match(SCOPED_REGISTRY)&.named_captures&.fetch("registry") }. compact end
package_lock()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 218 def package_lock @package_lock ||= dependency_files.find { |f| f.name == "package-lock.json" } end
parsed_package_lock()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 200 def parsed_package_lock @parsed_package_lock ||= JSON.parse(package_lock.content) end
registry_credentials()
click to toggle source
rubocop:enable Metrics/PerceivedComplexity
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 196 def registry_credentials credentials.select { |cred| cred.fetch("type") == "npm_registry" } end
registry_scopes(registry)
click to toggle source
rubocop:disable Metrics/PerceivedComplexity
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 168 def registry_scopes(registry) # Central registries don't just apply to scopes return if CENTRAL_REGISTRIES.include?(registry) return unless dependency_urls other_regs = registry_credentials.map { |c| c.fetch("registry") } - [registry] affected_urls = dependency_urls. select do |url| next false unless url.include?(registry) other_regs.none? { |r| r.include?(registry) && url.include?(r) } end scopes = affected_urls.map do |url| url.split(/\%40|@/)[1]&.split(%r{\%2[fF]|/})&.first end # Registry used for unscoped packages return if scopes.include?(nil) scopes.map { |scope| "@#{scope}:registry=https://#{registry}" } end
yarn_lock()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 214 def yarn_lock @yarn_lock ||= dependency_files.find { |f| f.name == "yarn.lock" } end
yarnrc_file()
click to toggle source
# File lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb, line 209 def yarnrc_file @yarnrc_file ||= dependency_files. find { |f| f.name.end_with?(".yarnrc") } end