complair.
Developer preview

Upload SBOMs from GitHub Actions

Push an SBOM to a product record on every release tag (or every push). Copy the workflow below into .github/workflows/sbom-upload.yml. No published Complair Marketplace action is required — this is a thin curl against the documented SBOM upload API.

Prerequisites

  • 1. Issue a product token. In the workspace, open the product, go to API tokens, click New token. Copy the token value once — it is not shown again.
  • 2. Store the token as a secret. In the GitHub repository: Settings → Secrets and variables → Actions → New repository secret. Name it COMPLAIR_SBOM_TOKEN.
  • 3. Decide how the SBOM is produced. The example below uses the CycloneDX/gh-node-module-generatebom action for Node projects. Swap in cyclonedx-bom, syft, cdxgen, or any tool that writes a CycloneDX/SPDX file.

Workflow YAML

name: SBOM upload to Complair

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:

jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Generate an SBOM (swap this for the generator your stack uses)
      - name: Generate CycloneDX SBOM
        run: |
          npx --yes @cyclonedx/cdxgen -o sbom.cdx.json

      - name: Upload to Complair
        env:
          COMPLAIR_SBOM_TOKEN: ${{ secrets.COMPLAIR_SBOM_TOKEN }}
          RELEASE_VERSION: ${{ github.ref_name }}
        run: |
          curl --fail-with-body -sS -X POST \
            "https://complair.eu/api/v1/sboms?format=cyclonedx_1_5&release_version=${RELEASE_VERSION}" \
            -H "Authorization: Bearer $COMPLAIR_SBOM_TOKEN" \
            -H "Content-Type: application/octet-stream" \
            -H "Idempotency-Key: ${{ github.run_id }}-${{ github.run_attempt }}" \
            --data-binary @sbom.cdx.json

Notes

  • Idempotency. The example uses ${{ github.run_id }}-${{ github.run_attempt }} as the idempotency key, so re-runs of the same job won't double-ingest.
  • release_version. Tag pushes (on: push: tags:) populate github.ref_name with the tag (e.g. v1.4.2). The SBOM links to the matching product release if one exists; otherwise it lands on the product without a release binding.
  • SPDX / package-lock / Gemfile.lock. Swap the format query param and the --data-binary @<file> reference. See the SBOM upload reference for all four accepted formats.
  • Failure modes. --fail-with-body makes curl exit non-zero on a 4xx/5xx with the JSON error visible in the job log. The action will fail loud, not silent.

GitLab CI

A GitLab CI snippet is on the roadmap. The endpoint is identical, so a minimal pipeline job is straightforward to adapt:

sbom:
  stage: release
  rules:
    - if: $CI_COMMIT_TAG
  script:
    - npx --yes @cyclonedx/cdxgen -o sbom.cdx.json
    - |
      curl --fail-with-body -sS -X POST \
        "https://complair.eu/api/v1/sboms?format=cyclonedx_1_5&release_version=${CI_COMMIT_TAG}" \
        -H "Authorization: Bearer $COMPLAIR_SBOM_TOKEN" \
        -H "Content-Type: application/octet-stream" \
        --data-binary @sbom.cdx.json

Add COMPLAIR_SBOM_TOKEN as a masked variable in the project settings before enabling the job.