diff --git a/.github/actions/fossa-guard/README.md b/.github/actions/fossa-guard/README.md index fefa957..bafccc8 100644 --- a/.github/actions/fossa-guard/README.md +++ b/.github/actions/fossa-guard/README.md @@ -39,6 +39,19 @@ The `fossa-guard` GitHub Action integrates with the FOSSA API to fetch and proce | `github_run_id` | No | GitHub Actions run ID for build links (optional). | | `github_server_url` | No | GitHub server URL (default: https://github.com) (optional). | +### PR Integration Inputs (Optional) + +| Input | Default | Description | +|-------|---------|-------------| +| `github_token` | `${{ github.token }}` | GitHub token for PR comments and status checks | +| `enable_pr_comment` | `false` | Enable PR commenting (`true`/`false`) | +| `enable_status_check` | `false` | Enable GitHub status checks (`true`/`false`) | +| `status_check_name` | `FOSSA Guard` | Custom name for status checks | +| `pr_comment_max_violations` | `5` | Max violations shown in PR comment | +| `enable_diff_mode` | `false` | Enable diff mode to show only new issues (`true`/`false`) | +| `diff_base_revision_sha` | (auto-detect) | Base revision SHA to compare against (optional - auto-detects default branch) | +| `enable_license_enrichment` | `true` | Show declared/discovered license indicators (`true`/`false`) | + ### Issue Types Explained - **policy_conflict**: There is a known explicit policy violation (FOSSA terminology). This means the license or dependency is denied in your FOSSA policy and should block the build. - **policy_flag**: The license needs to be reviewed or is unknown (FOSSA terminology). This means the license or dependency is flagged for review or is uncategorized in your FOSSA policy and may require manual attention. @@ -52,10 +65,18 @@ The `fossa-guard` GitHub Action integrates with the FOSSA API to fetch and proce | Mode | Description | |--------|-----------------------------------------------------------------------------------------------| -| BLOCK | Fails the build if violations matching `block_on` are found. Prints a Markdown/HTML summary. | -| REPORT | Generates and sends Slack reports (requires `slack_token` and `slack_channel`). Prints a Markdown/HTML summary. Intended for reporting only. Exit code 1 if Slack reporting fails and REPORT is the only action. | +| BLOCK | Fails the build if violations matching `block_on` are found (exit code 2). PR comments show violations. Status checks fail. Prints a Markdown/HTML summary. | +| REPORT | Shows violations in PR comments and status checks (marked as failed), but build passes (exit code 0). Useful for gradual rollout. Also sends Slack reports if configured. | | BLOCK,REPORT | Combines both actions - blocks on violations AND sends Slack reports. Exit code 2 if blocking violations found (Slack failure won't affect exit code). Exit code 0 if no blocking violations. | +### Mode Behavior Clarification + +**Important**: PR comments and status checks work identically in both BLOCK and REPORT modes. The only difference is: +- **REPORT mode**: Shows violations in status check (failure), but build passes (exit 0) +- **BLOCK mode**: Shows violations in status check (failure), and build fails (exit 2) + +This allows you to enable PR integration in REPORT mode first for visibility without blocking builds, then switch to BLOCK mode when ready to enforce compliance. + --- ## Business Logic @@ -101,6 +122,179 @@ jobs: --- +## Pull Request Workflow Examples + +### Basic PR Integration + +```yaml +name: FOSSA PR Check + +on: + pull_request: + branches: [main] + +permissions: + pull-requests: write # For PR comments + checks: write # For status checks + issues: write # For PR comments + +jobs: + fossa-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: FOSSA Guard with PR Integration + uses: SolaceDev/solace-public-workflows/.github/actions/fossa-guard@main + with: + fossa_api_key: ${{ secrets.FOSSA_API_KEY }} + fossa_project_id: ${{ secrets.FOSSA_PROJECT_ID }} + fossa_category: licensing + fossa_mode: BLOCK + fossa_branch: ${{ github.event.pull_request.number && 'PR' || github.event.repository.default_branch }} + fossa_revision: ${{ github.event.pull_request.head.ref || github.sha }} + block_on: policy_conflict,policy_flag + # PR features (auto-enabled) + github_token: ${{ github.token }} + enable_pr_comment: true + enable_status_check: true +``` + +### With Diff Mode (Recommended for PRs) + +Diff mode shows only newly introduced issues, making PR reviews more focused: + +```yaml +name: FOSSA PR Check with Diff Mode + +on: + pull_request: + branches: [main, master] + +permissions: + pull-requests: write # For PR comments + checks: write # For status checks + issues: write # For PR comments + +jobs: + fossa-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: FOSSA Guard - Licensing (Diff Mode) + uses: SolaceDev/solace-public-workflows/.github/actions/fossa-guard@main + with: + fossa_api_key: ${{ secrets.FOSSA_API_KEY }} + fossa_project_id: ${{ secrets.FOSSA_PROJECT_ID }} + fossa_category: licensing + fossa_mode: BLOCK + fossa_branch: PR + fossa_revision: ${{ github.event.pull_request.head.ref }} + block_on: policy_conflict + # Diff mode - auto-detects base branch + enable_diff_mode: true + # PR Integration + github_token: ${{ github.token }} + enable_pr_comment: true + enable_status_check: true + + - name: FOSSA Guard - Vulnerabilities (Diff Mode) + uses: SolaceDev/solace-public-workflows/.github/actions/fossa-guard@main + with: + fossa_api_key: ${{ secrets.FOSSA_API_KEY }} + fossa_project_id: ${{ secrets.FOSSA_PROJECT_ID }} + fossa_category: vulnerability + fossa_mode: BLOCK + fossa_branch: PR + fossa_revision: ${{ github.event.pull_request.head.ref }} + block_on: critical,high + # Diff mode + enable_diff_mode: true + # PR Integration + github_token: ${{ github.token }} + enable_pr_comment: true + enable_status_check: true +``` + +### REPORT Mode Example (Non-Blocking) + +Use REPORT mode for gradual rollout - violations are shown but don't fail the build: + +```yaml +- name: FOSSA Guard (Report Mode - Non-Blocking) + uses: SolaceDev/solace-public-workflows/.github/actions/fossa-guard@main + with: + fossa_api_key: ${{ secrets.FOSSA_API_KEY }} + fossa_project_id: ${{ secrets.FOSSA_PROJECT_ID }} + fossa_category: licensing + fossa_mode: REPORT # Show violations but don't fail build + block_on: policy_conflict,policy_flag + enable_diff_mode: true + github_token: ${{ github.token }} + enable_pr_comment: true + enable_status_check: true # Status shows failure but build passes +``` + +### Branch Protection Setup + +To enforce FOSSA checks before merging: + +1. Repository Settings → Branches → Add protection rule +2. Enable "Require status checks to pass before merging" +3. Add required checks: + - `FOSSA Guard (licensing)` + - `FOSSA Guard (vulnerability)` (if applicable) + +--- + +## Diff Mode + +Diff mode compares the PR branch against the base branch to show only newly introduced issues, making PR reviews more focused. + +### How It Works + +- Compares current scan results against base branch scan results +- Shows "X new, Y total (Z in base)" in PR comments for clarity +- Auto-detects default branch (main/master) if `diff_base_revision_sha` not provided +- Uses three-tier matching strategy for accurate comparison + +### Requirements + +- Base branch must have been scanned by FOSSA for comparison to work +- Best used with PR workflows to focus on newly introduced issues + +### Usage + +```yaml +with: + enable_diff_mode: true + # Optional - will auto-detect if not provided + diff_base_revision_sha: ${{ github.event.pull_request.base.sha }} +``` + +--- + +## PR Comment Features + +- **Smart deduplication**: One comment per category (licensing/vulnerability) - updates existing, doesn't duplicate +- **Top N violations**: Shows top N violations (default: 5, configurable via `pr_comment_max_violations`) +- **Clear explanations**: Shows what's blocking vs what needs review +- **Direct links**: Links to full scan report and FOSSA dashboard +- **Blocking status**: For vulnerabilities, shows actual blocking status (e.g., "✅ No blocking issues found (configured to block on: HIGH)") +- **Diff mode support**: Shows "X new, Y total (Z in base)" when diff mode is enabled + +--- + +## Status Check Behavior + +- Status checks show **failure** when violations exist matching `block_on` rules (regardless of mode) +- Status checks show **success** when no violations found or all issues are non-blocking +- Can be used with branch protection rules to enforce compliance +- Works in both BLOCK and REPORT modes (only exit code differs) + +--- + ## Notes - The action prints a Markdown summary to the GitHub Actions log. - If the `GITHUB_STEP_SUMMARY` environment variable is set, the summary is also written to the step summary for rich UI display. @@ -109,3 +303,49 @@ jobs: - Slack integration parameters (`slack_token`, `slack_channel`, `slack_thread_ts`) allow posting formatted reports to Slack channels or threads. - GitHub context parameters (`github_repository`, `github_run_id`, `github_server_url`) allow linking reports to specific repositories and builds. - For more details, see the script source and comments. + +--- + +## Troubleshooting + +### PR Comment Not Appearing + +**Check:** +- `github_token` input is set (defaults to `${{ github.token }}`) +- Workflow has `pull-requests: write` and `issues: write` permissions +- Running in `pull_request` event (not `push`) +- `enable_pr_comment` is not set to `false` + +### Status Check Not Appearing + +**Check:** +- Workflow has `checks: write` permission +- Using PR head SHA: `fossa_revision: ${{ github.event.pull_request.head.ref || github.sha }}` +- `enable_status_check` is not set to `false` + +### Diff Mode Not Working + +**Check:** +- The PR branch revision has been scanned by FOSSA (ensure FOSSA scan runs before FOSSA Guard) +- The base branch revision exists in FOSSA scan history +- `enable_diff_mode` is set to `true` +- FOSSA project exists and has scan data for both revisions + +### Token Permission Errors + +Add to workflow: +```yaml +permissions: + pull-requests: write + checks: write + issues: write +``` + +--- + + +## Reference Links + +- **Implementation PR**: https://github.com/SolaceDev/maas-build-actions/pull/581 +- **Live Example**: https://github.com/SolaceDev/solace-agent-mesh-enterprise/pull/458 +- **Full Documentation**: See maas-build-actions repository `scripts/fossa-guard/fossa-guard-usage.md` diff --git a/.github/actions/fossa-guard/action.yaml b/.github/actions/fossa-guard/action.yaml index 28584ab..6cf797f 100644 --- a/.github/actions/fossa-guard/action.yaml +++ b/.github/actions/fossa-guard/action.yaml @@ -49,10 +49,41 @@ inputs: github_server_url: description: "GitHub server URL (default: https://github.com) (optional)" required: false + github_token: + description: "GitHub token for PR comments and status checks" + required: false + default: ${{ github.token }} + enable_pr_comment: + description: "Enable PR commenting (true/false)" + required: false + default: "false" + enable_status_check: + description: "Enable GitHub status checks (true/false)" + required: false + default: "false" + status_check_name: + description: "Custom name for GitHub status check" + required: false + default: "FOSSA Guard" + pr_comment_max_violations: + description: "Maximum violations to show in PR comment" + required: false + default: "5" + enable_diff_mode: + description: "Enable diff mode to show only new issues (true/false)" + required: false + default: "false" + diff_base_revision_sha: + description: "Base revision SHA to compare against (optional - auto-detects default branch)" + required: false + enable_license_enrichment: + description: "Show declared/discovered license indicators (true/false)" + required: false + default: "true" runs: using: docker - image: docker://ghcr.io/solacedev/maas-build-actions:master + image: docker://ghcr.io/solacedev/maas-build-actions:latest entrypoint: /bin/sh args: - -c @@ -73,6 +104,14 @@ runs: if [ -n "$INPUT_GITHUB_REPOSITORY" ]; then export GITHUB_REPOSITORY="$INPUT_GITHUB_REPOSITORY"; fi if [ -n "$INPUT_GITHUB_RUN_ID" ]; then export GITHUB_RUN_ID="$INPUT_GITHUB_RUN_ID"; fi if [ -n "$INPUT_GITHUB_SERVER_URL" ]; then export GITHUB_SERVER_URL="$INPUT_GITHUB_SERVER_URL"; fi + if [ -n "$INPUT_GITHUB_TOKEN" ]; then export GITHUB_TOKEN="$INPUT_GITHUB_TOKEN"; fi + if [ -n "$INPUT_ENABLE_PR_COMMENT" ]; then export ENABLE_PR_COMMENT="$INPUT_ENABLE_PR_COMMENT"; fi + if [ -n "$INPUT_ENABLE_STATUS_CHECK" ]; then export ENABLE_STATUS_CHECK="$INPUT_ENABLE_STATUS_CHECK"; fi + if [ -n "$INPUT_STATUS_CHECK_NAME" ]; then export STATUS_CHECK_NAME="$INPUT_STATUS_CHECK_NAME"; fi + if [ -n "$INPUT_PR_COMMENT_MAX_VIOLATIONS" ]; then export PR_COMMENT_MAX_VIOLATIONS="$INPUT_PR_COMMENT_MAX_VIOLATIONS"; fi + if [ -n "$INPUT_ENABLE_DIFF_MODE" ]; then export ENABLE_DIFF_MODE="$INPUT_ENABLE_DIFF_MODE"; fi + if [ -n "$INPUT_DIFF_BASE_REVISION_SHA" ]; then export DIFF_BASE_REVISION_SHA="$INPUT_DIFF_BASE_REVISION_SHA"; fi + if [ -n "$INPUT_ENABLE_LICENSE_ENRICHMENT" ]; then export ENABLE_LICENSE_ENRICHMENT="$INPUT_ENABLE_LICENSE_ENRICHMENT"; fi echo "Debug: Inputs:" echo "FOSSA_API_KEY: [REDACTED]" echo "FOSSA_PROJECT_ID: $FOSSA_PROJECT_ID" @@ -90,5 +129,18 @@ runs: echo "GITHUB_REPOSITORY: $GITHUB_REPOSITORY" echo "GITHUB_RUN_ID: $GITHUB_RUN_ID" echo "GITHUB_SERVER_URL: $GITHUB_SERVER_URL" + echo "GITHUB_TOKEN: [REDACTED]" + echo "ENABLE_PR_COMMENT: $ENABLE_PR_COMMENT" + echo "ENABLE_STATUS_CHECK: $ENABLE_STATUS_CHECK" + echo "STATUS_CHECK_NAME: $STATUS_CHECK_NAME" + echo "PR_COMMENT_MAX_VIOLATIONS: $PR_COMMENT_MAX_VIOLATIONS" + echo "ENABLE_DIFF_MODE: $ENABLE_DIFF_MODE" + echo "DIFF_BASE_REVISION_SHA: $DIFF_BASE_REVISION_SHA" + echo "ENABLE_LICENSE_ENRICHMENT: $ENABLE_LICENSE_ENRICHMENT" + echo "GITHUB_EVENT_NAME: $GITHUB_EVENT_NAME" + echo "GITHUB_REF: $GITHUB_REF" + echo "GITHUB_SHA: $GITHUB_SHA" + echo "GITHUB_HEAD_REF: $GITHUB_HEAD_REF" + echo "GITHUB_BASE_REF: $GITHUB_BASE_REF" source /maas-build-actions/venv/bin/activate python3 /maas-build-actions/scripts/fossa-guard/fossa_guard.py