n8n/.github/workflows/sbom-generation-callable.yml
Declan Carroll 29735c7a04
chore: Standardize license metadata across all first-party packages and tighten SBOM pipeline (no-changelog) (#31880)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-08 10:19:32 +00:00

104 lines
4.0 KiB
YAML

name: 'Release: Attach SBOM'
on:
workflow_call:
inputs:
n8n_version:
description: 'N8N version to generate SBOM for'
required: true
type: string
release_tag_ref:
description: 'Git reference to checkout (e.g. n8n@1.2.3)'
required: true
type: string
secrets:
QBOT_SLACK_TOKEN:
required: true
workflow_dispatch:
inputs:
n8n_version:
description: 'N8N version to generate SBOM for'
required: true
type: string
release_tag_ref:
description: 'Git reference to checkout (e.g. n8n@1.2.3)'
required: true
type: string
permissions:
contents: write
id-token: write
attestations: write
jobs:
generate-sbom:
name: Generate and Attach SBOM to Release
runs-on: ubuntu-latest
timeout-minutes: 15
# No continue-on-error: SBOM is now the source of truth for
# THIRD_PARTY_LICENSES.md (served by the /third-party-licenses endpoint
# and attached to the GitHub release). A generation failure must block
# the release rather than silently shipping a stale or missing manifest.
steps:
- name: Checkout release tag
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.release_tag_ref }}
- name: Build production deployment artifact
uses: ./.github/actions/setup-nodejs
with:
build-command: 'pnpm build:deploy'
env:
# Opt in to SBOM + THIRD_PARTY_LICENSES.md generation. Regular CI Docker
# builds skip it; only this release SBOM job and explicit local opt-ins
# produce sbom-source.cdx.json + packages/cli/THIRD_PARTY_LICENSES.md.
N8N_GENERATE_LICENSES: 'true'
# Release-blocking gate. build:deploy already enriches + gates the SBOM via
# the generate-licenses pipeline; re-run the gate here as an explicit,
# un-skippable check on the exact artifact we are about to attest, so an
# unlicensed or non-SPDX component can never reach the signed attestation.
- name: Gate SBOM on resolved SPDX licenses
run: |
node scripts/licenses/check-sbom-licenses.mjs \
sbom-source.cdx.json \
--allow-ref=LicenseRef-n8n-sustainable-use --allow-ref=LicenseRef-n8n-enterprise
- name: Attest SBOM for release
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
with:
subject-path: './package.json'
sbom-path: 'sbom-source.cdx.json'
- name: Attach SBOM, VEX, and license manifest to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG_REF: ${{ inputs.release_tag_ref }}
run: |
gh release upload "$RELEASE_TAG_REF" \
sbom-source.cdx.json \
security/vex.openvex.json \
packages/cli/THIRD_PARTY_LICENSES.md \
--clobber
COMPONENT_COUNT=$(jq '.components | length' sbom-source.cdx.json 2>/dev/null || echo "unknown")
VEX_STATEMENTS=$(jq '.statements | length' security/vex.openvex.json 2>/dev/null || echo "0")
echo "SBOM, VEX, and license manifest attached to release"
echo " - SBOM: $COMPONENT_COUNT components from shipped artifact (no devDeps, no optional deps)"
echo " - SBOM: all components carry a resolved SPDX license (gated before attest)"
echo " - VEX: $VEX_STATEMENTS CVE statements"
echo " - THIRD_PARTY_LICENSES.md: rendered from SBOM (same artefact served by /third-party-licenses endpoint)"
- name: Notify Slack on failure
if: failure()
env:
SLACK_TOKEN: ${{ secrets.QBOT_SLACK_TOKEN }}
RELEASE_TAG_REF: ${{ inputs.release_tag_ref }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
node .github/scripts/slack/notify.mjs \
--channel '#alerts-build' \
--text "<${RUN_URL}|SBOM generation and attachment failed for release ${RELEASE_TAG_REF}>"