Skip to content

Repository files navigation

🐍📋 Python SBOM Generator Action

A comprehensive GitHub Action that generates CycloneDX Software Bill of Materials (SBOM) reports for Python projects with automatic detection and support for different Python dependency management tools.

python-sbom-action

🚀 Features

  • Multi-tool Support: Automatically detects and works with:

    • uv (uv.lock)
    • PDM (pdm.lock)
    • Poetry (poetry.lock)
    • Pipenv (Pipfile.lock)
    • pip-tools (requirements.txt with hashes)
    • Plain pip (requirements.txt)
  • Smart Detection: Automatically identifies the dependency management tool used in your project

  • Supported Formats: Generate SBOM in JSON, XML, or both

  • Flexible Configuration: Control inclusion of development dependencies, output formats, and more

  • Comprehensive Validation: Validates generated SBOM files for correctness

  • Rich Outputs: Provides detailed information about the generated SBOMs

📋 Quick Start

Basic Usage

name: "Generate SBOM"on: [push]jobs:
sbom:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: "Generate SBOM"uses: lfreleng-actions/python-sbom-action@v1

With Artifact Upload

name: "SBOM Generation"on: [push]jobs:
sbom:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: "Generate SBOM"id: sbomuses: lfreleng-actions/python-sbom-action@v1with:
include_dev: "false"sbom_format: "both"
- name: "Upload SBOM artifacts"uses: actions/upload-artifact@v4with:
name: sbom-filespath: | sbom-cyclonedx.json sbom-cyclonedx.xmlretention-days: 90
- name: "Summary"run: | echo "SBOM count: ${{ steps.sbom.outputs.component_count }}" echo "Tool used: ${{ steps.sbom.outputs.dependency_manager }}"

Advanced Configuration with Custom Output Directory

steps:
- name: "Generate SBOM with dev dependencies"uses: lfreleng-actions/python-sbom-action@v1with:
python_version: "3.11"include_dev: "true"sbom_format: "json"sbom_spec_version: "1.6"path_prefix: "src/myproject"# Source code locationoutput_directory: "reports"# Custom report locationfilename_prefix: "my-project-sbom"
- name: "Upload SBOM artifacts"uses: actions/upload-artifact@v4with:
name: sbom-filespath: reports/my-project-sbom.json

📥 Inputs

NameRequiredDefaultDescription
python_versionNo3.12Python version for SBOM generation
include_devNofalseInclude dev dependencies in SBOM
sbom_formatNobothSBOM format: 'json', 'xml', or 'both'
sbom_spec_versionNo1.5CycloneDX specification version
filename_prefixNosbom-cyclonedxBase filename for SBOM output
path_prefixNo.Directory location containing project code
output_directoryNo.Directory location to write SBOM reports
fail_on_errorNotrueFail action if SBOM generation fails

Input Parameter Notes

  • path_prefix vs output_directory: These parameters serve different purposes. path_prefix specifies where your Python project source code is, while output_directory specifies where the SBOM/report files get saved. This allows you to generate SBOMs from source code in one directory and write the reports to another location.

  • filename_prefix: This parameter sets the base filename for SBOM outputs (without file extension). For example, filename_prefix: "my-app" will generate my-app.json and my-app.xml files. The action automatically appends the appropriate extensions based on the sbom_format setting.

📤 Outputs

NameDescription
sbom_json_pathFull path to generated JSON SBOM file
sbom_xml_pathFull path to generated XML SBOM file
dependency_managerDetected Python dependency manager
component_countNumber of components found in the generated SBOM

🛠️ Supported Tools & Detection

Detection Priority

The action detects dependency management tools in the following priority order:

  1. uv - uv.lock present
  2. PDM - pdm.lock present
  3. Poetry - poetry.lock present
  4. Pipenv - Pipfile.lock present
  5. pip-tools - requirements.txt with requirements.in or version pins
  6. pip - Plain requirements.txt (fallback)

Tool-Specific Behavior

ToolLock FileInstall CommandDev Dependencies
uvuv.lockuv sync --locked [--no-dev]Via include_dev
PDMpdm.lockpdm sync [--prod] --no-selfVia include_dev
Poetrypoetry.lockpoetry install --no-rootVia include_dev
PipenvPipfile.lockpipenv install --deployVia include_dev
pip-toolsrequirements.txtpip install -r requirements.txtVia dev
piprequirements.txtpip install -r requirements.txtVia dev

📚 Usage Examples

Tool-Specific Examples

uv Projects

# For projects with uv.lock
- name: "Generate SBOM (uv project)"uses: lfreleng-actions/python-sbom-action@v1with:
python_version: "3.12"include_dev: "false"# Excludes dev dependencies for production SBOM

PDM Projects

# For projects with pdm.lock
- name: "Generate SBOM (PDM project)"uses: lfreleng-actions/python-sbom-action@v1with:
python_version: "3.11"include_dev: "true"# Include dev dependenciessbom_format: "json"# JSON format for CI integration

Poetry Projects

# For projects with poetry.lock
- name: "Generate SBOM (Poetry project)"uses: lfreleng-actions/python-sbom-action@v1with:
include_dev: "true"filename_prefix: "poetry-sbom"

Pipenv Projects

# For projects with Pipfile.lock
- name: "Generate SBOM (Pipenv project)"uses: lfreleng-actions/python-sbom-action@v1with:
sbom_spec_version: "1.6"fail_on_error: "false"# Continue on errors

pip-tools Projects

# For projects with requirements.txt + requirements.in
- name: "Generate SBOM (pip-tools project)"uses: lfreleng-actions/python-sbom-action@v1with:
include_dev: "true"# Will use requirements-dev.txt if present

Plain pip Projects

# For projects with requirements.txt files
- name: "Generate SBOM (pip project)"uses: lfreleng-actions/python-sbom-action@v1with:
fail_on_error: "false"# Recommended for pip projects

Advanced Patterns

Path Prefix and Output Directory Support

name: "SBOM with Path Prefix and Custom Output"on: [push]jobs:
sbom:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: "Generate SBOM for project in subdirectory"uses: lfreleng-actions/python-sbom-action@v1with:
path_prefix: "backend/api"# Where the source code isoutput_directory: "sbom-reports"# Where to write SBOM filesfilename_prefix: "api-sbom"# Creates api-sbom.jsonsbom_format: "json"
- name: "Upload SBOM"uses: actions/upload-artifact@v4with:
name: api-sbompath: sbom-reports/api-sbom.json

Filename Prefix Examples

# Different filename prefixes create different output files
- name: "Generate SBOMs with custom names"uses: lfreleng-actions/python-sbom-action@v1with:
filename_prefix: "my-app-v1.2.3"# Creates: my-app-v1.2.3.json, my-app-v1.2.3.xmlsbom_format: "both"
- name: "Generate timestamped SBOM"uses: lfreleng-actions/python-sbom-action@v1with:
filename_prefix: "sbom-${{ github.sha }}"# Creates: sbom-abc123def.jsonsbom_format: "json"

Monorepo Support with Centralized Reports

name: "Multi-project SBOM"on: [push]jobs:
sbom:
runs-on: ubuntu-lateststrategy:
matrix:
project: [api, worker, dashboard, shared]steps:
- uses: actions/checkout@v4
- name: "Generate SBOM for ${{ matrix.project }}"id: sbomuses: lfreleng-actions/python-sbom-action@v1with:
path_prefix: "./${{ matrix.project }}"# Source code locationoutput_directory: "sbom-reports"# Centralized report locationfilename_prefix: "sbom-${{ matrix.project }}"include_dev: "false"
- name: "Upload ${{ matrix.project }} SBOM"uses: actions/upload-artifact@v4with:
name: sbom-${{ matrix.project }}path: sbom-reports/sbom-${{ matrix.project }}.*
- name: "Summary for ${{ matrix.project }}"run: | echo "Generated SBOM for ${{ matrix.project }}" echo "Tool: ${{ steps.sbom.outputs.dependency_manager }}" echo "Components: ${{ steps.sbom.outputs.component_count }}"

Integration with Security Scanning

name: "SBOM + Security Scan"on: [push]jobs:
security:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: "Generate SBOM"id: sbomuses: lfreleng-actions/python-sbom-action@v1with:
sbom_format: "json"include_dev: "false"output_directory: "security-reports"
- name: "Security scan with Grype"uses: anchore/scan-action@v3with:
path: "${{ steps.sbom.outputs.sbom_json_path }}"format: "cyclonedx-json"

Release Automation with Custom Output

name: "Release with SBOM"on:
release:
types: [published]jobs:
sbom:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: "Generate production SBOM"uses: lfreleng-actions/python-sbom-action@v1with:
include_dev: "false"sbom_format: "both"sbom_spec_version: "1.6"output_directory: "release-artifacts"filename_prefix: "production-sbom"
- name: "Attach SBOM to release"uses: softprops/action-gh-release@v1with:
files: | release-artifacts/production-sbom.json release-artifacts/production-sbom.xml

Scheduled SBOM Updates

name: "Weekly SBOM Update"on:
schedule:
- cron: "0 2 * * 1"# Monday 2 AM UTCworkflow_dispatch:
jobs:
sbom:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: "Generate weekly SBOM"id: sbomuses: lfreleng-actions/python-sbom-action@v1
- name: "Upload current SBOM"uses: actions/upload-artifact@v4with:
name: sbom-cyclonxpath: sbom-cyclonedx.*retention-days: 30

Error Handling

Graceful Error Handling

- name: "Generate SBOM with error handling"id: sbomuses: lfreleng-actions/python-sbom-action@v1with:
fail_on_error: "false"continue-on-error: true
- name: "Handle SBOM generation failure"if: steps.sbom.outcome == 'failure'run: | echo "::warning::SBOM generation failed, continuing without SBOM" echo "SBOM generation failed" >> $GITHUB_STEP_SUMMARY

Conditional Generation

name: "Conditional SBOM"on: [push, pull_request]jobs:
sbom:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: "Check for Python project"id: checkrun: | if [[ -f "pyproject.toml" || -f "requirements.txt" || \ -f "Pipfile" ]]; then echo "is_python=true" >> $GITHUB_OUTPUT else echo "is_python=false" >> $GITHUB_OUTPUT fi - name: "Generate SBOM"if: steps.check.outputs.is_python == 'true'uses: lfreleng-actions/python-sbom-action@v1with:
fail_on_error: "false"

🔧 Implementation Details

SBOM Generation Process

  1. Detection: Scans for supported dependency files in priority order
  2. Tool Setup: Installs the detected dependency management tool
  3. Dependency Installation: Installs dependencies according to lock files
  4. SBOM Generation: Uses CycloneDX Python library to generate SBOM from environment
  5. Validation: Validates generated SBOM files for correctness
  6. Outputs: Provides paths and metadata about generated files

CycloneDX Integration

The action uses the CycloneDX Python library to generate SBOMs by analyzing the Python environment after dependency installation. This approach ensures the SBOM accurately reflects the resolved dependency tree.

Error Handling and Recovery

  • Graceful Degradation: Can continue on errors when fail_on_error: false
  • Comprehensive Logging: Detailed output for troubleshooting
  • Validation: Built-in SBOM file validation with helpful error messages

🔍 Troubleshooting

Common Issues

No supported dependency files found

  • Ensure your project has one of the supported lock/requirements files
  • Check that the file is in the path_prefix directory specified

Tool installation fails

  • Verify the Python version is compatible with your dependency manager
  • Check if there are any conflicting system packages

SBOM generation fails

  • Ensure all dependencies install without errors
  • Check for missing system dependencies required by Python packages
  • Try with fail_on_error: false to get more diagnostic information

Debug Mode

Set fail_on_error: false to enable verbose error handling and continue execution when errors occur.

- name: "Generate SBOM (debug mode)"uses: lfreleng-actions/python-sbom-action@v1with:
fail_on_error: "false"env:
ACTIONS_STEP_DEBUG: trueRUNNER_DEBUG: 1

📋 Best Practices

1. Pin Action Versions

# Good: Pin to specific versionuses: lfreleng-actions/python-sbom-action@v1.2.3# Better: Pin to commit SHA for securityuses: lfreleng-actions/python-sbom-action@a1b2c3d4...

2. Appropriate Triggers

# Trigger on dependency changeson:
push:
paths:
- "pyproject.toml"
- "*.lock"
- "requirements*.txt"
- "Pipfile.lock"

3. Retention Policies

# Short retention for PR builds
- name: "Upload SBOM (PR)"if: github.event_name == 'pull_request'uses: actions/upload-artifact@v4with:
retention-days: 7# Longer retention for main branch
- name: "Upload SBOM (main)"if: github.ref == 'refs/heads/main'uses: actions/upload-artifact@v4with:
retention-days: 90

4. Output Directory Organization

# Organize SBOMs by environment/purpose
- name: "Generate production SBOM"uses: lfreleng-actions/python-sbom-action@v1with:
include_dev: "false"output_directory: "sbom/production"filename_prefix: "app-prod"
- name: "Generate development SBOM"uses: lfreleng-actions/python-sbom-action@v1with:
include_dev: "true"output_directory: "sbom/development"filename_prefix: "app-dev"

5. Resource Optimization

jobs:
sbom:
runs-on: ubuntu-latesttimeout-minutes: 15# Reasonable timeoutsteps:
- name: "Generate SBOM"uses: lfreleng-actions/python-sbom-action@v1with:
python_version: "3.12"# Use latest stable

🤝 Contributing

Contributions are welcome! Please see our contributing guidelines and code of conduct.

📄 License

This project uses the Apache License 2.0. See the LICENSE file for details.

🔗 Related Projects

About

Generates an SBOM for Python projects

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages