Skip to content

Conversation

@pboling
Copy link
Contributor

@pboling pboling commented Oct 26, 2025

# 📍 NOTE What
1️⃣ Please see #38 first Modernize gem structure merged
2️⃣ Then see #37 next Upgrade to v1.7 spec merged
3️⃣ Then see #39 Add --validate feature will not do
4️⃣ Then this one Add --include-metadata feature <=== You are here

CLI and wiring

  • --include-metadata
    • 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).
  • --enrich-components
    • 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.
  • Help and README updated.

JSON and XML emission

  • 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 using purl.
      • first_author 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.

Component shape

  • 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.

Tests

  • features/metadata_tools.feature (integration)
  • spec/cyclonedx/metadata_tools_spec.rb (unit, offline-safe)
  • 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 when include_enrichment: true and omits otherwise.

Signed-off-by: Peter H. Boling peter.boling@gmail.com

Copilot AI review requested due to automatic review settings October 26, 2025 08:10
Copy link

Copilot AI left a 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 pull request introduces support for emitting metadata.tools information in CycloneDX BOMs when the --include-metadata flag is provided. The tools metadata identifies the producer (CycloneDX, cyclonedx-ruby, and the gem version) and is emitted for both JSON and XML formats when the selected spec version is >= 1.2.

Key changes:

  • Added --include-metadata CLI flag to control metadata.tools emission
  • Implemented metadata.tools generation for JSON and XML BOM formats
  • Restructured test files and added RSpec configuration
  • Added unit and integration tests for the new functionality

Reviewed Changes

Copilot reviewed 62 out of 82 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
spec/spec_helper.rb Replaced Aruba-based configuration with standard RSpec setup including SimpleCov initialization
spec/cyclonedx/ruby_spec.rb Added version number existence test for the gem
spec/cyclonedx/metadata_tools_spec.rb New test file validating metadata.tools emission in JSON and XML BOMs
spec/cyclonedx/bom_helpers_spec.rb Tests for BomHelpers.purl method with legacy method compatibility check
spec/cyclonedx/bom_component_spec.rb Updated to use namespaced class name (Cyclonedx::BomComponent)
spec/bom_helpers_spec.rb Deleted legacy test file
sig/cyclonedx/ruby.rbs Added RBS type signature for the Ruby module with VERSION constant
schema/*.{json,xsd,proto} Added CycloneDX schema files for various versions and formats
schema/README.md Documentation about the CycloneDX specification and schemas
lib/cyclonedx_deprecated.rb Backward compatibility layer providing deprecated global methods
lib/cyclonedx/ruby/version.rb Version constant definition (VERSION = "1.2.0")
lib/cyclonedx/ruby.rb Main entry point requiring dependencies and gem components
features/support/*.rb Added frozen_string_literal comments

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

validation without needing internet access.
Namespace: urn:oasis:names:tc:entity:xmlns:xml:catalog
-->
<!-- to prevent unintendedn notwork access, we do not set a DTD/XSD in this XML -->
Copy link

Copilot AI Oct 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'unintended' (was 'unintendedn') and 'network' (was 'notwork').

Suggested change
<!-- to prevent unintendedn notwork access, we do not set a DTD/XSD in this XML -->
<!-- to prevent unintended network access, we do not set a DTD/XSD in this XML -->

Copilot uses AI. Check for mistakes.
@pboling pboling changed the title ✨ --include-metadata (metadata.tools) ✨ --include-metadata (metadata.tools) & --enrich-components Oct 26, 2025
@pboling pboling force-pushed the feat/metadata-tools branch from e20181d to bc50e2a Compare October 30, 2025 07:49
@pboling pboling requested a review from a team as a code owner October 30, 2025 07:49
@pboling pboling force-pushed the feat/metadata-tools branch 7 times, most recently from 4c22698 to 3ec031f Compare November 6, 2025 12:00
Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
- All generated BOMs are now automatically validated against the CycloneDX schema.
  If validation fails, the tool exits with an error code instead of writing an invalid BOM.
- Added --validate PATH flag in Cyclonedx::BomBuilder to validate existing BOM files
  without generating a new one.
- In validate-only mode (--validate <path>), project path is not required.
- Format is automatically inferred from file extension (.json or .xml) when using
  --validate unless --format is explicitly provided.

- Added Cyclonedx::BomHelpers.validate_bom_content(content, format, spec_version) which:
  - For JSON: uses json_schemer to validate against bom-<ver>.schema.json.
  - For XML: uses Nokogiri::XML::Schema with bom-<ver>.xsd.
- Uses local schemas at schema/ and surfaces compact error messages; returns non-zero
  exit on failure.

- Added json_schemer (~> 2.2) to cyclonedx-ruby.gemspec.
- Required json_schemer in lib/cyclonedx/ruby.rb.

- Updated features/help.feature to show the --validate flag.
- Added features/validate.feature:
  - Validate generated XML BOM succeeds (automatic validation).
  - Validate generated JSON BOM succeeds (automatic validation).
  - Validate existing XML BOM succeeds with --validate flag.
  - Validate existing JSON BOM succeeds with --validate flag.
  - Validate fails for invalid XML BOM (corrupts namespace and expects exit 1).

Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
end

def get_gem(name, version, logger)
url = "https://rubygems.org/api/v1/versions/#{name}.json"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might want to make the domain of this call configurable so that a user can query a private or third party gem server instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!
I'll make it default to gem.coop, and allow overrides.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to gem.coop in b1ab078

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✨ --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

  • 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

Core implementation

  • 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]

Tests

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

Use cases

Users can now:

- Add spec version selection end-to-end with a new --spec-version flag (default 1.7).
- Update JSON and XML outputs to honor the selected spec version.
- Update fixtures, help text, tests, and docs.

Files:
- lib/bom_helpers.rb:
  - Added SUPPORTED_SPEC_VERSIONS, cyclonedx_xml_namespace helper.
build_bom now accepts spec_version and routes to:
    - build_json_bom(gems, spec_version) sets specVersion to the provided version.
    - build_bom_xml(gems, spec_version) sets xmlns to http://cyclonedx.org/schema/bom/<version>.</version>
- lib/bom_builder.rb:
  - Added --spec-version with validation; default is 1.7.
  - Pass @spec_version into build_bom(@Gems, @bom_output_format, @spec_version).

Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
- Added --validate and --validate-file flags in Cyclonedx::BomBuilder.
- After writing the BOM, if --validate is set, validate JSON via JSON Schema and XML via XSD with local files under schema/.
- Added logic to validate an existing file with --validate --validate-file <path>, inferring format from extension unless --format is provided.</path>
- In validate-only mode, project path isn’t required.

- Added Cyclonedx::BomHelpers.validate_bom_content(content, format, spec_version) which:
  - For JSON: uses json_schemer to validate against bom-<ver>.schema.json.</ver>
  - For XML: uses Nokogiri::XML::Schema with bom-<ver>.xsd.</ver>
- Uses local schemas at schema/ and surfaces compact error messages; returns non-zero exit on failure.

- Added json_schemer (~> 2.2) to cyclonedx-ruby.gemspec.
- Required json_schemer in lib/cyclonedx/ruby.rb.

- Updated features/help.feature to show the new flags.
- Added features/validate.feature:
  - Validate XML BOM succeeds.
  - Validate JSON BOM succeeds.
  - Validate fails for invalid XML BOM (corrupts namespace and expects exit 1).

- Infer format from file extension when using --validate-file and no --format provided.

Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
- Add spec version selection end-to-end with a new --spec-version flag (default 1.7).
- Update JSON and XML outputs to honor the selected spec version.
- Update fixtures, help text, tests, and docs.

Files:
- lib/bom_helpers.rb:
  - Added SUPPORTED_SPEC_VERSIONS, cyclonedx_xml_namespace helper.
build_bom now accepts spec_version and routes to:
    - build_json_bom(gems, spec_version) sets specVersion to the provided version.
    - build_bom_xml(gems, spec_version) sets xmlns to http://cyclonedx.org/schema/bom/<version>.</version>
- lib/bom_builder.rb:
  - Added --spec-version with validation; default is 1.7.
  - Pass @spec_version into build_bom(@Gems, @bom_output_format, @spec_version).

Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
- Added --validate and --validate-file flags in Cyclonedx::BomBuilder.
- After writing the BOM, if --validate is set, validate JSON via JSON Schema and XML via XSD with local files under schema/.
- Added logic to validate an existing file with --validate --validate-file <path>, inferring format from extension unless --format is provided.</path>
- In validate-only mode, project path isn’t required.

- Added Cyclonedx::BomHelpers.validate_bom_content(content, format, spec_version) which:
  - For JSON: uses json_schemer to validate against bom-<ver>.schema.json.</ver>
  - For XML: uses Nokogiri::XML::Schema with bom-<ver>.xsd.</ver>
- Uses local schemas at schema/ and surfaces compact error messages; returns non-zero exit on failure.

- Added json_schemer (~> 2.2) to cyclonedx-ruby.gemspec.
- Required json_schemer in lib/cyclonedx/ruby.rb.

- Updated features/help.feature to show the new flags.
- Added features/validate.feature:
  - Validate XML BOM succeeds.
  - Validate JSON BOM succeeds.
  - Validate fails for invalid XML BOM (corrupts namespace and expects exit 1).

- Infer format from file extension when using --validate-file and no --format provided.

Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
- 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 <peter.boling@gmail.com>
- 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 <peter.boling@gmail.com>
- Fix link to renamed LICENSE => LICENSE.txt

Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
@pboling pboling force-pushed the feat/metadata-tools branch from 3ec031f to b47dd03 Compare December 19, 2025 20:52
Signed-off-by: Peter H. Boling <peter.boling@gmail.com>
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

- 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

# Core implementation

- 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]

# Tests

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

# Use cases

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 <peter.boling@gmail.com>
@pboling pboling requested a review from andrew December 19, 2025 21:13
@pboling
Copy link
Contributor Author

pboling commented Dec 19, 2025

@andrew This has been rebased on top of #39 - and this PR will shrink considerably once that one is merged.

@andrew
Copy link

andrew commented Dec 20, 2025

Got some test failures

@pboling
Copy link
Contributor Author

pboling commented Dec 21, 2025

Replaced by #50

@pboling pboling closed this Dec 21, 2025
@jkowalleck jkowalleck added the enhancement New feature or request label Dec 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants