Skip to content

Commit 8ce4ebb

Browse files
committed
NODE-7025: Moving logic to script and action runs it
1 parent 8ec55e8 commit 8ce4ebb

3 files changed

Lines changed: 125 additions & 80 deletions

File tree

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,26 @@
11
name: Generate SBOM
22
description: Generates CycloneDX SBOM using cdxgen
3+
34
inputs:
45
output-file:
56
description: "Output filename for the SBOM"
67
required: false
78
default: "sbom.json"
9+
810
outputs:
911
HAS_CHANGES:
1012
description: "Whether the SBOM has meaningful changes compared to the existing version"
11-
value: ${{ steps.check_changes.outputs.HAS_CHANGES }}
13+
value: ${{ steps.generate.outputs.HAS_CHANGES }}
14+
1215
runs:
1316
using: composite
1417
steps:
1518
- name: Generate SBOM
16-
id: generate-sbom
17-
shell: bash
18-
run: |
19-
echo "Generating SBOM for 'node' project..."
20-
npx @cyclonedx/cyclonedx-npm --omit dev --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
36-
37-
- 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'
19+
id: generate
4420
shell: bash
4521
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
85-
shell: bash
22+
SBOM_OUTPUT_FILE: ${{ inputs.output-file }}
8623
run: |
87-
if [ ! -f "${{ inputs.output-file }}" ]; then
88-
echo "Error: Final SBOM file not found at ${{ inputs.output-file }}"
89-
exit 1
90-
fi
91-
echo "SBOM file validated: ${{ inputs.output-file }}"
24+
SCRIPT_DIR="${{ github.action_path }}"
25+
chmod +x "${SCRIPT_DIR}/generate-sbom.sh"
26+
"${SCRIPT_DIR}/generate-sbom.sh" "$SBOM_OUTPUT_FILE"
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env bash
2+
#
3+
# generate-sbom.sh - Generate and validate CycloneDX SBOM
4+
#
5+
# Usage: ./generate-sbom.sh [output-file]
6+
#
7+
# Environment variables:
8+
# GITHUB_OUTPUT - Path to GitHub Actions output file (optional)
9+
#
10+
11+
set -euo pipefail
12+
13+
SBOM_FILE="${1:-sbom.json}"
14+
TEMP_SBOM="sbom-new.json"
15+
CYCLONEDX_CLI="/tmp/cyclonedx"
16+
CYCLONEDX_CLI_URL="https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.29.1/cyclonedx-linux-x64"
17+
JQ_NORMALIZER='del(.serialNumber) | del(.metadata.timestamp) | walk(if type == "object" and .timestamp then .timestamp = "TIMESTAMP_NORMALIZED" else . end)'
18+
19+
echo "Starting SBOM generation (output: $SBOM_FILE)"
20+
21+
echo "Generating SBOM for 'node' project..."
22+
23+
if ! npx @cyclonedx/cyclonedx-npm \
24+
--omit dev \
25+
--package-lock-only \
26+
--output-file "$TEMP_SBOM" \
27+
--output-format json \
28+
--spec-version 1.5; then
29+
echo "ERROR: Failed to generate SBOM" >&2
30+
exit 1
31+
fi
32+
33+
if [[ ! -f "$TEMP_SBOM" ]]; then
34+
echo "ERROR: SBOM file not found after generation" >&2
35+
exit 1
36+
fi
37+
38+
echo "SBOM file generated: $TEMP_SBOM"
39+
40+
echo "Downloading CycloneDX CLI..."
41+
42+
if ! curl -L -s -o "$CYCLONEDX_CLI" "$CYCLONEDX_CLI_URL"; then
43+
echo "ERROR: Failed to download CycloneDX CLI" >&2
44+
exit 1
45+
fi
46+
47+
chmod +x "$CYCLONEDX_CLI"
48+
49+
if [[ ! -x "$CYCLONEDX_CLI" ]]; then
50+
echo "ERROR: CycloneDX CLI is not executable" >&2
51+
exit 1
52+
fi
53+
54+
echo "CycloneDX CLI ready at $CYCLONEDX_CLI"
55+
56+
echo "Validating SBOM: $TEMP_SBOM"
57+
58+
if ! "$CYCLONEDX_CLI" validate --input-file "$TEMP_SBOM" --fail-on-errors; then
59+
echo "ERROR: SBOM validation failed for $TEMP_SBOM" >&2
60+
exit 1
61+
fi
62+
63+
echo "SBOM validation passed: $TEMP_SBOM"
64+
65+
echo "Checking for SBOM changes..."
66+
67+
HAS_CHANGES="false"
68+
69+
if [[ ! -f "$SBOM_FILE" ]]; then
70+
echo "No existing $SBOM_FILE found, creating initial version"
71+
mv "$TEMP_SBOM" "$SBOM_FILE"
72+
HAS_CHANGES="true"
73+
else
74+
echo "Comparing new SBOM with existing $SBOM_FILE..."
75+
76+
# Try cyclonedx diff for component-level comparison
77+
DIFF_OUTPUT=$("$CYCLONEDX_CLI" diff "$SBOM_FILE" "$TEMP_SBOM" --component-versions 2>/dev/null || true)
78+
79+
if echo "$DIFF_OUTPUT" | grep -q "^None$"; then
80+
echo "No component changes detected via cyclonedx diff"
81+
82+
# Double-check with jq normalization (excludes metadata like timestamps)
83+
if diff -q \
84+
<(jq -r "$JQ_NORMALIZER" < "$SBOM_FILE") \
85+
<(jq -r "$JQ_NORMALIZER" < "$TEMP_SBOM") > /dev/null 2>&1; then
86+
echo "No meaningful changes detected in SBOM"
87+
rm -f "$TEMP_SBOM"
88+
HAS_CHANGES="false"
89+
else
90+
echo "Changes detected in SBOM (non-component changes)"
91+
mv "$TEMP_SBOM" "$SBOM_FILE"
92+
HAS_CHANGES="true"
93+
fi
94+
else
95+
echo "Component changes detected:"
96+
echo "$DIFF_OUTPUT"
97+
mv "$TEMP_SBOM" "$SBOM_FILE"
98+
HAS_CHANGES="true"
99+
fi
100+
fi
101+
102+
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
103+
echo "HAS_CHANGES=${HAS_CHANGES}" >> "$GITHUB_OUTPUT"
104+
fi
105+
echo "Output: HAS_CHANGES=${HAS_CHANGES}"
106+
107+
if [[ ! -f "$SBOM_FILE" ]]; then
108+
echo "ERROR: Final SBOM file not found at $SBOM_FILE" >&2
109+
exit 1
110+
fi
111+
112+
echo "SBOM file validated: $SBOM_FILE"
113+
echo "SBOM generation completed successfully"

.github/workflows/sbom.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ on:
88
- 'package-lock.json'
99
workflow_dispatch:
1010

11-
env:
12-
SBOM_FILE: "sbom.json"
13-
1411
permissions:
1512
contents: write
1613

@@ -20,7 +17,7 @@ jobs:
2017
runs-on: ubuntu-latest
2118

2219
concurrency:
23-
group: sbom-${{ github.ref }}
20+
group: sbom-update
2421
cancel-in-progress: false
2522

2623
steps:
@@ -39,14 +36,14 @@ jobs:
3936
id: generate_sbom
4037
uses: ./.github/actions/sbom-update
4138
with:
42-
output-file: ${{ env.SBOM_FILE }}
39+
output-file: sbom.json
4340

4441
- name: Commit SBOM changes
4542
if: steps.generate_sbom.outputs.HAS_CHANGES == 'true'
4643
run: |
4744
git config user.name "github-actions[bot]"
4845
git config user.email "github-actions[bot]@users.noreply.github.com"
49-
git add ${{ env.SBOM_FILE }}
46+
git add sbom.json
5047
git commit -m "chore(deps): Update SBOM after dependency changes"
5148
git push
5249
echo "SBOM updated and committed" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)