rubion 0.3.16 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1749851afa6f0075dc159a4f4d406a6c1900d8404eaf61fc4737d9d350deb3d7
4
- data.tar.gz: c59e82269f8e505a62c9fdd54141547ccd67d0ee72ceb139a47d65fb02627293
3
+ metadata.gz: 25866a240d194626328073cc8f0e78b970dd1e8389563f8a2a636a23ccc545e3
4
+ data.tar.gz: bc7061c95fe6a24fd7cc464bf3671f26bc9d1a53eb248512d7b15c1c67efdbf6
5
5
  SHA512:
6
- metadata.gz: b842fac77f18bfbbd548a2a7ae43f6f98022a47c2c2ad4678e755349c712ffb4ec6c27404b7b7b6c4ed6719e4b65d3bd9f66aa44f4adefb9b3f8681b387cb2ca
7
- data.tar.gz: 1fcc0c42ca646da4ecd88b178969663a4b45b79d1c95657dfe0f5948e293b49fb4042b9e0b710e42a62b8832050266e662b7366c02b433ca8aeeb80c8a5cb746
6
+ metadata.gz: aa33bfe89c56497e77cb63b9e518fe4f57673c53440971ee50b3ebe56f82f83ea39af26e74b5bd3e38036ef85270be2a778b900afce56027234e50c80acb7603
7
+ data.tar.gz: 536c26c682881e1516baeeb9833214fb3a761fa0c65df777961d434da28a4e4ba5a39c6e6013251e3b27a6baca3ba9b424e7465282832ed298d061564c859959
@@ -125,14 +125,17 @@ module Rubion
125
125
  def check_gem_versions
126
126
  stdout, stderr, status = Open3.capture3('bundle outdated --parseable', chdir: @project_path)
127
127
 
128
- if status.success?
129
- # Command succeeded - parse output (may be empty if all gems are up to date)
128
+ # bundle outdated returns exit code 1 when outdated gems are found (expected behavior)
129
+ # Exit code 0 means no outdated gems or command succeeded
130
+ # Exit code 1 means outdated gems found - this is success, not an error
131
+ if status.success? || status.exitstatus == 1
132
+ # Command succeeded or outdated gems found - parse output
130
133
  parse_bundle_outdated_output(stdout)
131
134
  elsif status.exitstatus.nil?
132
135
  # Command not found or failed to execute
133
136
  raise "bundle outdated command failed or is not available. Error: #{stderr}"
134
137
  else
135
- # Command failed with non-zero exit code
138
+ # Command failed with unexpected non-zero exit code
136
139
  raise "bundle outdated failed with exit code #{status.exitstatus}. Output: #{stdout}#{unless stderr.empty?
137
140
  "\nError: #{stderr}"
138
141
  end}"
@@ -148,16 +151,26 @@ module Rubion
148
151
  if status.exitstatus.nil?
149
152
  # Command not found or failed to execute
150
153
  raise "#{@package_manager} audit command failed or is not available. Error: #{stderr}"
151
- elsif !status.success? && status.exitstatus != 1
152
- # Exit code 1 is expected when vulnerabilities are found, other non-zero codes are errors
154
+ elsif @package_manager == 'npm' && !status.success? && status.exitstatus != 1
155
+ # For npm, exit code 1 means vulnerabilities were found; any other non-zero code is an error
153
156
  raise "#{@package_manager} audit failed with exit code #{status.exitstatus}. Output: #{stdout}#{unless stderr.empty?
154
157
  "\nError: #{stderr}"
155
158
  end}"
159
+ elsif @package_manager == 'yarn' && !status.success?
160
+ # For Yarn (classic), any non-zero exit code is a bitmask of severities:
161
+ # 1=info, 2=low, 4=moderate, 8=high, 16=critical. The exit code is the sum of severities found.
162
+ # Non-zero here indicates vulnerabilities were found; we'll still try to parse the JSON output below.
163
+ # Do not raise here so that vulnerabilities are handled gracefully.
156
164
  end
157
165
 
158
166
  begin
159
- data = JSON.parse(stdout)
160
- parse_npm_audit_output(data)
167
+ # Yarn audit outputs JSON line by line, need to parse each line
168
+ if @package_manager == 'yarn'
169
+ parse_yarn_audit_output(stdout)
170
+ else
171
+ data = JSON.parse(stdout)
172
+ parse_npm_audit_output(data)
173
+ end
161
174
  rescue JSON::ParserError => e
162
175
  raise "Failed to parse #{@package_manager} audit JSON output: #{e.message}. Raw output: #{stdout}"
163
176
  end
@@ -364,6 +377,55 @@ module Rubion
364
377
  @result.package_vulnerabilities = vulnerabilities
365
378
  end
366
379
 
380
+ def parse_yarn_audit_output(output)
381
+ vulnerabilities = []
382
+ seen_advisories = {}
383
+
384
+ # Yarn audit outputs JSON line by line
385
+ output.each_line do |line|
386
+ next if line.strip.empty?
387
+
388
+ begin
389
+ json_obj = JSON.parse(line)
390
+ next unless json_obj.is_a?(Hash)
391
+
392
+ # Parse auditAdvisory type
393
+ if json_obj['type'] == 'auditAdvisory' && json_obj['data'] && json_obj['data']['advisory']
394
+ advisory = json_obj['data']['advisory']
395
+ advisory_id = advisory['id']
396
+
397
+ # Skip if we've already seen this advisory
398
+ next if seen_advisories[advisory_id]
399
+
400
+ seen_advisories[advisory_id] = true
401
+
402
+ # Extract package name and version from findings
403
+ if advisory['findings'] && advisory['findings'].is_a?(Array) && advisory['findings'].first
404
+ finding = advisory['findings'].first
405
+ version = finding['version'] || 'unknown'
406
+ else
407
+ version = 'unknown'
408
+ end
409
+
410
+ # Get severity (yarn uses lowercase)
411
+ severity = (advisory['severity'] || 'unknown').downcase
412
+
413
+ vulnerabilities << {
414
+ package: advisory['module_name'] || 'unknown',
415
+ version: version,
416
+ severity: severity,
417
+ title: advisory['title'] || advisory['overview'] || 'Vulnerability detected'
418
+ }
419
+ end
420
+ rescue JSON::ParserError
421
+ # Skip invalid JSON lines
422
+ next
423
+ end
424
+ end
425
+
426
+ @result.package_vulnerabilities = vulnerabilities
427
+ end
428
+
367
429
  def parse_npm_outdated_output(data)
368
430
  versions = []
369
431
 
@@ -789,7 +851,14 @@ module Rubion
789
851
  puts "\n Both npm and yarn are available. Which would you like to use?"
790
852
  print " Enter 'n' for npm or 'y' for yarn (default: npm): "
791
853
 
792
- choice = $stdin.gets.chomp.strip.downcase
854
+ input = $stdin.gets
855
+ if input.nil?
856
+ # stdin not available (e.g., running through bundle exec in non-interactive mode)
857
+ puts " (stdin not available, using npm as default)\n"
858
+ return 'npm'
859
+ end
860
+
861
+ choice = input.chomp.strip.downcase
793
862
 
794
863
  if choice.empty? || choice == 'n' || choice == 'npm'
795
864
  'npm'
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubion
4
- VERSION = "0.3.16"
4
+ VERSION = "0.3.18"
5
5
  end
6
6
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.16
4
+ version: 0.3.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - bipashant
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-11-17 00:00:00.000000000 Z
11
+ date: 2025-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: terminal-table