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'

      - 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")
          MISSING_LICENSES=$(jq '[.components[] | select((.licenses // []) | length == 0)] | 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: $MISSING_LICENSES components missing license metadata"
          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}>"
