Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tools/sbom-diff-and-risk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ The [examples/](examples/) directory includes:
- a sample pass JSON report at [sample-report.json](examples/sample-report.json)
- a sample summary-only JSON artifact at [sample-summary.json](examples/sample-summary.json)
- a consumer GitHub Actions workflow example at [github-actions-consumer.yml](examples/github-actions-consumer.yml)
- a policy-gated consumer GitHub Actions workflow example at [github-actions-policy-consumer.yml](examples/github-actions-policy-consumer.yml)
- a sample pass Markdown report at [sample-report.md](examples/sample-report.md)
- sample policy-warn reports at [sample-policy-warn-report.json](examples/sample-policy-warn-report.json) and [sample-policy-warn-report.md](examples/sample-policy-warn-report.md)
- sample policy-fail reports at [sample-policy-fail-report.json](examples/sample-policy-fail-report.json) and [sample-policy-fail-report.md](examples/sample-policy-fail-report.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ The same workflow is also checked in as
[../examples/github-actions-consumer.yml](../examples/github-actions-consumer.yml)
for copying into consumer repositories.

For a policy-gated variant that writes `outputs/policy.json` with
`--policy-json PATH`, see
[../examples/github-actions-policy-consumer.yml](../examples/github-actions-policy-consumer.yml).

```yaml
name: Dependency diff review

Expand Down Expand Up @@ -143,3 +147,5 @@ from that local checkout instead of downloading a release wheel:

For compact summary consumption patterns, see
[summary-json-ci-cookbook.md](summary-json-ci-cookbook.md).
For policy sidecar consumption patterns, see
[policy-decision-ci-cookbook.md](policy-decision-ci-cookbook.md).
5 changes: 5 additions & 0 deletions tools/sbom-diff-and-risk/docs/policy-decision-ci-cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ decision metadata remains available for review.
For a checked-in reference artifact generated from this path, see
[sample-policy.json](../examples/sample-policy.json).

For a full GitHub Actions consumer workflow example that captures
`outputs/policy.json`, uploads it even when local policy fails, and then fails
the job based on `summary.policy`, see
[github-actions-policy-consumer.yml](../examples/github-actions-policy-consumer.yml).

## Python consumer

This example reads the policy-only JSON sidecar, prints compact policy status,
Expand Down
117 changes: 117 additions & 0 deletions tools/sbom-diff-and-risk/examples/github-actions-policy-consumer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Example only.
# Copy this file into a consumer repository under .github/workflows/ if useful.
# This repository does not run this file as a workflow.
# Production PyPI publishing for sbom-diff-and-risk is intentionally deferred;
# install from a GitHub Release asset or local checkout instead.

name: Dependency policy review

on:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
dependency-policy:
runs-on: ubuntu-latest

steps:
- name: Check out consumer repository
uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.x"

- name: Download sbom-diff-and-risk release wheel
env:
GH_TOKEN: ${{ github.token }}
run: |
mkdir -p .tooling/sbom-diff-risk
gh release download v0.8.0 \
--repo stacknil/scientific-computing-toolkit \
--pattern "sbom_diff_and_risk-0.8.0-py3-none-any.whl" \
--dir .tooling/sbom-diff-risk

- name: Install sbom-diff-risk
run: |
python -m pip install \
.tooling/sbom-diff-risk/sbom_diff_and_risk-0.8.0-py3-none-any.whl

- name: Compare dependency evidence with local policy
id: compare
run: |
mkdir -p outputs
set +e
sbom-diff-risk compare \
--before path/to/before-sbom.json \
--after path/to/after-sbom.json \
--format auto \
--policy path/to/policy.yml \
--out-json outputs/report.json \
--out-md outputs/report.md \
--policy-json outputs/policy.json \
--out-sarif outputs/report.sarif
status=$?
set -e
echo "$status" > outputs/policy-exit-code.txt
echo "exit_code=$status" >> "$GITHUB_OUTPUT"

- name: Summarize local policy decision
run: |
python - <<'PY'
import json
from pathlib import Path

policy_report = json.loads(
Path("outputs/policy.json").read_text(encoding="utf-8")
)
policy = policy_report.get("summary", {}).get("policy")

if policy is None:
print("policy=not-used")
raise SystemExit(0)

print(
"policy="
f"{policy['status']} "
f"blocking={policy['blocking']} "
f"warning={policy['warning']} "
f"suppressed={policy['suppressed']}"
)

findings = (
policy_report.get("blocking_findings", [])
+ policy_report.get("warning_findings", [])
+ policy_report.get("suppressed_findings", [])
)

for finding in findings:
print(
"policy-finding "
f"level={finding.get('level')} "
f"rule={finding.get('policy_rule')} "
f"reason={finding.get('decision_reason')} "
f"severity_source={finding.get('severity_source')} "
f"observed={finding.get('observed_value')} "
f"threshold={finding.get('matched_threshold')}"
)

if policy["status"] == "fail":
raise SystemExit("local policy failed")
PY

- name: Upload dependency policy outputs
if: always()
uses: actions/upload-artifact@v7
with:
name: dependency-policy-outputs
path: |
outputs/report.json
outputs/report.md
outputs/policy.json
outputs/policy-exit-code.txt
outputs/report.sarif