-
Notifications
You must be signed in to change notification settings - Fork 2.3k
218 lines (173 loc) · 9.64 KB
/
pr-severity.yml
File metadata and controls
218 lines (173 loc) · 9.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
name: PR Severity Classification
on:
# Use pull_request_target to allow running on fork PRs with access to secrets.
# This is safe because we don't checkout or execute any code from the PR -
# we only read PR metadata (changed files, labels) via the GitHub API.
pull_request_target:
types: [opened, synchronize, labeled]
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: pr-severity-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
classify:
name: Classify PR Severity
runs-on: ubuntu-latest
# Skip if PR has skip-severity-check label.
# For labeled events, only run if 'reclassify' label was added.
if: |
!contains(github.event.pull_request.labels.*.name, 'skip-severity-check') &&
(github.event.action != 'labeled' || github.event.label.name == 'reclassify')
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Classify PR with Claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ secrets.PR_SEVERITY_BOT_TOKEN }}
# Allow any user since this workflow only reads PR metadata via API
# and doesn't execute any code from the PR. Tool permissions are
# restricted to gh pr commands only.
allowed_non_write_users: "*"
# Allow Claude to manage labels and post comments.
# Keep permissions minimal to limit prompt injection risk.
claude_args: --allowedTools "Bash(gh pr view:*)" "Bash(gh pr edit:*)" "Bash(gh pr comment:*)"
prompt: |
You are a PR severity classifier for the lnd (Lightning Network Daemon) repository.
## Tool Constraints
You ONLY have access to these commands:
- `gh pr view` - to read PR metadata
- `gh pr edit` - to add/remove labels
- `gh pr comment` - to post comments
You do NOT have access to `gh api`, `gh label`, or any other
`gh` subcommand. Do not attempt to use them. For ALL label
operations, use `gh pr edit` with `--add-label` or
`--remove-label`.
## Your Task
Analyze PR #${{ github.event.pull_request.number }} and:
1. Determine its severity level based on the files changed
2. Apply the appropriate severity label
3. Post a detailed comment explaining your determination
## Severity Levels
**CRITICAL** (severity-critical) - Requires expert review:
- lnwallet/* - Wallet operations, channel funding, signing, commitment transactions
- htlcswitch/* - HTLC forwarding, payment routing state machine
- contractcourt/* - On-chain dispute resolution, breach handling
- sweep/* - Output sweeping, fund recovery, fee bumping
- peer/*, brontide/* - Encrypted peer connections, Noise protocol
- keychain/* - Private key derivation and management
- input/* - Script signing, witness generation, MuSig2
- channeldb/* - Channel state persistence, database migrations
- funding/* - Channel funding workflow coordination
- lnwire/* - Lightning wire protocol messages
- server.go, rpcserver.go - Core server coordination
**HIGH** (severity-high) - Requires knowledgeable engineer:
- routing/* - Payment pathfinding algorithms
- invoices/* - Invoice management and settlement
- discovery/* - Gossip protocol
- graph/* - Network graph maintenance
- watchtower/* - Breach remediation
- feature/* - Feature bit management
- lnrpc/* - RPC/API definitions
- macaroons/*, walletunlocker/*, cert/* - Auth/security
- chainntnfs/*, chanacceptor/*, protofsm/*, sqldb/*
**MEDIUM** (severity-medium) - Focused review:
- cmd/* - CLI client commands (do NOT inherit severity from server-side packages with similar names)
- payments/*, autopilot/*, lncfg/*, chanfitness/*
- netann/*, kvdb/*, chanbackup/*, aezeed/*, tor/*
- zpay32/*, tlv/*, fn/*, record/*, amp/*
- *.proto files (API changes)
- Other Go files not categorized above
**LOW** (severity-low) - Best-effort review:
- docs/*, release-notes/*, *.md files
- scripts/*, tools/*, contrib/*, make/*, docker/*
- itest/*, lntest/*, *_test.go (test-only changes)
- .github/* (CI/CD configuration)
## Classification Rules
1. The HIGHEST severity file determines the PR severity
2. Classify files by their actual package path, NOT by filename keywords.
Files under cmd/* are CLI client code and should always be MEDIUM,
even if the filename contains a server-side package name (e.g.
cmd/commands/cmd_walletunlocker.go is MEDIUM, not HIGH).
3. Bump severity UP one level if:
- PR touches >20 files (excluding tests and auto-generated files)
- PR has >500 lines changed (excluding tests and auto-generated files)
- PR touches multiple distinct critical packages
4. Check for override labels first (severity-override-*). If present, respect the override.
5. Database migrations (channeldb/migration*, sqldb/*, wtdb/*) are always CRITICAL
## Files to Exclude from Line/File Counting
When calculating file count and lines changed for severity bumps, exclude:
- Test files: *_test.go, itest/*, lntest/*
- Auto-generated files: *.pb.go, *.pb.gw.go, *.pb.json.go, *.sql.go, *_generated.go
- Mock files: mock_*.go, *_mock.go
## Steps
1. First, check for existing override labels AND existing severity labels:
```
gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name'
```
Note which `severity-*` label (if any) is currently applied. This is
the "previous severity".
2. If an override label exists (severity-override-*), use that level and skip classification.
3. Check for existing bot comments. Look for the HTML marker `<!-- pr-severity-bot -->`:
```
gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[].body' | grep -c 'pr-severity-bot' || true
```
This tells you whether the bot has commented before.
4. Get the list of changed files:
```
gh pr view ${{ github.event.pull_request.number }} --json files,additions,deletions
```
5. Classify each file and determine the new overall severity.
6. **Decide whether to comment.** Only post a comment if EITHER:
- The bot has NOT commented before (no existing comment with `<!-- pr-severity-bot -->`), OR
- The newly determined severity is DIFFERENT from the previous severity label.
If the bot already commented AND the severity has NOT changed, just
stop here — do NOT post another comment. Still update the label if
needed (step 7-8), but skip the comment.
7. Remove any existing severity-* labels (not override labels):
```
gh pr edit ${{ github.event.pull_request.number }} --remove-label "severity-critical" 2>/dev/null || true
gh pr edit ${{ github.event.pull_request.number }} --remove-label "severity-high" 2>/dev/null || true
gh pr edit ${{ github.event.pull_request.number }} --remove-label "severity-medium" 2>/dev/null || true
gh pr edit ${{ github.event.pull_request.number }} --remove-label "severity-low" 2>/dev/null || true
```
8. Apply the new severity label:
```
gh pr edit ${{ github.event.pull_request.number }} --add-label "severity-<level>"
```
9. If you determined in step 6 that a comment should be posted, post it
with your analysis. Use this format:
If this is a severity CHANGE (previous label existed but differs),
prepend: `> ⚠️ Severity changed: **<OLD>** → **<NEW>** (files changed since last classification)`
```markdown
## <emoji> PR Severity: **<LEVEL>**
> <source> | <N> files | <M> lines changed
<details>
<summary>🔴 <strong>Critical</strong> (N files)</summary>
- `path/to/file1.go` - reason
- `path/to/file2.go` - reason
</details>
[repeat for other tiers if applicable]
### Analysis
<Your explanation of why this severity was chosen, any concerns, etc.>
---
<sub>To override, add a `severity-override-{critical,high,medium,low}` label.</sub>
<!-- pr-severity-bot -->
```
10. Post the comment using `gh pr comment`:
```
gh pr comment ${{ github.event.pull_request.number }} --body "YOUR_COMMENT_HERE"
```
11. If you decided in step 6 to SKIP commenting, do NOT post any comment.
Just ensure the label is correct and exit.
## Emoji Mapping
- critical: 🔴
- high: 🟠
- medium: 🟡
- low: 🟢