-
-
Notifications
You must be signed in to change notification settings - Fork 517
197 lines (180 loc) · 8.97 KB
/
issue-comment.yml
File metadata and controls
197 lines (180 loc) · 8.97 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
name: Auto-comment on Issues with Diagnostics Links
# =============================================================================
# PURPOSE: Automatically respond to new issues with helpful templates
#
# This workflow:
# 1. Detects the type of issue (bug, question, security CVE, etc.)
# 2. Posts an appropriate template comment with guidance
# 3. For security issues (CVE/GHSA), closes and labels for admin deletion
#
# Template files are stored in .github/issue-comments/
# =============================================================================
# Triggers on newly opened issues
on:
issues:
types: [opened]
permissions:
contents: read # Read template files from repository
issues: write # Post comments, add labels, close issues
jobs:
comment-on-issue:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1 # Shallow clone - only need template files
- name: Comment on bug reports
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
const path = require('path');
const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
// =========================================================
// STEP 1: Load all comment templates from .github/issue-comments/
//
// Template files:
// - bug.md : For bug reports (has "describe the issue")
// - question.md : For questions (has "how can we help")
// - generic.md : Fallback for unrecognized issue types
// - system-info.md: When in-app reporter was used
// - security.md : For CVE/GHSA security disclosures
// =========================================================
let bugComment = '';
let questionComment = '';
let genericComment = '';
let systemInfoComment = '';
let securityComment = '';
try {
bugComment = fs.readFileSync(path.join(workspace, '.github/issue-comments/bug.md'), 'utf8');
} catch (e) {
console.log('Could not read bug.md:', e.message);
}
try {
questionComment = fs.readFileSync(path.join(workspace, '.github/issue-comments/question.md'), 'utf8');
} catch (e) {
console.log('Could not read question.md:', e.message);
}
try {
genericComment = fs.readFileSync(path.join(workspace, '.github/issue-comments/generic.md'), 'utf8');
} catch (e) {
console.log('Could not read generic.md:', e.message);
}
try {
systemInfoComment = fs.readFileSync(path.join(workspace, '.github/issue-comments/system-info.md'), 'utf8');
} catch (e) {
console.log('Could not read system-info.md:', e.message);
}
try {
securityComment = fs.readFileSync(path.join(workspace, '.github/issue-comments/security.md'), 'utf8');
} catch (e) {
console.log('Could not read security.md:', e.message);
}
// =========================================================
// STEP 2: Extract issue content for classification
// =========================================================
const issue = context.payload.issue || {};
const title = (issue.title || '');
const body = (issue.body || '');
const titleLower = title.toLowerCase();
const bodyLower = body.toLowerCase();
// =========================================================
// STEP 3: Detect issue type using content patterns
//
// SECURITY CHECK (highest priority):
// - CVE pattern: CVE-2025-1234 or just CVE-
// - GHSA pattern: GHSA-xxxx-xxxx-xxxx (GitHub Security Advisory)
// These should NEVER be disclosed publicly in issues!
//
// SYSTEM INFO CHECK:
// - "Collected Value Title" indicates the in-app bug reporter
// was used, which automatically captures system info
//
// ISSUE TYPE CHECK:
// - "describe the issue" = bug report template
// - "how can we help" = question template
// =========================================================
const cvePattern = /cve-(\d{4}-\d+)?/i;
const ghsaPattern = /ghsa-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}/i;
const hasCVE = cvePattern.test(title) || cvePattern.test(body) || ghsaPattern.test(title) || ghsaPattern.test(body);
const hasSystemInfo = bodyLower.includes('collected value title');
const isBug = bodyLower.includes('describe the issue');
const isQuestion = bodyLower.includes('how can we help');
console.log('Issue Classification Results:');
console.log(' hasCVE:', hasCVE, '(security vulnerability disclosure)');
console.log(' hasSystemInfo:', hasSystemInfo, '(in-app reporter used)');
console.log(' isBug:', isBug);
console.log(' isQuestion:', isQuestion);
// =========================================================
// STEP 4: Select appropriate template
//
// Priority order (highest to lowest):
// 1. Security (CVE/GHSA) - Must be handled immediately
// 2. System-info - User used in-app reporter, thank them
// 3. Bug report - Standard bug template
// 4. Question - Help/support template
// 5. Generic - Fallback for unrecognized issues
// =========================================================
let comment = '';
if (hasCVE && securityComment) {
console.log('Posting security comment - CVE detected');
comment = securityComment;
} else if (hasSystemInfo && systemInfoComment) {
console.log('Posting system-info comment');
comment = systemInfoComment;
} else if (isBug && bugComment) {
console.log('Posting bug comment');
comment = bugComment;
} else if (isQuestion && questionComment) {
console.log('Posting question comment');
comment = questionComment;
} else if (genericComment) {
console.log('Posting generic comment');
comment = genericComment;
}
// =========================================================
// STEP 5: Post comment and handle security issues
// =========================================================
if (comment) {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
// ---------------------------------------------------------
// SECURITY HANDLING: CVE/GHSA issues must be closed immediately
// to prevent public disclosure of vulnerabilities.
//
// Actions taken:
// 1. Add 'security' and 'security-delete-required' labels
// 2. Close the issue with 'not_planned' reason
// 3. Log for admin to manually delete (API can't delete issues)
//
// The security.md template directs users to:
// https://github.com/ChurchCRM/CRM/security/advisories
// ---------------------------------------------------------
if (hasCVE) {
console.log('⚠️ SECURITY: Closing issue due to CVE/GHSA disclosure');
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['security', 'security-delete-required']
});
await github.rest.issues.update({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed',
state_reason: 'not_planned'
});
// Note: GitHub REST API doesn't support issue deletion
// Issues can only be deleted by repository admins via the UI
// The 'security-delete-required' label flags this for admin action
console.log('Issue closed and labeled - manual deletion required by admin');
}
} else {
console.log('No comment template available to post.');
}