package-audit 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d30d08ba36373c75427371f922cb0a5819a021868bf82001428e0541571df9f8
4
- data.tar.gz: ac4dce54e3905dd56de9b137a62101de7267262c1f6b0310e4697c8f016a36b8
3
+ metadata.gz: 4c2f009e294663828a3055ac8b8facb3106251875a240f9abf74754747102cef
4
+ data.tar.gz: 0a11812a839205caa7793c5b34baf31006438b020e9f535ffe1fd5b3ee0333ab
5
5
  SHA512:
6
- metadata.gz: 00be4151f4f124614d117a739a558f9f2816f0f72095f222ddadf5101a6d089b40bdc5369c4a68c9b096b1547932561394f1fee5ca58712e13a4909c4a8c9558
7
- data.tar.gz: f224c2c2fe2ff39586d20989ef6999d7b2a52acd2276dcdd9895441105ccaebc5991523676b88545a5afa96d4ffcac10291ab76dfab735b65d42aabc4598d7e4
6
+ metadata.gz: 7e7a294008ddcb510e8335193ac013447c38b27a71f440325ae2221f5bd0dea29bf714a88e6089b451d50c64f24964da04215c5e54c74c0729fa37a3f277d44b
7
+ data.tar.gz: 29bb2f4dbef1bb9a6c38eb7d4b17c9aa299f943916765d05a02b14b8f48a0e8ce212bc834e4657285b99d9ba0eb33c80df479e907b673f13fa6834c098e8649e
@@ -15,6 +15,9 @@ module Package
15
15
  class_option Enum::Option::CONFIG,
16
16
  aliases: '-c', banner: 'FILE',
17
17
  desc: "Path to a custom configuration file, default: #{Const::File::CONFIG})"
18
+ class_option Enum::Option::ENVIRONMENT,
19
+ aliases: '-e', repeatable: true,
20
+ desc: 'Environment to be audited (repeat this flag for each environment)'
18
21
  class_option Enum::Option::TECHNOLOGY,
19
22
  aliases: '-t', repeatable: true,
20
23
  desc: 'Technology to be audited (repeat this flag for each technology)'
@@ -14,15 +14,13 @@ module Package
14
14
  risk_explanation
15
15
  ]
16
16
 
17
- ALL = %i[name version latest_version latest_version_date groups vulnerabilities risk_type risk_explanation]
18
- DEPRECATED = %i[name version latest_version latest_version_date groups]
19
- OUTDATED = %i[name version latest_version latest_version_date groups]
20
- VULNERABLE = %i[name version latest_version groups vulnerabilities]
17
+ DEFAULT = %i[name version latest_version latest_version_date groups vulnerabilities risk_type risk_explanation]
21
18
 
22
19
  # the names of these fields must match the instance variables in the Dependency class
23
20
  HEADERS = {
24
21
  name: 'Package',
25
22
  version: 'Version',
23
+ version_date: 'Version Date',
26
24
  latest_version: 'Latest',
27
25
  latest_version_date: 'Latest Date',
28
26
  groups: 'Groups',
@@ -2,11 +2,15 @@ module Package
2
2
  module Audit
3
3
  module Enum
4
4
  module Environment
5
- DEV = :development
6
- TEST = :test
7
- STAGING = :staging
8
- PRODUCTION = :production
9
- DEFAULT = :default
5
+ DEV = 'development'
6
+ TEST = 'test'
7
+ STAGING = 'staging'
8
+ PRODUCTION = 'production'
9
+ DEFAULT = 'default'
10
+
11
+ def self.all
12
+ constants.map { |key| Enum::Environment.const_get(key) }.sort
13
+ end
10
14
  end
11
15
  end
12
16
  end
@@ -5,6 +5,7 @@ module Package
5
5
  CONFIG = 'config'
6
6
  CSV = 'csv'
7
7
  CSV_EXCLUDE_HEADERS = 'exclude-headers'
8
+ ENVIRONMENT = 'environment'
8
9
  INCLUDE_IGNORED = 'include-ignored'
9
10
  TECHNOLOGY = 'technology'
10
11
  end
@@ -11,17 +11,23 @@ module Package
11
11
  @packages = packages
12
12
  end
13
13
 
14
- def fetch
14
+ def fetch # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
15
15
  threads = @packages.map do |package|
16
16
  Thread.new do
17
17
  response = Net::HTTP.get_response(URI.parse("#{REGISTRY_URL}/#{package.name}"))
18
- raise response.error unless response.is_a?(Net::HTTPSuccess)
18
+ raise "Unable to fetch meta data for #{package.name} from #{REGISTRY_URL} (#{response.class})" unless
19
+ response.is_a?(Net::HTTPSuccess)
19
20
 
20
21
  json_package = JSON.parse(response.body, symbolize_names: true)
21
22
  update_meta_data(package, json_package)
23
+ rescue StandardError => e
24
+ Thread.current[:exception] = e
22
25
  end
23
26
  end
24
- threads.each(&:join)
27
+ threads.each do |thread|
28
+ thread.join
29
+ raise thread[:exception] if thread[:exception]
30
+ end
25
31
  @packages
26
32
  end
27
33
 
@@ -36,7 +36,7 @@ module Package
36
36
 
37
37
  @vuln_hash[full_name] = Package.new(name, version, 'node') unless @vuln_hash.key? full_name
38
38
  @vuln_hash[full_name].update vulnerabilities: @vuln_hash[full_name].vulnerabilities + [vulnerability]
39
- @vuln_hash[full_name].update groups: @pkg_hash[parent_name].groups
39
+ @vuln_hash[full_name].update groups: @pkg_hash[parent_name].groups.map(&:to_s)
40
40
  end
41
41
  end
42
42
  end
@@ -1,3 +1,5 @@
1
+ require_relative '../enum/environment'
2
+
1
3
  module Package
2
4
  module Audit
3
5
  module Npm
@@ -7,13 +9,17 @@ module Package
7
9
  @yarn_lock_path = yarn_lock_path
8
10
  end
9
11
 
10
- def fetch(default_deps, dev_deps)
12
+ def fetch(default_deps, dev_deps) # rubocop:disable Metrics/MethodLength
11
13
  pkgs = []
12
14
  default_deps.merge(dev_deps).each do |dep_name, expected_version|
13
15
  pkg_block = fetch_package_block(dep_name, expected_version)
14
16
  version = fetch_package_version(dep_name, pkg_block)
15
17
  pks = Package.new(dep_name.to_s, version, 'node')
16
- pks.update groups: dev_deps.key?(dep_name) ? %i[development] : %i[default development]
18
+ pks.update groups: if dev_deps.key?(dep_name)
19
+ [Enum::Environment::DEV]
20
+ else
21
+ [Enum::Environment::DEFAULT, Enum::Environment::DEV]
22
+ end
17
23
  pkgs << pks
18
24
  end
19
25
  pkgs
@@ -22,7 +28,7 @@ module Package
22
28
  private
23
29
 
24
30
  def fetch_package_block(dep_name, expected_version)
25
- regex = /#{Regexp.escape(dep_name)}@#{Regexp.escape(expected_version)}.*?:.*?(\n\n|\z)/m
31
+ regex = regex_pattern_for_package(dep_name, expected_version)
26
32
  blocks = @yarn_lock_file.match(regex)
27
33
  if blocks.nil? || blocks[0].nil?
28
34
  raise NoMatchingPatternError, "Unable to find \"#{dep_name}\" in #{@yarn_lock_path}"
@@ -40,6 +46,17 @@ module Package
40
46
 
41
47
  version || '0.0.0.0'
42
48
  end
49
+
50
+ def regex_pattern_for_package(dep_name, version)
51
+ # assume the package name is prefixed by a space, a quote or be the first thing on the line
52
+ # there can be multiple comma-separated versions on the same line with or without quotes
53
+ # Here are some examples of strings that would be matched:
54
+ # - aria-query@^5.0.0:
55
+ # - lodash@^4.17.15, lodash@^4.17.20:
56
+ # - "@adobe/css-tools@^4.0.1":
57
+ # - "@babel/runtime@^7.23.1", "@babel/runtime@^7.9.2":
58
+ /(?:^|[ "])#{Regexp.escape(dep_name)}@#{Regexp.escape(version)}.*?:.*?(\n\n|\z)/m
59
+ end
43
60
  end
44
61
  end
45
62
  end
@@ -31,27 +31,27 @@ module Package
31
31
  specs = BundlerSpecs.gemfile(@dir)
32
32
  pkgs = specs.map { |spec| Package.new(spec.name, spec.version, Enum::Technology::RUBY) }
33
33
  vulnerable_pkgs = VulnerabilityFinder.new(@dir).run
34
- pkgs = GemMetaData.new(pkgs + vulnerable_pkgs).fetch.filter(&:risk?)
34
+ pkgs = GemMetaData.new(@dir, pkgs + vulnerable_pkgs).fetch.filter(&:risk?)
35
35
  DuplicatePackageMerger.new(pkgs).run
36
36
  end
37
37
 
38
38
  def deprecated
39
39
  specs = BundlerSpecs.gemfile(@dir)
40
40
  pkgs = specs.map { |spec| Package.new(spec.name, spec.version, Enum::Technology::RUBY) }
41
- pkgs = GemMetaData.new(pkgs).fetch.filter(&:deprecated?)
41
+ pkgs = GemMetaData.new(@dir, pkgs).fetch.filter(&:deprecated?)
42
42
  DuplicatePackageMerger.new(pkgs).run
43
43
  end
44
44
 
45
45
  def outdated(include_implicit: false)
46
46
  specs = include_implicit ? BundlerSpecs.all(@dir) : BundlerSpecs.gemfile(@dir)
47
47
  pkgs = specs.map { |spec| Package.new(spec.name, spec.version, Enum::Technology::RUBY) }
48
- pkgs = GemMetaData.new(pkgs).fetch.filter(&:outdated?)
48
+ pkgs = GemMetaData.new(@dir, pkgs).fetch.filter(&:outdated?)
49
49
  DuplicatePackageMerger.new(pkgs).run
50
50
  end
51
51
 
52
52
  def vulnerable
53
53
  pkgs = VulnerabilityFinder.new(@dir).run
54
- pkgs = GemMetaData.new(pkgs).fetch.filter(&:vulnerable?)
54
+ pkgs = GemMetaData.new(@dir, pkgs).fetch.filter(&:vulnerable?)
55
55
  DuplicatePackageMerger.new(pkgs).run
56
56
  end
57
57
  end
@@ -4,7 +4,8 @@ module Package
4
4
  module Audit
5
5
  module Ruby
6
6
  class GemMetaData
7
- def initialize(pkgs)
7
+ def initialize(dir, pkgs)
8
+ @dir = dir
8
9
  @pkgs = pkgs
9
10
  @gem_hash = {}
10
11
  end
@@ -45,12 +46,16 @@ module Package
45
46
  end
46
47
 
47
48
  def assign_groups # rubocop:disable Metrics/AbcSize
48
- definition = Bundler.definition
49
+ definition = Bundler::Definition.build Pathname("#{@dir}/Gemfile"), Pathname("#{@dir}/Gemfile.lock"), nil
50
+ Bundler.ui.level = 'error'
51
+ definition.resolve_remotely!
49
52
  groups = definition.groups.uniq.sort
50
53
  groups.each do |group|
51
54
  specs = definition.specs_for([group])
52
55
  specs.each do |spec|
53
- @gem_hash[spec.name].update(groups: @gem_hash[spec.name].groups | [group]) if @gem_hash.key? spec.name
56
+ if @gem_hash.key? spec.name
57
+ @gem_hash[spec.name].update(groups: (@gem_hash[spec.name].groups | [group]).map(&:to_s))
58
+ end
54
59
  end
55
60
  end
56
61
  end
@@ -4,6 +4,7 @@ require_relative '../enum/option'
4
4
  require_relative '../enum/report'
5
5
  require_relative '../technology/detector'
6
6
  require_relative '../technology/validator'
7
+ require_relative '../util/spinner'
7
8
  require_relative '../util/summary_printer'
8
9
  require_relative 'package_finder'
9
10
  require_relative 'package_printer'
@@ -18,26 +19,46 @@ module Package
18
19
  @options = options
19
20
  @report = report
20
21
  @config = parse_config_file
22
+ @environments = parse_environments
21
23
  @technologies = parse_technologies
24
+ @spinner = Util::Spinner.new('Evaluating packages and their dependencies...')
22
25
  end
23
26
 
24
- def run
27
+ def run # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
28
+ mutex = Mutex.new
25
29
  cumulative_pkgs = []
30
+ thread_index = 0
26
31
 
27
- @technologies.each do |technology|
28
- all_pkgs, ignored_pkgs = PackageFinder.new(@config, @dir, @report).run(technology)
29
- ignored_pkgs = [] if @options[Enum::Option::INCLUDE_IGNORED]
30
- cumulative_pkgs << all_pkgs
31
- print_results(technology, (all_pkgs || []) - (ignored_pkgs || []), ignored_pkgs || [])
32
+ @spinner.start
33
+ threads = @technologies.map.with_index do |technology, technology_index|
34
+ Thread.new do
35
+ all_pkgs, ignored_pkgs = PackageFinder.new(@config, @dir, @report, @environments).run(technology)
36
+ ignored_pkgs = [] if @options[Enum::Option::INCLUDE_IGNORED]
37
+ cumulative_pkgs += all_pkgs || []
38
+ sleep 0.1 while technology_index != thread_index # print each technology in order
39
+ mutex.synchronize do
40
+ @spinner.stop
41
+ print_results(technology, (all_pkgs || []) - (ignored_pkgs || []), ignored_pkgs || [])
42
+ thread_index += 1
43
+ @spinner.start
44
+ end
45
+ rescue StandardError => e
46
+ Thread.current[:exception] = e
47
+ end
32
48
  end
33
-
34
- cumulative_pkgs.any?
49
+ threads.each do |thread|
50
+ thread.join
51
+ raise thread[:exception] if thread[:exception]
52
+ end
53
+ cumulative_pkgs.any? ? 1 : 0
54
+ ensure
55
+ @spinner.stop
35
56
  end
36
57
 
37
58
  private
38
59
 
39
60
  def print_results(technology, pkgs, ignored_pkgs)
40
- PackagePrinter.new(@options, pkgs).print(report_fields)
61
+ PackagePrinter.new(@options, pkgs).print(Const::Fields::DEFAULT)
41
62
  print_summary(technology, pkgs, ignored_pkgs) unless @options[Enum::Option::CSV]
42
63
  print_disclaimer(technology) unless @options[Enum::Option::CSV] || pkgs.empty?
43
64
  end
@@ -70,19 +91,6 @@ module Package
70
91
  end
71
92
  end
72
93
 
73
- def report_fields
74
- case @report
75
- when Enum::Report::DEPRECATED
76
- Const::Fields::DEPRECATED
77
- when Enum::Report::OUTDATED
78
- Const::Fields::OUTDATED
79
- when Enum::Report::VULNERABLE
80
- Const::Fields::VULNERABLE
81
- else
82
- Const::Fields::ALL
83
- end
84
- end
85
-
86
94
  def parse_config_file
87
95
  if @options[Enum::Option::CONFIG].nil?
88
96
  YAML.load_file("#{@dir}/#{Const::File::CONFIG}") if File.exist? "#{@dir}/#{Const::File::CONFIG}"
@@ -93,6 +101,17 @@ module Package
93
101
  end
94
102
  end
95
103
 
104
+ def parse_environments
105
+ unsupported_technologies = (@options[Enum::Option::ENVIRONMENT] || []) - Enum::Environment.all
106
+
107
+ if unsupported_technologies.any?
108
+ raise ArgumentError, "#{unsupported_technologies} is not valid list of environments, " \
109
+ "use one of #{Enum::Environment.all}"
110
+ end
111
+
112
+ (@options[Enum::Option::ENVIRONMENT] || Enum::Environment.all) | [Enum::Environment::DEFAULT]
113
+ end
114
+
96
115
  def parse_technologies
97
116
  technology_validator = Technology::Validator.new(@dir)
98
117
  @options[Enum::Option::TECHNOLOGY]&.each { |technology| technology_validator.validate! technology }
@@ -11,16 +11,19 @@ require 'yaml'
11
11
  module Package
12
12
  module Audit
13
13
  class PackageFinder
14
- def initialize(config, dir, report)
14
+ def initialize(config, dir, report, environments)
15
15
  @config = config
16
16
  @dir = dir
17
17
  @report = report
18
+ @environments = environments
18
19
  end
19
20
 
20
21
  def run(technology)
21
22
  all_pkgs = find_by_technology(technology)
22
- ignored_pkgs = filter_pkgs_based_on_config(all_pkgs)
23
- [all_pkgs, ignored_pkgs]
23
+ ignored_by_environment_pkgs = filter_pkgs_based_on_environment(all_pkgs)
24
+ active_pkgs = all_pkgs - ignored_by_environment_pkgs
25
+ ignored_by_config_pkgs = filter_pkgs_based_on_config(active_pkgs)
26
+ [active_pkgs, ignored_by_config_pkgs]
24
27
  end
25
28
 
26
29
  private
@@ -53,6 +56,15 @@ module Package
53
56
  end
54
57
  ignored_pkgs
55
58
  end
59
+
60
+ def filter_pkgs_based_on_environment(pkgs)
61
+ ignored_pkgs = []
62
+
63
+ pkgs.each do |pkg|
64
+ ignored_pkgs << pkg unless (pkg.groups & @environments).any?
65
+ end
66
+ ignored_pkgs
67
+ end
56
68
  end
57
69
  end
58
70
  end
@@ -32,14 +32,14 @@ module Package
32
32
  private
33
33
 
34
34
  def check_fields(fields)
35
- return unless (fields - Const::Fields::ALL).any?
35
+ return unless (fields - Const::Fields::DEFAULT).any?
36
36
 
37
37
  raise ArgumentError,
38
- "#{fields - Const::Fields::ALL} are not valid field names. " \
39
- "Available fields names are: #{Const::Fields::ALL}."
38
+ "#{fields - Const::Fields::DEFAULT} are not valid field names. " \
39
+ "Available fields names are: #{Const::Fields::DEFAULT}."
40
40
  end
41
41
 
42
- def pretty(fields = Const::Fields::ALL) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
42
+ def pretty(fields = Const::Fields::DEFAULT) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
43
43
  # find the maximum length of each field across all the packages so we know how many
44
44
  # characters of horizontal space to allocate for each field when printing
45
45
  fields.each do |key|
@@ -16,7 +16,7 @@ module Package
16
16
  unless production_dependency?
17
17
  risks.each_with_index do |risk, index|
18
18
  risks[index] =
19
- [risk, Risk.new(Enum::RiskType::MEDIUM, risk.explanation)].min || Risk.new(Enum::RiskType::NONE)
19
+ [risk, Risk.new(Enum::RiskType::LOW, risk.explanation)].min || Risk.new(Enum::RiskType::NONE)
20
20
  end
21
21
  end
22
22
  risks
@@ -0,0 +1,48 @@
1
+ module Package
2
+ module Audit
3
+ module Util
4
+ class Spinner
5
+ ANIMATION_SPEED = 0.1
6
+ STATES = %w[| / - \\]
7
+
8
+ def initialize(message = 'Loading...')
9
+ @message = message
10
+ @running = false
11
+ @thread = nil
12
+ end
13
+
14
+ def start # rubocop:disable Metrics/MethodLength
15
+ return if ENV['RACK_ENV'] == 'test'
16
+ raise 'Loading indicator already started.' if @running
17
+
18
+ @running = true
19
+ @thread = Thread.new do
20
+ step = 0
21
+ while @running
22
+ if @running && (ENV['RUBY_ENV'] != 'test' && ENV['RACK_ENV'] != 'test')
23
+ print "\r#{@message} #{STATES[step % STATES.length]}"
24
+ end
25
+ sleep ANIMATION_SPEED
26
+ step += 1
27
+ end
28
+ end
29
+ end
30
+
31
+ def stop
32
+ return if ENV['RACK_ENV'] == 'test'
33
+ return unless @running
34
+
35
+ @running = false
36
+ @thread&.join
37
+ clear_console_line
38
+ end
39
+
40
+ private
41
+
42
+ def clear_console_line
43
+ print "\r#{' ' * (@message.length + 2)}\r"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -85,7 +85,7 @@ module Package
85
85
 
86
86
  puts Util::BashColor.blue('5. Check whether the package is used in production or not.')
87
87
  puts ' If a package is limited to a non-production environment:'
88
- puts " - cap risk severity to\t -> #{Util::BashColor.orange('medium')} risk"
88
+ puts " - cap risk severity to\t -> #{Util::BashColor.yellow('low')} risk"
89
89
  end
90
90
  end
91
91
  end
@@ -1,5 +1,5 @@
1
1
  module Package
2
2
  module Audit
3
- VERSION = '0.4.0'
3
+ VERSION = '0.5.0'
4
4
  end
5
5
  end
@@ -2,12 +2,9 @@ module Package
2
2
  module Audit
3
3
  module Const
4
4
  module Fields
5
- ALL: Array[Symbol]
6
5
  AVAILABLE: Array[Symbol]
7
- DEPRECATED: Array[Symbol]
6
+ DEFAULT: Array[Symbol]
8
7
  HEADERS: Hash[Symbol, String]
9
- OUTDATED: Array[Symbol]
10
- VULNERABLE: Array[Symbol]
11
8
  end
12
9
  end
13
10
  end
@@ -2,11 +2,13 @@ module Package
2
2
  module Audit
3
3
  module Enum
4
4
  module Environment
5
- DEFAULT: Symbol
6
- DEV: Symbol
7
- PRODUCTION: Symbol
8
- STAGING: Symbol
9
- TEST: Symbol
5
+ DEFAULT: String
6
+ DEV: String
7
+ PRODUCTION: String
8
+ STAGING: String
9
+ TEST: String
10
+
11
+ def self.all: -> Array[String]
10
12
  end
11
13
  end
12
14
  end
@@ -5,6 +5,7 @@ module Package
5
5
  CONFIG: String
6
6
  CSV: String
7
7
  CSV_EXCLUDE_HEADERS: String
8
+ ENVIRONMENT: String
8
9
  INCLUDE_IGNORED: String
9
10
  TECHNOLOGY: String
10
11
  end
@@ -1,12 +1,12 @@
1
1
  module Package
2
2
  module Audit
3
3
  class Package
4
- @groups: Array[Symbol]
4
+ @groups: Array[String]
5
5
  @risks: Array[Risk]
6
6
  @technology: String
7
7
  @vulnerabilities: Array[String]
8
8
 
9
- attr_accessor groups: Array[Symbol]
9
+ attr_accessor groups: Array[String]
10
10
  attr_accessor latest_version: String
11
11
  attr_accessor latest_version_date: String
12
12
  attr_reader name: String
@@ -14,6 +14,8 @@ module Package
14
14
  def fetch_package_block: (Symbol, String) -> String
15
15
 
16
16
  def fetch_package_version: (Symbol, String) -> String
17
+
18
+ def regex_pattern_for_package: (Symbol, String) -> Regexp
17
19
  end
18
20
  end
19
21
  end
@@ -2,10 +2,11 @@ module Package
2
2
  module Audit
3
3
  module Ruby
4
4
  class GemMetaData
5
+ @dir: String
5
6
  @gem_hash: Hash[String, Package]
6
7
  @pkgs: Array[Package]
7
8
 
8
- def initialize: (Array[Package]) -> void
9
+ def initialize: (String, Array[Package]) -> void
9
10
 
10
11
  def fetch: -> Array[Package]
11
12
 
@@ -3,13 +3,15 @@ module Package
3
3
  class CommandParser
4
4
  @config: Hash[String, untyped]?
5
5
  @dir: String
6
+ @environments: Array[String]
7
+ @spinner: Util::Spinner
6
8
  @options: Hash[String, untyped]
7
9
  @report: Symbol
8
10
  @technologies: Array[String]
9
11
 
10
12
  def initialize: (String, Hash[String, untyped], Symbol) -> void
11
13
 
12
- def run: -> bool
14
+ def run: -> int
13
15
 
14
16
  private
15
17
 
@@ -17,6 +19,8 @@ module Package
17
19
 
18
20
  def parse_config_file: -> Hash[String, untyped]?
19
21
 
22
+ def parse_environments: -> Array[String]
23
+
20
24
  def parse_technologies: -> Array[String]
21
25
 
22
26
  def print_disclaimer: (String) -> void
@@ -24,8 +28,6 @@ module Package
24
28
  def print_results: (String, Array[Package], Array[Package]) -> void
25
29
 
26
30
  def print_summary: (String, Array[Package], Array[Package]) -> void
27
-
28
- def report_fields: -> Array[Symbol]
29
31
  end
30
32
  end
31
33
  end
@@ -4,8 +4,9 @@ module Package
4
4
  @config: Hash[String, untyped]?
5
5
  @dir: String
6
6
  @report: Symbol
7
+ @environments: Array[String]
7
8
 
8
- def initialize: (Hash[String, untyped]?, String, Symbol) -> void
9
+ def initialize: (Hash[String, untyped]?, String, Symbol, Array[String]) -> void
9
10
 
10
11
  def run: (String) -> Array[Array[Package]]
11
12
 
@@ -13,6 +14,8 @@ module Package
13
14
 
14
15
  def filter_pkgs_based_on_config: (Array[Package]) -> Array[Package]
15
16
 
17
+ def filter_pkgs_based_on_environment: (Array[Package]) -> Array[Package]
18
+
16
19
  def find_by_technology: (String) -> Array[Package]
17
20
 
18
21
  def find_node: -> Array[Package]
@@ -0,0 +1,24 @@
1
+ module Package
2
+ module Audit
3
+ module Util
4
+ class Spinner
5
+ ANIMATION_SPEED: Float
6
+ STATES: Array[String]
7
+
8
+ @message: String
9
+ @running: bool
10
+ @thread: Thread?
11
+
12
+ def initialize: (?String) -> void
13
+
14
+ def start: -> void
15
+
16
+ def stop: -> void
17
+
18
+ private
19
+
20
+ def clear_console_line: -> void
21
+ end
22
+ end
23
+ end
24
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: package-audit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
- - Vadim Kononov
7
+ - Tactica Communications Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-11 00:00:00.000000000 Z
11
+ date: 2023-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler-audit
@@ -85,6 +85,7 @@ files:
85
85
  - lib/package/audit/technology/detector.rb
86
86
  - lib/package/audit/technology/validator.rb
87
87
  - lib/package/audit/util/bash_color.rb
88
+ - lib/package/audit/util/spinner.rb
88
89
  - lib/package/audit/util/summary_printer.rb
89
90
  - lib/package/audit/version.rb
90
91
  - sig/package/audit/cli.rbs
@@ -124,6 +125,7 @@ files:
124
125
  - sig/package/audit/technology/detector.rbs
125
126
  - sig/package/audit/technology/validator.rbs
126
127
  - sig/package/audit/util/bash_color.rbs
128
+ - sig/package/audit/util/spinner.rbs
127
129
  - sig/package/audit/util/summary_printer.rbs
128
130
  - sig/package/audit/version.rbs
129
131
  homepage: https://github.com/tactica/package-audit
@@ -148,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
150
  - !ruby/object:Gem::Version
149
151
  version: '0'
150
152
  requirements: []
151
- rubygems_version: 3.4.12
153
+ rubygems_version: 3.4.22
152
154
  signing_key:
153
155
  specification_version: 4
154
156
  summary: A helper tool to find outdated, deprecated and vulnerable dependencies.