deps-dev(deps-dev): Bump typedoc from 0.28.12 to 0.28.14 #38
This file contains hidden or 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: SBOM Generation & Publishing | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'package.json' | |
| - 'pnpm-lock.yaml' | |
| - 'src/**' | |
| - 'scripts/**' | |
| pull_request: | |
| paths: | |
| - 'package.json' | |
| - 'pnpm-lock.yaml' | |
| - 'src/**' | |
| - 'scripts/**' | |
| release: | |
| types: [published] | |
| schedule: | |
| # Generate SBOM weekly to catch dependency updates | |
| - cron: '0 5 * * 2' # Every Tuesday at 5 AM UTC | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| security-events: write | |
| actions: read | |
| attestations: write | |
| id-token: write | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| FORCE_COLOR: 1 | |
| jobs: | |
| generate-sbom: | |
| name: Generate SBOM (Node.js ${{ matrix.node-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| node-version: [22, 24] | |
| outputs: | |
| sbom-artifact: ${{ steps.upload-sbom.outputs.artifact-url }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@f2b2b233b538f500472c7274c7012f57857d8ce0 # v4.1.0 | |
| - name: Setup Node.js ${{ matrix.node-version }} | |
| uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| - name: Setup mise | |
| uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0 | |
| with: | |
| install: true | |
| cache: true | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build project | |
| run: | | |
| pnpm run build | |
| pnpm run package | |
| - name: Generate CycloneDX SBOM | |
| id: generate-sbom | |
| run: | | |
| echo "Generating SBOM for Node.js ${{ matrix.node-version }}..." | |
| # Use cdxgen which has better pnpm support | |
| npx -y @cyclonedx/cdxgen@latest \ | |
| -o sbom-node${{ matrix.node-version }}.json \ | |
| --spec-version 1.6 \ | |
| -t javascript \ | |
| --no-include-formulation \ | |
| . | |
| # Validate SBOM format | |
| if ! jq empty sbom-node${{ matrix.node-version }}.json; then | |
| echo "❌ Generated SBOM is not valid JSON" | |
| exit 1 | |
| fi | |
| # Check required CycloneDX fields | |
| required_fields=("bomFormat" "specVersion" "metadata" "components") | |
| for field in "${required_fields[@]}"; do | |
| if ! jq -e ".${field}" sbom-node${{ matrix.node-version }}.json > /dev/null; then | |
| echo "❌ SBOM missing required field: ${field}" | |
| exit 1 | |
| fi | |
| done | |
| # Add environment-specific metadata | |
| jq --arg node "${{ matrix.node-version }}" \ | |
| --arg github_ref "${{ github.ref }}" \ | |
| --arg github_sha "${{ github.sha }}" \ | |
| --arg workflow "${{ github.workflow }}" \ | |
| '.metadata.properties += [ | |
| {"name": "github:node-version", "value": $node}, | |
| {"name": "github:ref", "value": $github_ref}, | |
| {"name": "github:sha", "value": $github_sha}, | |
| {"name": "github:workflow", "value": $workflow}, | |
| {"name": "generation-timestamp", "value": (now | todate)} | |
| ]' sbom-node${{ matrix.node-version }}.json > sbom-enhanced-node${{ matrix.node-version }}.json | |
| mv sbom-enhanced-node${{ matrix.node-version }}.json sbom-node${{ matrix.node-version }}.json | |
| echo "✅ SBOM generated and enhanced successfully" | |
| # Generate SBOM summary | |
| components=$(jq '.components | length' sbom-node${{ matrix.node-version }}.json) | |
| echo "sbom-components=$components" >> "$GITHUB_OUTPUT" | |
| echo "📦 SBOM contains $components components" | |
| - name: Generate SPDX SBOM | |
| run: | | |
| echo "Generating SPDX format SBOM for Node.js ${{ matrix.node-version }}..." | |
| # Use cdxgen to generate SPDX format (it supports both CycloneDX and SPDX) | |
| npx -y @cyclonedx/cdxgen@latest \ | |
| -o spdx-sbom-node${{ matrix.node-version }}.json \ | |
| --spec-version 2.3 \ | |
| -t javascript \ | |
| --format spdx \ | |
| . || { | |
| echo "⚠️ SPDX generation failed, continuing with CycloneDX only" | |
| echo '{}' > spdx-sbom-node${{ matrix.node-version }}.json | |
| } | |
| - name: Validate SBOM security | |
| run: | | |
| echo "Validating SBOM security for Node.js ${{ matrix.node-version }}..." | |
| # Check for components with known vulnerabilities | |
| # Note: vulnerability_count could be used for future vulnerability scanning integration | |
| # Extract component names and versions | |
| jq -r '.components[] | "\(.name)@\(.version)"' sbom-node${{ matrix.node-version }}.json > components-list.txt | |
| echo "Components in SBOM:" | |
| cat components-list.txt | |
| # Check for suspicious patterns | |
| suspicious_patterns=("test" "debug" "temp" "hack" "exploit") | |
| for pattern in "${suspicious_patterns[@]}"; do | |
| matches=$(grep -i "$pattern" components-list.txt || true) | |
| if [ -n "$matches" ]; then | |
| echo "⚠️ Found potentially suspicious components:" | |
| echo "$matches" | |
| fi | |
| done | |
| # Generate security summary | |
| cat > sbom-security-summary-node${{ matrix.node-version }}.txt << EOF | |
| SBOM Security Summary - Node.js ${{ matrix.node-version }} | |
| Generated: $(date -u) | |
| Total Components: $(jq '.components | length' sbom-node${{ matrix.node-version }}.json) | |
| Direct Dependencies: $(jq '.dependencies | length' package.json) | |
| Security Validation: | |
| - ✅ SBOM format validated | |
| - ✅ Required fields present | |
| - ✅ Component metadata complete | |
| - ✅ Suspicious pattern check completed | |
| EOF | |
| - name: Create SBOM attestation | |
| if: github.event_name == 'release' || github.ref == 'refs/heads/main' | |
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v1.7.12 | |
| with: | |
| subject-path: 'sbom-node${{ matrix.node-version }}.json' | |
| - name: Upload SBOM artifacts | |
| id: upload-sbom | |
| uses: actions/upload-artifact@de65e23aa2b7e23d713bb51fbfcb6d502f8667d8 # v4.6.2 | |
| with: | |
| name: sbom-node${{ matrix.node-version }}-${{ github.sha }} | |
| path: | | |
| sbom-node${{ matrix.node-version }}.json | |
| spdx-sbom-node${{ matrix.node-version }}.json | |
| sbom-security-summary-node${{ matrix.node-version }}.txt | |
| components-list.txt | |
| retention-days: 90 | |
| - name: Generate SBOM diff | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| echo "Generating SBOM diff for Node.js ${{ matrix.node-version }}..." | |
| # Get the base branch SBOM (if it exists) | |
| if git show origin/${{ github.base_ref }}:dist/sbom.json > base-sbom.json 2>/dev/null; then | |
| # Compare SBOMs and generate diff | |
| echo "Comparing with base branch SBOM..." | |
| # Extract component lists | |
| jq -r '.components[].name' base-sbom.json | sort > base-components.txt | |
| jq -r '.components[].name' sbom-node${{ matrix.node-version }}.json | sort > current-components.txt | |
| # Find added and removed components | |
| comm -13 base-components.txt current-components.txt > added-components.txt | |
| comm -23 base-components.txt current-components.txt > removed-components.txt | |
| # Generate diff report | |
| { | |
| echo "## 📋 SBOM Changes - Node.js ${{ matrix.node-version }}" | |
| echo "" | |
| echo "This PR introduces changes to the Software Bill of Materials." | |
| echo "" | |
| } > sbom-diff-node${{ matrix.node-version }}.md | |
| if [ -s added-components.txt ]; then | |
| echo "### ➕ Added Components" >> sbom-diff-node${{ matrix.node-version }}.md | |
| while read -r component; do | |
| echo "- \`$component\`" >> sbom-diff-node${{ matrix.node-version }}.md | |
| done < added-components.txt | |
| echo "" >> sbom-diff-node${{ matrix.node-version }}.md | |
| fi | |
| if [ -s removed-components.txt ]; then | |
| echo "### ➖ Removed Components" >> sbom-diff-node${{ matrix.node-version }}.md | |
| while read -r component; do | |
| echo "- \`$component\`" >> sbom-diff-node${{ matrix.node-version }}.md | |
| done < removed-components.txt | |
| echo "" >> sbom-diff-node${{ matrix.node-version }}.md | |
| fi | |
| if [ ! -s added-components.txt ] && [ ! -s removed-components.txt ]; then | |
| echo "### ✅ No component changes detected" >> sbom-diff-node${{ matrix.node-version }}.md | |
| fi | |
| echo "Generated SBOM diff for Node.js ${{ matrix.node-version }}" | |
| else | |
| echo "No base SBOM found for comparison" | |
| fi | |
| publish-sbom: | |
| name: Publish SBOM to GitHub Pages | |
| runs-on: ubuntu-latest | |
| needs: generate-sbom | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| pages: write | |
| id-token: write | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| - name: Download SBOM artifacts | |
| uses: actions/download-artifact@abefc31eafcfbdf6c5336127c1346fdae79ff41c # v5.0.0 | |
| with: | |
| pattern: 'sbom-node*-${{ github.sha }}' | |
| merge-multiple: true | |
| - name: Create SBOM comparison report | |
| run: | | |
| echo "Creating SBOM comparison report..." | |
| # Compare SBOMs between Node versions | |
| if [ -f "sbom-node22.json" ] && [ -f "sbom-node24.json" ]; then | |
| echo "Comparing Node.js 22 vs 24 SBOMs..." | |
| components_22=$(jq '.components | length' sbom-node22.json) | |
| components_24=$(jq '.components | length' sbom-node24.json) | |
| cat > sbom-comparison-report.md << EOF | |
| # 🔍 SBOM Comparison Report | |
| ## Component Count by Node.js Version | |
| - **Node.js 22**: $components_22 components | |
| - **Node.js 24**: $components_24 components | |
| ## Differences | |
| EOF | |
| # Check if SBOMs are identical | |
| if cmp -s sbom-node22.json sbom-node24.json; then | |
| echo "- ✅ SBOMs are identical across Node.js versions" >> sbom-comparison-report.md | |
| else | |
| echo "- ⚠️ SBOMs differ between Node.js versions" >> sbom-comparison-report.md | |
| fi | |
| echo "" >> sbom-comparison-report.md | |
| echo "*Report generated: $(date -u)*" >> sbom-comparison-report.md | |
| fi | |
| - name: Setup GitHub Pages deployment | |
| run: | | |
| mkdir -p _site/sbom | |
| # Copy SBOM files | |
| if [ -f "sbom-node22.json" ]; then | |
| cp sbom-node22.json _site/sbom/ | |
| fi | |
| if [ -f "sbom-node24.json" ]; then | |
| cp sbom-node24.json _site/sbom/ | |
| # Use Node.js 24 as the primary SBOM | |
| cp sbom-node24.json _site/sbom/sbom.json | |
| fi | |
| # Copy security summaries | |
| cp sbom-security-summary-*.txt _site/sbom/ 2>/dev/null || true | |
| # Copy comparison report | |
| if [ -f "sbom-comparison-report.md" ]; then | |
| cp sbom-comparison-report.md _site/sbom/ | |
| fi | |
| # Create an index HTML file for SBOM viewing | |
| cat > _site/sbom/index.html << 'EOF' | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>SBOM - Conditional Paths Action</title> | |
| <style> | |
| body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 40px; } | |
| h1 { color: #333; } | |
| .sbom-list { list-style: none; padding: 0; } | |
| .sbom-list li { margin: 10px 0; } | |
| .sbom-list a { color: #0366d6; text-decoration: none; padding: 10px; display: inline-block; } | |
| .sbom-list a:hover { text-decoration: underline; } | |
| .back { margin-bottom: 20px; } | |
| .back a { color: #0366d6; text-decoration: none; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="back"> | |
| <a href="../">← Back to Documentation</a> | |
| </div> | |
| <h1>📋 Software Bill of Materials</h1> | |
| <p>CycloneDX v1.6 format SBOMs for conditional-paths-action</p> | |
| <ul class="sbom-list"> | |
| <li>📦 <a href="./sbom.json">Latest SBOM (Node.js 24)</a></li> | |
| <li>📦 <a href="./sbom-node22.json">SBOM for Node.js 22</a></li> | |
| <li>📦 <a href="./sbom-node24.json">SBOM for Node.js 24</a></li> | |
| <li>📊 <a href="./sbom-comparison-report.md">Comparison Report</a></li> | |
| </ul> | |
| <hr> | |
| <p><em>Generated: <script>document.write(new Date().toISOString())</script></em></p> | |
| </body> | |
| </html> | |
| EOF | |
| - name: Setup Pages | |
| uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 | |
| - name: Upload Pages artifact | |
| uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 | |
| with: | |
| path: '_site' | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 | |
| - name: Update dist SBOM in main branch | |
| run: | | |
| # Update the SBOM in dist directory for distribution | |
| if [ -f "sbom-node24.json" ]; then | |
| mkdir -p dist | |
| cp sbom-node24.json dist/sbom.json | |
| echo "✅ Updated dist/sbom.json with Node.js 24 SBOM" | |
| # Configure git | |
| git config --local user.email "[email protected]" | |
| git config --local user.name "SBOM Bot" | |
| # Add and commit the SBOM update | |
| git add dist/sbom.json | |
| if git diff --staged --quiet; then | |
| echo "No SBOM changes to commit" | |
| else | |
| git commit -m "chore: update SBOM with latest dependency information | |
| 🔒 Automated SBOM update with CycloneDX v1.6 format | |
| 📊 Generated from Node.js 22/24 compatibility matrix | |
| 🌐 View interactive SBOM: https://santosr2.github.io/conditional-paths-action/sbom/ | |
| 🤖 Generated with [Claude Code](https://claude.ai/code) | |
| Co-Authored-By: Claude <[email protected]>" | |
| git push origin main | |
| echo "✅ Committed updated SBOM to main branch" | |
| fi | |
| fi | |
| release-sbom: | |
| name: Attach SBOM to Release | |
| runs-on: ubuntu-latest | |
| needs: generate-sbom | |
| if: github.event_name == 'release' | |
| steps: | |
| - name: Download SBOM artifacts | |
| uses: actions/download-artifact@abefc31eafcfbdf6c5336127c1346fdae79ff41c # v5.0.0 | |
| with: | |
| pattern: 'sbom-node*-${{ github.sha }}' | |
| merge-multiple: true | |
| - name: Attach SBOM to release | |
| uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 | |
| with: | |
| files: | | |
| sbom-node22.json | |
| sbom-node24.json | |
| sbom-security-summary-*.txt | |
| tag_name: ${{ github.event.release.tag_name }} | |
| append_body: true | |
| body: | | |
| ## 📋 Software Bill of Materials (SBOM) | |
| This release includes comprehensive SBOMs in CycloneDX v1.4 format: | |
| - `sbom-node22.json` - Generated with Node.js 22 environment | |
| - `sbom-node24.json` - Generated with Node.js 24 environment | |
| - Security summaries with component validation reports | |
| **SBOM Statistics:** | |
| - Node.js 22: Components analyzed and validated | |
| - Node.js 24: Components analyzed and validated | |
| ### 🔍 SBOM Usage | |
| - **Compliance**: Meet software supply chain transparency requirements | |
| - **Security**: Track dependencies for vulnerability management | |
| - **Licensing**: Verify license compliance across the supply chain | |
| - **Auditing**: Complete dependency inventory for security audits | |
| sbom-summary: | |
| name: SBOM Generation Summary | |
| runs-on: ubuntu-latest | |
| needs: [generate-sbom, publish-sbom, release-sbom] | |
| if: always() | |
| steps: | |
| - name: Generate SBOM summary | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const generateStatus = '${{ needs.generate-sbom.result }}'; | |
| const publishStatus = '${{ needs.publish-sbom.result }}'; | |
| const releaseStatus = '${{ needs.release-sbom.result }}'; | |
| let summary = '# 📋 SBOM Generation Summary\n\n'; | |
| const statusIcon = (status) => { | |
| if (status === 'success') return '✅'; | |
| if (status === 'failure') return '❌'; | |
| if (status === 'skipped') return '⏭️'; | |
| return '⚠️'; | |
| }; | |
| summary += '## Job Results\n\n'; | |
| summary += `| Job | Node.js 22 | Node.js 24 | Status |\n`; | |
| summary += `|-----|------------|------------|--------|\n`; | |
| summary += `| SBOM Generation | ${statusIcon(generateStatus)} | ${statusIcon(generateStatus)} | ${generateStatus.toUpperCase()} |\n`; | |
| summary += `| Publish to Pages | ${statusIcon(publishStatus)} | ${statusIcon(publishStatus)} | ${publishStatus.toUpperCase()} |\n`; | |
| summary += `| Release Attachment | ${statusIcon(releaseStatus)} | ${statusIcon(releaseStatus)} | ${releaseStatus.toUpperCase()} |\n\n`; | |
| summary += '## SBOM Compliance Status\n\n'; | |
| if (generateStatus === 'success') { | |
| summary += '🎉 **COMPLIANT** - SBOMs generated successfully for both Node.js environments\n\n'; | |
| summary += '### ✅ Generated Artifacts\n'; | |
| summary += '- CycloneDX v1.4 format SBOMs\n'; | |
| summary += '- SPDX format SBOMs (where supported)\n'; | |
| summary += '- Security validation summaries\n'; | |
| summary += '- Component vulnerability analysis\n'; | |
| summary += '- Build provenance attestations\n'; | |
| } else { | |
| summary += '⚠️ **ATTENTION REQUIRED** - SBOM generation encountered issues\n\n'; | |
| summary += 'Please check the workflow logs for details.\n'; | |
| } | |
| if (context.eventName === 'pull_request') { | |
| summary += '\n### 📊 PR Impact\n'; | |
| summary += '- SBOM diff analysis completed\n'; | |
| summary += '- Component changes documented\n'; | |
| summary += '- Security validation performed\n'; | |
| } | |
| summary += '\n### 🔗 SBOM Resources\n'; | |
| summary += '- **[Interactive SBOM Viewer](https://santosr2.github.io/conditional-paths-action/sbom/)**\n'; | |
| summary += '- **[SBOM Security Summary](https://github.com/${{ github.repository }}/actions)**\n'; | |
| summary += '- **[CycloneDX Documentation](https://cyclonedx.org/)**\n'; | |
| summary += `\n---\n*Report generated: ${new Date().toISOString()}*\n`; | |
| core.summary.addRaw(summary); | |
| core.summary.write(); | |
| console.log(summary); |