test ci: add gh workflows to generate sbom #15
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Download SBOM from Insights and Convert to CSV | |
on: | |
pull_request: | |
branches: | |
- main | |
jobs: | |
convert-sbom: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout Code | |
uses: actions/checkout@v3 | |
- name: Set Timestamp and Unique Filename | |
run: | | |
FILE_PREFIX=$(echo "${{ github.repository }}" | sed 's|/|-|g')-$(date +%Y%m%d%H%M%S) | |
echo "FILE_PREFIX=${FILE_PREFIX}" >> $GITHUB_ENV | |
- name: Download SBOM | |
run: | | |
curl -L \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
https://api.github.com/repos/${{ github.repository }}/dependency-graph/sbom \ | |
-o "${FILE_PREFIX}-sbom.json" | |
- name: Verify SBOM JSON File | |
run: | | |
ls -l "${FILE_PREFIX}-sbom.json" | |
- name: Preview SBOM JSON Content | |
run: | | |
head -n 20 "${FILE_PREFIX}-sbom.json" | |
- name: Convert SBOM to CSV using jq | |
run: | | |
echo "name,SPDXID,versionInfo,downloadLocation,externalRefs,license,source_code_url,vendor" > "${FILE_PREFIX}-sbom.csv" | |
jq -r ' | |
.sbom.packages[] | [ | |
.name, | |
.SPDXID, | |
.versionInfo, | |
.downloadLocation, | |
( .externalRefs[]? | .referenceLocator ), | |
"None", "None", "None" | |
] | @csv' "${FILE_PREFIX}-sbom.json" >> "${FILE_PREFIX}-sbom.csv" | |
- name: Preview SBOM CSV Content | |
run: | | |
head -n 20 "${FILE_PREFIX}-sbom.csv" | |
- name: Enrich SBOM CSV with RubyGems Data | |
run: | | |
TEMP_CSV="${FILE_PREFIX}-sbom-temp.csv" | |
echo "name,SPDXID,versionInfo,downloadLocation,externalRefs,license,source_code_url,vendor" > "$TEMP_CSV" | |
tail -n +2 "${FILE_PREFIX}-sbom.csv" | while IFS=, read -r name SPDXID versionInfo downloadLocation externalRefs license source_code_url vendor; do | |
# Debug each row | |
echo "Processing: $name, $SPDXID, $versionInfo, $downloadLocation, $externalRefs, $license, $source_code_url, $vendor" | |
if [[ "$externalRefs" == *"pkg:gem"* ]]; then | |
echo "Processing RubyGem: $name" | |
gem_name=$(echo "$name" | tr -d '"') | |
version=$(echo "$versionInfo" | tr -d '"') | |
# If version has a comparison operator (e.g., ~>, >=, <=) | |
if [[ "$versionInfo" =~ [\~\>\<\=\ ] ]]; then | |
echo "Evaluating version constraint: $versionInfo" | |
# Extract the base version (e.g., "2.11" from "~> 2.11") | |
base_version=$(echo "$versionInfo" | sed -E 's/[^\d.]//g') | |
# Get the list of available versions from RubyGems API | |
api_url="https://rubygems.org/api/v2/rubygems/${gem_name}/versions.json" | |
available_versions=$(curl -s "$api_url" | jq -r '.[].version') | |
# Find the valid version according to the constraint | |
valid_version="" | |
if [[ "$versionInfo" == "~>"* ]]; then | |
# Handle pessimistic constraint "~> 2.11" (i.e., 2.11.x but not 3.0) | |
valid_version=$(echo "$available_versions" | grep -E "^${base_version}\." | sort -V | head -n 1) | |
elif [[ "$versionInfo" == ">="* ]]; then | |
# Handle >= constraint | |
valid_version=$(echo "$available_versions" | grep -E "^${base_version}" | sort -V | head -n 1) | |
elif [[ "$versionInfo" == "<="* ]]; then | |
# Handle <= constraint | |
valid_version=$(echo "$available_versions" | grep -E "^${base_version}" | sort -V | tail -n 1) | |
fi | |
if [ -z "$valid_version" ]; then | |
echo "No valid version found for constraint $versionInfo" | |
continue | |
fi | |
# Proceed with the valid version | |
echo "Using version: $valid_version for $gem_name" | |
api_url="https://rubygems.org/api/v2/rubygems/${gem_name}/versions/${valid_version}.json" | |
response=$(curl -s "$api_url") | |
# Extract relevant fields from the response | |
new_license=$(echo "$response" | jq -r '.licenses[0] // "None"') | |
new_source_code_url=$(echo "$response" | jq -r '.source_code_uri // "None"') | |
new_vendor=$(echo "$response" | jq -r '.authors // "None"') | |
else | |
# Handle fixed version | |
echo "Fixed version: $versionInfo" | |
api_url="https://rubygems.org/api/v2/rubygems/${gem_name}/versions/${versionInfo}.json" | |
response=$(curl -s "$api_url") | |
new_license=$(echo "$response" | jq -r '.licenses[0] // "None"') | |
new_source_code_url=$(echo "$response" | jq -r '.source_code_uri // "None"') | |
new_vendor=$(echo "$response" | jq -r '.authors // "None"') | |
fi | |
else | |
# Default values if not a RubyGem | |
new_license="None" | |
new_source_code_url="None" | |
new_vendor="None" | |
fi | |
# Write updated values to temp CSV | |
echo "$name,$SPDXID,$versionInfo,$downloadLocation,$externalRefs,$new_license,$new_source_code_url,$new_vendor" >> "$TEMP_CSV" | |
done | |
mv "$TEMP_CSV" "${FILE_PREFIX}-sbom.csv" | |
- name: Verify SBOM CSV File | |
run: | | |
ls -l "${FILE_PREFIX}-sbom.csv" | |
- name: Upload SBOM JSON as Artifact | |
uses: actions/upload-artifact@v3 | |
with: | |
name: sbom-json | |
path: ${{ env.FILE_PREFIX }}-sbom.json | |
- name: Upload SBOM CSV as Artifact | |
uses: actions/upload-artifact@v3 | |
with: | |
name: sbom-csv | |
path: ${{ env.FILE_PREFIX }}-sbom.csv |