bundler-sbom 0.2.0 → 0.3.0

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: f578e54cb4d73e62b18d305684a0ff770edb7cde70b31fdd8cb9eaa7b53e0885
4
- data.tar.gz: 9e853789b6b01962185dde4a528f84c1e1f16f4432d4a9c5f57b16d5680e0489
3
+ metadata.gz: c2d31deef79ab54416961ff900632cf386f95207f35afd2c2e491d97c53d4c0e
4
+ data.tar.gz: 6060186d5f3394f12f9c58a2ad1aa4a01b554500f58ef606403536675e506f18
5
5
  SHA512:
6
- metadata.gz: 4bd4342d874517d03999ba5166fac776610ae3832d79eb620732de9cb7fa6e82614b61ba52a1dc89c79580d1985dad790c6f2ca4c641fd10afbc65ed32fe1b85
7
- data.tar.gz: 9f30c4813af67c7882dcec7d132e8c324bc243d6f8fb19cef7a8571a9678fbbf0b92d15fd1a598f0afe6f73497faeea428bbbcd3d03838f3347380f4e44f722c
6
+ metadata.gz: bb372a7bf2da186dcdf3a3406f236682b35b3aba690a21f3617a32cd94cebf85a4902e39a755a0e1698ff463a9f37fa8c79a425230ab6d1b68c16d1790dbb476
7
+ data.tar.gz: aab0fffe6b7c684d8bb07c33040f2f5897c00d9353e5809b665333a714ee6175a36a2eae4ac01d8427c5b273e3911e91fadc8580f486d4dc04db0ec9f6ec337d
data/README.md CHANGED
@@ -23,6 +23,7 @@ $ bundle sbom dump [options]
23
23
  Available options:
24
24
  - `-f, --format FORMAT`: Output format (json or xml, default: json)
25
25
  - `-s, --sbom FORMAT`: SBOM specification format (spdx or cyclonedx, default: spdx)
26
+ - `--without GROUPS`: Exclude groups (comma or colon separated, e.g., 'development:test' or 'development,test')
26
27
 
27
28
  Generated files will be named according to the following pattern:
28
29
  - SPDX format: `bom.json` or `bom.xml`
@@ -34,6 +35,8 @@ $ bundle sbom dump # Generates SPDX format in JSON (bo
34
35
  $ bundle sbom dump -f xml # Generates SPDX format in XML (bom.xml)
35
36
  $ bundle sbom dump -s cyclonedx # Generates CycloneDX format in JSON (bom-cyclonedx.json)
36
37
  $ bundle sbom dump -s cyclonedx -f xml # Generates CycloneDX format in XML (bom-cyclonedx.xml)
38
+ $ bundle sbom dump --without development # Excludes development group
39
+ $ bundle sbom dump --without development:test # Excludes development and test groups
37
40
  ```
38
41
 
39
42
  ### Analyze License Information
@@ -8,9 +8,11 @@ module Bundler
8
8
  desc "dump", "Generate SBOM and save to file"
9
9
  method_option :format, type: :string, default: "json", desc: "Output format: json or xml", aliases: "-f"
10
10
  method_option :sbom, type: :string, default: "spdx", desc: "SBOM format: spdx or cyclonedx", aliases: "-s"
11
+ method_option :without, type: :string, desc: "Exclude groups (comma or colon separated, e.g., 'development:test' or 'development,test')"
11
12
  def dump
12
13
  format = options[:format].downcase
13
14
  sbom_format = options[:sbom].downcase
15
+ without_groups = parse_without_groups(options[:without])
14
16
 
15
17
  # Validate output format
16
18
  unless ["json", "xml"].include?(format)
@@ -25,7 +27,7 @@ module Bundler
25
27
  end
26
28
 
27
29
  # Generate SBOM based on specified format
28
- sbom = Bundler::Sbom::Generator.generate_sbom(sbom_format)
30
+ sbom = Bundler::Sbom::Generator.generate_sbom(sbom_format, without_groups: without_groups)
29
31
 
30
32
  # Determine file extension based on output format
31
33
  ext = (format == "json") ? "json" : "xml"
@@ -100,6 +102,16 @@ module Bundler
100
102
  def self.exit_on_failure?
101
103
  true
102
104
  end
105
+
106
+ private
107
+
108
+ def parse_without_groups(without_option)
109
+ return [] unless without_option
110
+
111
+ # Split by comma or colon and clean up whitespace
112
+ groups = without_option.split(%r{[:,]}).map(&:strip).reject(&:empty?)
113
+ groups.map(&:to_sym)
114
+ end
103
115
  end
104
116
  end
105
117
  end
@@ -5,7 +5,7 @@ require "rexml/document"
5
5
  module Bundler
6
6
  module Sbom
7
7
  class CycloneDX
8
- def self.generate(lockfile, document_name)
8
+ def self.generate(gems, document_name)
9
9
  serial_number = SecureRandom.uuid
10
10
  timestamp = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
11
11
  sbom = {
@@ -33,7 +33,7 @@ module Bundler
33
33
 
34
34
  # Deduplicate specs by name and version
35
35
  seen_gems = Set.new
36
- lockfile.specs.each do |spec|
36
+ gems.each do |spec|
37
37
  gem_key = "#{spec.name}:#{spec.version}"
38
38
  next if seen_gems.include?(gem_key)
39
39
  seen_gems.add(gem_key)
@@ -10,7 +10,7 @@ module Bundler
10
10
  class GemfileLockNotFoundError < StandardError; end
11
11
 
12
12
  class Generator
13
- def self.generate_sbom(format = "spdx")
13
+ def self.generate_sbom(format = "spdx", without_groups: [])
14
14
  lockfile_path = Bundler.default_lockfile
15
15
  if !lockfile_path || !lockfile_path.exist?
16
16
  Bundler.ui.error "No Gemfile.lock found. Run `bundle install` first."
@@ -20,11 +20,14 @@ module Bundler
20
20
  lockfile = Bundler::LockfileParser.new(lockfile_path.read)
21
21
  document_name = File.basename(Dir.pwd)
22
22
 
23
+ # Get gems to include based on groups
24
+ gems = get_gems_for_groups(lockfile, without_groups)
25
+
23
26
  case format.to_s.downcase
24
27
  when "cyclonedx"
25
- CycloneDX.generate(lockfile, document_name)
28
+ CycloneDX.generate(gems, document_name)
26
29
  else # default to spdx
27
- SPDX.generate(lockfile, document_name)
30
+ SPDX.generate(gems, document_name)
28
31
  end
29
32
  end
30
33
 
@@ -47,6 +50,44 @@ module Bundler
47
50
  SPDX.parse_xml(doc)
48
51
  end
49
52
  end
53
+
54
+ private
55
+
56
+ def self.get_gems_for_groups(lockfile, without_groups)
57
+ # If no groups specified, use all specs
58
+ if without_groups.empty?
59
+ return lockfile.specs
60
+ end
61
+
62
+ # Try to get group information from Bundler.definition if available
63
+ if defined?(Bundler::Definition) && Bundler.respond_to?(:definition)
64
+ begin
65
+ definition = Bundler.definition
66
+ all_groups = definition.groups
67
+ include_groups = all_groups - without_groups
68
+
69
+ # Use specs_for to get all gems (including transitive dependencies) for included groups
70
+ if definition.respond_to?(:specs_for)
71
+ definition.specs_for(include_groups)
72
+ else
73
+ # Fallback to old method if specs_for is not available
74
+ included_gems = Set.new
75
+ include_groups.each do |group|
76
+ definition.dependencies_for(group).each do |dep|
77
+ included_gems.add(dep.name)
78
+ end
79
+ end
80
+ lockfile.specs.select { |spec| included_gems.include?(spec.name) }
81
+ end
82
+ rescue => e
83
+ # Fallback to all specs if there's any issue with Bundler.definition
84
+ Bundler.ui.warn("Warning: Could not determine group information: #{e.message}")
85
+ lockfile.specs
86
+ end
87
+ else
88
+ lockfile.specs
89
+ end
90
+ end
50
91
  end
51
92
  end
52
93
  end
@@ -5,7 +5,7 @@ require "rexml/document"
5
5
  module Bundler
6
6
  module Sbom
7
7
  class SPDX
8
- def self.generate(lockfile, document_name)
8
+ def self.generate(gems, document_name)
9
9
  spdx_id = generate_spdx_id
10
10
  sbom = {
11
11
  "SPDXID" => "SPDXRef-DOCUMENT",
@@ -23,7 +23,7 @@ module Bundler
23
23
 
24
24
  # Deduplicate specs by name and version
25
25
  seen_gems = Set.new
26
- lockfile.specs.each do |spec|
26
+ gems.each do |spec|
27
27
  gem_key = "#{spec.name}:#{spec.version}"
28
28
  next if seen_gems.include?(gem_key)
29
29
  seen_gems.add(gem_key)
@@ -1,5 +1,5 @@
1
1
  module Bundler
2
2
  module Sbom
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler-sbom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SHIBATA Hiroshi