@@ -5,23 +5,87 @@ inputs:
55 description : " Output filename for the SBOM"
66 required : false
77 default : " sbom.json"
8-
8+ outputs :
9+ HAS_CHANGES :
10+ description : " Whether the SBOM has meaningful changes compared to the existing version"
11+ value : ${{ steps.check_changes.outputs.HAS_CHANGES }}
912runs :
1013 using : composite
1114 steps :
1215 - name : Generate SBOM
16+ id : generate-sbom
1317 shell : bash
14- working-directory : ${{ inputs.working-directory }}
1518 run : |
1619 echo "Generating SBOM for 'node' project..."
17- npx @cyclonedx/cyclonedx-npm --package-lock-only --omit dev --output-file sbom.json --output-format json --spec-version 1.5
20+ npx @cyclonedx/cyclonedx-npm --package-lock-only --output-file sbom-new.json --output-format json --spec-version 1.5
21+
22+ - name : Validate SBOM presence
23+ shell : bash
24+ run : |
25+ if [ ! -f "sbom-new.json" ]; then
26+ echo "Error: SBOM file not found"
27+ exit 1
28+ fi
29+ echo "SBOM file generated: sbom-new.json"
30+
31+ - name : Download CycloneDX CLI
32+ shell : bash
33+ run : |
34+ curl -L -s -o /tmp/cyclonedx "https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.29.1/cyclonedx-linux-x64"
35+ chmod +x /tmp/cyclonedx
1836
1937 - name : Validate SBOM
38+ shell : bash
39+ run : /tmp/cyclonedx validate --input-file sbom-new.json --fail-on-errors
40+
41+ - name : Check for SBOM changes
42+ id : check_changes
43+ if : steps.generate-sbom.outcome == 'success'
44+ shell : bash
45+ env :
46+ SBOM_FILE : ${{ inputs.output-file }}
47+ run : |
48+ JQ_NORMALIZER='del(.serialNumber) | del(.metadata.timestamp) | walk(if type == "object" and .timestamp then .timestamp = "TIMESTAMP_NORMALIZED" else . end)'
49+
50+ if [ -f "$SBOM_FILE" ]; then
51+ echo "Comparing new SBOM with existing $SBOM_FILE..."
52+
53+ # First try cyclonedx diff for component-level comparison
54+ DIFF_OUTPUT=$(/tmp/cyclonedx diff "$SBOM_FILE" sbom-new.json --component-versions 2>/dev/null || true)
55+
56+ if echo "$DIFF_OUTPUT" | grep -q "^None$"; then
57+ echo "No component changes detected via cyclonedx diff"
58+
59+ # Double-check with jq normalization (excludes metadata like timestamps)
60+ if diff -q \
61+ <(cat "$SBOM_FILE" | jq -r "$JQ_NORMALIZER") \
62+ <(cat sbom-new.json | jq -r "$JQ_NORMALIZER") > /dev/null 2>&1; then
63+ echo "HAS_CHANGES=false" >> $GITHUB_OUTPUT
64+ echo "No meaningful changes detected in SBOM"
65+ rm sbom-new.json
66+ else
67+ echo "HAS_CHANGES=true" >> $GITHUB_OUTPUT
68+ echo "Changes detected in SBOM (non-component changes)"
69+ mv sbom-new.json "$SBOM_FILE"
70+ fi
71+ else
72+ echo "Component changes detected:"
73+ echo "$DIFF_OUTPUT"
74+ echo "HAS_CHANGES=true" >> $GITHUB_OUTPUT
75+ mv sbom-new.json "$SBOM_FILE"
76+ fi
77+ else
78+ echo "No existing $SBOM_FILE found, creating initial version"
79+ echo "HAS_CHANGES=true" >> $GITHUB_OUTPUT
80+ mv sbom-new.json "$SBOM_FILE"
81+ fi
82+ continue-on-error : true
83+
84+ - name : Final SBOM validation
2085 shell : bash
2186 run : |
2287 if [ ! -f "${{ inputs.output-file }}" ]; then
23- echo "Error: SBOM file not found"
88+ echo "Error: Final SBOM file not found at ${{ inputs.output-file }} "
2489 exit 1
2590 fi
26-
2791 echo "SBOM file validated: ${{ inputs.output-file }}"
0 commit comments