-
-
Notifications
You must be signed in to change notification settings - Fork 20
✨ --spec-version, --include-metadata, --enrich-components, --gem-server #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- make setup, specs_list private methods Signed-off-by: Peter H. Boling <[email protected]>
- When provided, metadata.tools identifies this producer: - vendor: CycloneDX - name: cyclonedx-ruby - version: the gem’s version - Emitted for both JSON and XML, and only when the selected spec supports metadata (>= 1.2). - Help and README updated. - features/metadata_tools.feature (integration) - spec/cyclonedx/metadata_tools_spec.rb (unit, offline-safe) Signed-off-by: Peter H. Boling <[email protected]>
- Updated Cyclonedx::BomBuilder to add:
- CLI: --enrich-components to opt-in enrichment.
- Pass include_enrichment to build_bom(...).
- Note: This does not alter default outputs; enrichment only applies with the flag.
- Updated Cyclonedx::BomHelpers:
- build_bom supports include_enrichment and passes it to both JSON and XML builders.
- build_json_bom adds bom-ref and publisher via BomComponent when include_enrichment: true.
- build_bom_xml adds:
- bom-ref attribute on <component> using purl.
- <publisher>first_author</publisher> if authors are present (first item split on commas/ampersands).
- Added a small _get helper to read properties from either Hash or OpenStruct-like objects.
- Updated Cyclonedx::BomComponent:
- Added optional keyword parameter include_enrichment: false to hash_val.
- When true, include:
- "bom-ref": purl (if present)
- "publisher": first author (if present)
- Made property access robust across Hash/OpenStruct.
- Ensured hashes is an array with an object { alg, content } as expected by existing specs.
- Added spec/cyclonedx/component_enrichment_spec.rb:
- Verifies JSON has bom-ref and publisher when include_enrichment: true and omits them otherwise.
- Verifies XML has bom-ref attribute and <publisher> when include_enrichment: true and omits otherwise.
Signed-off-by: Peter H. Boling <[email protected]>
- Fix link to renamed LICENSE => LICENSE.txt Signed-off-by: Peter H. Boling <[email protected]>
Signed-off-by: Peter H. Boling <[email protected]>
Signed-off-by: Peter H. Boling <[email protected]>
Added --gem-server flag to allow users to specify a custom gem server for fetching gem metadata instead of using the hardcoded default. - Added --gem-server URL option in Cyclonedx::BomBuilder command-line parser - Stores custom server URL in @options[:gem_server] for use during BOM generation - When specified, passes the custom gem_server to get_gem() calls - Defaults to gem.coop when not specified, maintaining backward compatibility - Modified Cyclonedx::BomHelpers.get_gem to accept optional gem_server parameter - Defaults to 'https://gem.coop' when nil - Strips trailing slashes from gem_server URLs for consistency - Constructs gem metadata API URL using provided server - Updated get_gem call in bom_builder.rb (line 222) to pass @options[:gem_server] Unit tests (spec/cyclonedx/bom_helpers_spec.rb): - Validates default behavior uses gem.coop when gem_server is not provided or nil - Verifies custom gem server URLs are used correctly - Tests trailing slash removal from custom server URLs - Confirms rubygems.org works as a custom server - Maintains existing error handling tests Cucumber tests (features/gem_server.feature): - Validates default gem.coop behavior when --gem-server not specified - Tests custom gem server with https://rubygems.org - Tests custom gem server with trailing slash normalization - Verifies help text displays the --gem-server option Users can now: - Use private gem servers: --gem-server https://internal.company.com - Use rubygems.org directly: --gem-server https://rubygems.org - Use alternate public mirrors - Default to gem.coop without any configuration change Signed-off-by: Peter H. Boling <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for CycloneDX spec version selection via the --spec-version flag and introduces several new CLI options to enhance BOM generation capabilities. The changes include optional metadata embedding, component enrichment features, and configurable gem server selection.
Key Changes
- Added three new CLI flags:
--include-metadata(embeds tool identity in BOMs),--enrich-components(adds bom-ref and publisher fields), and--gem-server(allows custom gem repository configuration) - Changed default gem server from rubygems.org to gem.coop across the codebase
- Refactored gem object field access to support both Hash and OpenStruct-like objects
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/cyclonedx/bom_builder.rb | Added CLI option parsing for new flags and spec version validation logic |
| lib/cyclonedx/bom_helpers.rb | Implemented metadata.tools support, component enrichment, custom gem server configuration, and helper methods for object field access |
| lib/cyclonedx/bom_component.rb | Refactored to use a fetch method for accessing gem object fields and added enrichment support |
| lib/cyclonedx/ruby.rb | Reordered requires to resolve dependency issues |
| spec/cyclonedx/metadata_tools_spec.rb | Added unit tests for metadata.tools emission in JSON and XML formats |
| spec/cyclonedx/component_enrichment_spec.rb | Added unit tests for component enrichment features (bom-ref and publisher) |
| spec/cyclonedx/bom_helpers_spec.rb | Added tests for gem server configuration including default, custom, and error handling scenarios |
| features/metadata_tools.feature | Added Cucumber scenarios testing metadata inclusion in both JSON and XML BOMs |
| features/gem_server.feature | Added Cucumber scenarios for custom gem server functionality |
| features/help.feature | Updated help text to reflect new CLI options |
| README.md | Updated documentation with new CLI flags and changed gem badge link |
| Gemfile, Gemfile.lock, features/fixtures/simple/Gemfile | Changed gem source from rubygems.org to gem.coop |
| CODE_OF_CONDUCT.md | Added Contributor Covenant Code of Conduct |
| .rubocop_todo.yml | Updated RuboCop configuration to reflect new code metrics |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
It isn't clear to me why this gem depends on activesupport. It seems to be something related to the Hash core extensions. I am going to try to narrow it down and remove the dependency in a new PR. |
Co-authored-by: Copilot <[email protected]> Signed-off-by: |7eter l-|. l3oling <[email protected]>
Signed-off-by: Peter H. Boling <[email protected]>
Signed-off-by: Peter H. Boling <[email protected]>
Signed-off-by: Peter H. Boling <[email protected]>
Signed-off-by: Peter H. Boling <[email protected]>
Signed-off-by: Peter H. Boling <[email protected]>
1158d73 to
f477f8d
Compare
|
@jkowalleck @andrew Done, specs fixed, script fixed, everything fixed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 17 out of 19 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def _get(obj, key) | ||
| if obj.respond_to?(:[]) && obj[key] | ||
| obj[key] | ||
| elsif obj.respond_to?(key) | ||
| obj.public_send(key) | ||
| end |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic in the _get method has a bug. The condition obj.respond_to?(:[]) && obj[key] will return nil if the key exists but has a falsy value (nil, false, 0, empty string). The method should check for key existence rather than truthiness of the value. Consider using obj.respond_to?(:key?) && obj.key?(key) for Hash-like objects, or check the presence separately from retrieving the value.
| if @project_path | ||
| begin | ||
| @logger.info("Changing directory to Ruby project directory located at #{@provided_path}") | ||
| Dir.chdir @project_path | ||
| rescue StandardError => e | ||
| @logger.error("Unable to change directory to Ruby project directory located at #{@provided_path}. #{e.message}: #{Array(e.backtrace).join("\n")}") | ||
| abort | ||
| end | ||
| else | ||
| @logger.error("project_path could not be determined. path provided was: #{@options[:path]}") |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition if @project_path on line 117 is redundant. At line 114, @project_path is assigned File.expand_path(@options[:path]), and since we've already validated that @options[:path] exists (line 103) and is a directory (line 108), File.expand_path will never return nil. The else branch on lines 125-128 is unreachable code.
| if @project_path | |
| begin | |
| @logger.info("Changing directory to Ruby project directory located at #{@provided_path}") | |
| Dir.chdir @project_path | |
| rescue StandardError => e | |
| @logger.error("Unable to change directory to Ruby project directory located at #{@provided_path}. #{e.message}: #{Array(e.backtrace).join("\n")}") | |
| abort | |
| end | |
| else | |
| @logger.error("project_path could not be determined. path provided was: #{@options[:path]}") | |
| begin | |
| @logger.info("Changing directory to Ruby project directory located at #{@provided_path}") | |
| Dir.chdir @project_path | |
| rescue StandardError => e | |
| @logger.error("Unable to change directory to Ruby project directory located at #{@provided_path}. #{e.message}: #{Array(e.backtrace).join("\n")}") |
jkowalleck
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, i find the review hard. it is a mix of multiple scopes, goals, and therefore, i'd decline the review.
please divide this PR into multiple PRs - each with its own scope.
Think like this: if I wanted a change (feature/fix/etc), then I would write one ticket/request per change, and therefore each change will have its own discussion of expected outcome/cases/non-cases/etc, its own pull request, its own domain experts, its own review - and therefore its own pace.
Mixing multiple things in one PR makes review cumbersome and slow. - which blocks rapid evolution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thats a copy of https://github.com/CycloneDX/.github/blob/master/CODE_OF_CONDUCT.md ?
Anyway, it is not needed, as the original one appliesalready - see https://github.com/CycloneDX/cyclonedx-ruby-gem?tab=coc-ov-file#readme
so, could this file be removed, then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like it!
| # frozen_string_literal: true | ||
|
|
||
| source 'https://rubygems.org' | ||
| source 'https://gem.coop/' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep,
moving away from the money-driven ting to an alternative, free, community-driven one - 👍
| # CycloneDX Ruby Gem | ||
|
|
||
| [](https://rubygems.org/gems/cyclonedx-ruby) | ||
| [](https://bestgems.org/gems/cyclonedx-ruby) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change?
the button linking to the primary download source is very common,
why link to some download stats page instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a preference to not link to RG.O. If you prefer the old way I'll leave it alone! I like the additional information on bestgems, which is also a community resource, but I'm not strongly inclined either way.
| `-o, --output bom_file_path` Path to output the bom file | ||
| `-f, --format bom_output_format` Output format for bom. Supported: xml (default), json | ||
| `-s, --spec-version version` CycloneDX spec version to target (default: 1.7). Supported: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7 | ||
| `--include-metadata` Include metadata.tools identifying cyclonedx-ruby as the producer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i dont see a reason to hide this feature behind a feature switch.
it should be always the case: add the tool itself to metadata - whatsoever.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, will make it built-in default for spec versions that support it.
| Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE] file for the full license. | ||
|
|
||
| [License]: https://github.com/CycloneDX/cyclonedx-ruby-gem/blob/master/LICENSE | ||
| [License]: https://github.com/CycloneDX/cyclonedx-ruby-gem/blob/master/LICENSE.txt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this fix is out of scope, and was superseded by #51
| # JSON at CycloneDX 1.2 to a custom path | ||
| cyclonedx-ruby -p /path/to/ruby/project -f json -s 1.2 -o bom/out.json | ||
|
|
||
| # Include producer metadata and validate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...] and validate
where comes the validate from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's vestigial, it was a really big rebase getting it off of the validation feature. I'll pull this apart into separate PRs, and make metadata inclusion a built-in default for spec versions that support it (v1.2+).
|
|
||
| $stdout.sync = true | ||
|
|
||
| require "rubygems" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right to question that. It should not be needed. It wasn't working without it on my machine, but I think it may just be an edge case of attempting to run it from the source checkout versus a real installed gem that has the benefit of the bin script wrapper (which already does require "rubygems") and the installed gems lookup being ahead of other scripts. Since I don't have the gem installed locally, and am just working on the source I needed it to get it to run, until I built and installed the gem from the source. For normal usage it is not needed at all, and I forgot I had added it for testing.
Will remove.
Co-authored-by: Copilot <[email protected]> Signed-off-by: |7eter l-|. l3oling <[email protected]>
✨ --include-metadata (metadata.tools) & --enrich-components
CLI and wiring
--include-metadata- vendor: CycloneDX
- name: cyclonedx-ruby
- version: the gem’s version
--enrich-componentsJSON and XML emission
Component shape
Tests
✨ --gem-server: Configurable Gem Server URL
Added --gem-server flag to allow users to specify a custom gem server
for fetching gem metadata instead of using the hardcoded default.
CLI changes
Core implementation
Tests
Unit tests (spec/cyclonedx/bom_helpers_spec.rb):
Cucumber tests (features/gem_server.feature):
Use cases
Users can now:
Signed-off-by: Peter H. Boling [email protected]