Skip to content
Notifications
Clear all

Just built a CLI tool to diff two Black Duck project BOMs for change tracking.

1 Posts
1 Users
0 Reactions
0 Views
(@hannahj)
Trusted Member
Joined: 1 week ago
Posts: 59
Topic starter   [#14696]

I've been managing the ingestion of Black Duck security and license data into our data warehouse for several quarters now, primarily for trend analysis and compliance reporting. A recurring operational challenge has been tracking the precise delta between successive project BOM scans, especially after major dependency updates. The built-in project version comparison is useful for a high-level view, but I needed a way to programmatically extract a detailed, machine-readable diff to integrate with our internal change management and data pipeline dashboards.

To address this, I've developed a Python-based CLI tool that fetches and compares two Black Duck project BOMs (by project name and version), outputting a structured diff. The core functionality leverages the Black Duck REST API (`bd_rest_api` Python library) and focuses on components added or removed between scans. Here is the basic architecture:

```python
# Simplified core diff logic
def get_bom_diff(project_name, version1, version2):
bom1 = hub.get_components(project_name, version1)
bom2 = hub.get_components(project_name, version2)

# Normalize to sets of component identifiers (using external Ids)
comp1_set = {(c['componentName'], c['externalId']) for c in bom1}
comp2_set = {(c['componentName'], c['externalId']) for c in bom2}

added = comp2_set - comp1_set
removed = comp1_set - comp2_set

return {
'project': project_name,
'comparison': f'{version1} -> {version2}',
'added': [{'componentName': c[0], 'externalId': c[1]} for c in added],
'removed': [{'componentName': c[0], 'externalId': c[1]} for c in removed],
'total_components_v1': len(comp1_set),
'total_components_v2': len(comp2_set)
}
```

The tool produces JSON or CSV output, suitable for further processing. Key features implemented include:
* Support for comparing across different project versions, as well as different projects (for fork or refactor scenarios).
* Configurable field comparison (can diff by component name, version, external ID, or license).
* Pagination handling for large BOMs via the API.
* A dry-run mode to preview API calls.

In practice, I've integrated this tool into our Airflow DAGs that pull Black Duck data nightly. The diff output is stored as an artifact in S3 and loaded into a dedicated `bom_change_audit` table, enabling us to:
* Trigger alerts when high-risk components are introduced.
* Generate precise change logs for our release notes.
* Correlate dependency churn with downstream build failures.

I'm curious if others have tackled similar challenges. Specifically:
* What alternative methods or existing tools have you used for tracking BOM deltas over time?
* How do you handle the comparison when component versions are updated versus when components are swapped for functionally equivalent alternatives (different externalId)?
* Are there particular fields in the Black Duck BOM response you've found most reliable for creating a stable component identity key for comparison?

The script is still in a rough state, but I'm considering cleaning it up and open-sourcing it if there's interest. I'd appreciate any feedback on the approach or insights into potential pitfalls I may have overlooked.

— hannah


Data is the new oil – but only if refined


   
Quote