GitHub Actions¶
Automate license compliance checks on every push and pull request with the official Feluda GitHub Action.
Quick Start¶
Add this workflow to .github/workflows/feluda.yml:
name: Feluda Scan
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anistark/feluda@v1
with:
fail-on-restrictive: true
fail-on-incompatible: true
update-badge: true
Feluda now exits non-zero whenever restrictive or incompatible licenses show up, and update-badge refreshes the README badge.
Action Inputs¶
Input |
Default |
Description |
|---|---|---|
|
|
Fail the workflow when restrictive licenses are found |
|
|
Fail the workflow when incompatible licenses are found |
|
|
Update the Feluda badge in README |
|
(all) |
Filter scan to a specific language ecosystem |
|
(none) |
Declare project license for compatibility checks |
|
|
Treat unknown licenses as incompatible |
Complete Workflow Example¶
Full workflow with compliance artifacts and SBOM generation:
name: Feluda Compliance
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Feluda Scan
uses: anistark/feluda@v1
with:
fail-on-restrictive: true
fail-on-incompatible: true
update-badge: true
- name: Generate Compliance Artifacts
run: |
echo "1" | feluda generate
echo "2" | feluda generate
feluda sbom spdx --output sbom.spdx.json
feluda sbom cyclonedx --output sbom.cyclonedx.json
feluda sbom validate sbom.spdx.json --output sbom-spdx-validation.txt
feluda sbom validate sbom.cyclonedx.json --output sbom-cyclonedx-validation.txt
- name: Upload Compliance Artifacts
uses: actions/upload-artifact@v4
with:
name: compliance-artifacts
path: |
NOTICE
THIRD_PARTY_LICENSES.md
sbom.spdx.json
sbom.cyclonedx.json
sbom-spdx-validation.txt
sbom-cyclonedx-validation.txt
GitHub Advanced Security (SARIF)¶
Surface license findings directly in the repository’s Security tab using GitHub Advanced Security code scanning.
name: Feluda SARIF Scan
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
sarif:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- name: Run Feluda license scan
run: feluda --ci-format sarif --output-file results.sarif
- name: Upload SARIF to GitHub Advanced Security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
Feluda maps restrictive licenses to SARIF warning level and incompatible
licenses (when a project license is specified) to error level. A clean scan still
produces a valid SARIF file with an empty results array, so the upload step never
needs to be skipped.
Tip
Pass --project-license MIT (or your actual license) to enable incompatibility
detection and get error-level findings alongside warning-level ones.
GitHub Token Configuration¶
Large scans may hit GitHub API rate limits. Store a GITHUB_TOKEN secret with repo scope for private dependencies.
- uses: anistark/feluda@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
fail-on-restrictive: true
Tip
The default GITHUB_TOKEN provided by GitHub Actions works for public repositories. Use a Personal Access Token for private dependency scanning.
Scan Remote Repository¶
Scan an external repository from your workflow:
- name: Scan External Repo
run: |
feluda --repo git@github.com:org/private-repo.git \
--ssh-key "$HOME/.ssh/ci_key" \
--ssh-passphrase "${{ secrets.SSH_PASSPHRASE }}"
Important
Supply either SSH or HTTPS credentials—not both—unless your CI job truly needs the fallback.
Badge Updates¶
Keep the README badge current by enabling update-badge:
- uses: anistark/feluda@v1
with:
update-badge: true
The action updates the badge snippet so your README always reflects the most recent scan status.
Badge markdown:
[](https://github.com/anistark/feluda)
Workflow Triggers¶
Common trigger configurations:
On every push and PR:
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
Scheduled nightly scan:
on:
schedule:
- cron: '0 2 * * *' # 2 AM UTC daily
Manual dispatch:
on:
workflow_dispatch:
inputs:
language:
description: 'Language to scan'
required: false
default: ''