pr-risk-scorer
A GitHub Action that scores pull requests by structural risk across five dimensions and posts the result as a PR comment.
Quick Start
Add this step to any workflow that runs on pull_request events:
- name: Score PR Risk
uses: FasterApiWeb/pr-risk-scorer@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
github-token |
Yes | — | Token used to post the PR comment (secrets.GITHUB_TOKEN works) |
config-path |
No | .github/pr-risk-scorer.yml |
Path to pr-risk-scorer.yml config file |
Secrets (
SLACK_WEBHOOK_URL,JIRA_API_TOKEN,JIRA_EMAIL,LINEAR_API_TOKEN,ANTHROPIC_API_KEY) are passed asenv:vars on the step, not asinputs:. See the full workflow example below.
Outputs
| Output | Description |
|---|---|
risk-score |
Numeric score 0–100 |
risk-label |
LOW, MEDIUM, or HIGH |
Score Breakdown
The total score is a weighted average of five analyzers (0 = no risk, 100 = maximum risk):
| Dimension | Weight | Method |
|---|---|---|
| Diff Size | 20% | Lines added + deleted, scaled to 1 000 max |
| Complexity | 30% | Average cyclomatic complexity of changed .py files via radon |
| Coverage Gap | 20% | 1 − line_rate from coverage.xml (inverse of test coverage) |
| Dead Code | 15% | Count of unused symbols via vulture, capped at 20 items |
| Migrations | 15% | Presence of DB migration files (0 → 0, 1 → 60, 2 → 80, 3+ → 100) |
Risk Tiers
| Emoji | Level | Score Range |
|---|---|---|
| 🟢 | LOW | < 40 |
| 🟡 | MEDIUM | 40 – 70 |
| 🔴 | HIGH | > 70 |
Example PR Comment
Screenshot placeholder — paste a screenshot of a real PR comment here after first run.
## PR Risk Score: 🟡 MEDIUM (54.5 / 100)
> Threshold: 70 | Status: ✅ PASS
| Analyzer | Score | Risk |
|------------------|------:|-------------|
| Diff Size (20%) | 42.0 | 🟡 MEDIUM |
| Complexity (30%) | 60.0 | 🟡 MEDIUM |
| Coverage Gap (20%)| 55.0| 🟡 MEDIUM |
| Dead Code (15%) | 20.0 | 🟢 LOW |
| Migrations (15%) | 0.0 | 🟢 LOW |
Full Example Workflow
Full workflow with all integrations wired:
name: PR Quality Gate
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
risk-score:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # required for git diff HEAD~1
- name: Generate coverage report
run: |
pip install pytest pytest-cov
pytest --cov=src --cov-report=xml
- name: Score PR Risk
uses: FasterApiWeb/pr-risk-scorer@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
config-path: .github/pr-risk-scorer.yml
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
LINEAR_API_TOKEN: ${{ secrets.LINEAR_API_TOKEN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
Minimal config (Slack only)
.github/pr-risk-scorer.yml:
slack:
enabled: true
# SLACK_WEBHOOK_URL is read from the environment
notify_on: [high, medium] # omit to notify on all scores
Score Bands
| Score | Label | Meaning |
|---|---|---|
| 0 – 39 | 🟢 LOW | Routine change, low review overhead |
| 40 – 70 | 🟡 MEDIUM | Notable change, standard review recommended |
| 71 – 100 | 🔴 HIGH | Large or complex change, careful review required |
Local Development
# Install hatch
pip install hatch
# Run tests
hatch run test
# Type check
hatch run typecheck
# Lint for dead code
hatch run lint
Contributing
See CONTRIBUTING.md.
Metadata
Release files for pr-risk-scorer 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pr_risk_scorer-0.2.1.tar.gz | 83.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pr_risk_scorer-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 121.5 kB
Release files / pr_risk_scorer-0.2.1.tar.gz
| Download URL | pr_risk_scorer-0.2.1.tar.gz |
|---|---|
| Size | 83.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e2bbf8d323a381e83a54b0bb560879179074c4e8b585e04e16b3896b701834cb
|
|
BLAKE2b-256 checksum How to use checksums |
8e5637916de81c745c9e33d9deef0119c4ad82b9730c2be0116ffa1e3b7f683f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 25, 2026.
Transparency logRelease files / pr_risk_scorer-0.2.1-py3-none-any.whl
| Download URL | pr_risk_scorer-0.2.1-py3-none-any.whl |
|---|---|
| Size | 38.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
959d8678695267058fa9742aba9c64bdfacf73d5aa3d214f2ea5722684fb6354
|
|
BLAKE2b-256 checksum How to use checksums |
bd8662a733c1f97e3dba6e5f46f72b9a580df431117e7d07d498f12d301a1648
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 25, 2026.
Transparency log