-
-
Notifications
You must be signed in to change notification settings - Fork 95
296 lines (266 loc) · 12.9 KB
/
gw_comment_trigger.yml
File metadata and controls
296 lines (266 loc) · 12.9 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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
name: Bugspots Analysis via Comment
on:
issue_comment:
types: [created]
jobs:
parse-comment:
if: github.event.issue.pull_request == null && contains(github.event.comment.body, 'gw --repo')
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
outputs:
repo_url: ${{ steps.parse.outputs.repo_url }}
limit: ${{ steps.parse.outputs.limit }}
branch: ${{ steps.parse.outputs.branch }}
steps:
- name: Parse comment
id: parse
env:
COMMENT_BODY: ${{ github.event.comment.body }}
run: |
echo "Comment body: $COMMENT_BODY"
# Extract repository URL
# Extract repository URL using environment variable
repo_url=$(echo "$COMMENT_BODY" | grep -oP 'gw --repo \K[^\s]+' || echo "")
if [ -z "$repo_url" ]; then
echo "Error: No repository URL found in comment"
exit 1
fi
# Validate repository URL format
if ! echo "$repo_url" | grep -qE '^https://github\.com/[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+/?$'; then
echo "Error: Invalid repository URL format. Must be a GitHub repository URL."
exit 1
fi
# Extract limit
limit_raw=$(echo "$COMMENT_BODY" | grep -oP -- '--limit\s+\K\d+' || echo "")
# Validate and set limit (default to 10 if not specified or invalid)
if [ -n "$limit_raw" ] && [ "$limit_raw" -gt 0 ] && [ "$limit_raw" -le 100 ]; then
limit="$limit_raw"
else
limit="10"
if [ -n "$limit_raw" ]; then
echo "Warning: Invalid limit value '$limit_raw', using default 10"
fi
fi
# Extract branch
branch_raw=$(echo "$COMMENT_BODY" | grep -oP -- '--branch\s+\K[^\s]+' || echo "")
if [ -n "$branch_raw" ]; then
branch="$branch_raw"
else
branch=""
fi
echo "repo_url=$repo_url" >> $GITHUB_OUTPUT
echo "limit=$limit" >> $GITHUB_OUTPUT
echo "branch=$branch" >> $GITHUB_OUTPUT
echo "Parsed repo: $repo_url, limit: $limit, branch: $branch"
run-bugspots:
needs: parse-comment
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '2.7'
- name: Install bugspots gem
run: gem install bugspots
- name: Run Bugspots Comment Analyzer
id: bugspots
continue-on-error: true
env:
REPO_URL: ${{ needs.parse-comment.outputs.repo_url }}
LIMIT: ${{ needs.parse-comment.outputs.limit }}
BRANCH: ${{ needs.parse-comment.outputs.branch }}
run: |
chmod +x BugPredict/gw.sh
BugPredict/gw.sh "$REPO_URL" "$LIMIT" "$BRANCH"
- name: Check for repository errors
id: check-errors
env:
REPO_URL: ${{ needs.parse-comment.outputs.repo_url }}
BRANCH: ${{ needs.parse-comment.outputs.branch }}
run: |
repo_name=$(basename "$REPO_URL" .git)
# Check if the bugspots step failed
if [ "${{ steps.bugspots.outcome }}" = "failure" ]; then
echo "analysis_failed=true" >> $GITHUB_OUTPUT
# Check for specific error types
if [ -f "bugspots-results/bugspots-${repo_name}.err" ]; then
error_content=$(cat "bugspots-results/bugspots-${repo_name}.err")
if [[ "$error_content" == *"Clone failed"* ]]; then
echo "error_type=clone_failed" >> $GITHUB_OUTPUT
elif [[ "$error_content" == *"Invalid Git repository"* ]]; then
echo "error_type=invalid_repo" >> $GITHUB_OUTPUT
elif [[ "$error_content" == *"No commits found"* ]]; then
echo "error_type=no_commits" >> $GITHUB_OUTPUT
elif [[ "$error_content" == *"no such branch"* ]]; then
echo "error_type=invalid_branch" >> $GITHUB_OUTPUT
else
echo "error_type=unknown" >> $GITHUB_OUTPUT
fi
else
echo "error_type=unknown" >> $GITHUB_OUTPUT
fi
else
echo "analysis_failed=false" >> $GITHUB_OUTPUT
fi
- name: Prepare error comment
if: steps.check-errors.outputs.analysis_failed == 'true'
env:
REPO_URL: ${{ needs.parse-comment.outputs.repo_url }}
ERROR_TYPE: ${{ steps.check-errors.outputs.error_type }}
run: |
echo "## ❌ Repository Analysis Failed" > comment.md
echo "" >> comment.md
echo "**Repository:** \`$REPO_URL\`" >> comment.md
echo "**Analysis Date:** $(date '+%Y-%m-%d %H:%M:%S UTC')" >> comment.md
echo "" >> comment.md
case "$ERROR_TYPE" in
"clone_failed")
echo "### 🚫 Invalid Repository" >> comment.md
echo "" >> comment.md
echo "**Error:** Unable to clone the repository. This usually means:" >> comment.md
echo "- The repository URL is incorrect" >> comment.md
echo "- The repository does not exist" >> comment.md
echo "- The repository is private and not accessible" >> comment.md
echo "- The repository URL format is invalid" >> comment.md
;;
"invalid_repo")
echo "### 🚫 Invalid Git Repository" >> comment.md
echo "" >> comment.md
echo "**Error:** The URL does not point to a valid Git repository." >> comment.md
echo "" >> comment.md
echo "Please ensure you're providing a valid GitHub repository URL." >> comment.md
;;
"no_commits")
echo "### 📭 Empty Repository" >> comment.md
echo "" >> comment.md
echo "**Error:** The repository exists but has no commits." >> comment.md
echo "" >> comment.md
echo "Bugspots analysis requires commit history to analyze bug patterns." >> comment.md
;;
"invalid_branch")
echo "### 🚫 Invalid Branch" >> comment.md
echo "" >> comment.md
echo "**Error:** The specified branch does not exist in the repository." >> comment.md
echo "" >> comment.md
echo "Please specify a valid branch or omit the --branch parameter to use the default branch." >> comment.md
;;
*)
echo "### ⚠️ Analysis Error" >> comment.md
echo "" >> comment.md
echo "**Error:** An unexpected error occurred during analysis." >> comment.md
echo "" >> comment.md
repo_name=$(basename "$REPO_URL" .git)
if [ -f "bugspots-results/bugspots-${repo_name}.err" ]; then
echo "**Error details:**" >> comment.md
echo '```' >> comment.md
cat "bugspots-results/bugspots-${repo_name}.err" >> comment.md
echo '```' >> comment.md
fi
;;
esac
echo "" >> comment.md
echo "**Usage examples:**" >> comment.md
echo '```' >> comment.md
echo "gw --repo https://github.com/username/repository" >> comment.md
echo "gw --repo https://github.com/username/repository --limit 15" >> comment.md
echo "gw --repo https://github.com/username/repository --branch main" >> comment.md
echo '```' >> comment.md
- name: Prepare success comment
if: steps.check-errors.outputs.analysis_failed == 'false'
env:
REPO_URL: ${{ needs.parse-comment.outputs.repo_url }}
LIMIT: ${{ needs.parse-comment.outputs.limit }}
run: |
repo_name=$(basename "$REPO_URL" .git)
if [ -f "bugspots-results/bugspots-${repo_name}.log" ] && [ -s "bugspots-results/bugspots-${repo_name}.log" ]; then
# Parse the bugspots output to extract hotspots
if grep -q "Hotspots:" "bugspots-results/bugspots-${repo_name}.log"; then
echo "## 🎯 Bugspots Analysis Results" > comment.md
echo "" >> comment.md
echo "**Repository:** \`$REPO_URL\`" >> comment.md
echo "**Analysis Date:** $(date '+%Y-%m-%d %H:%M:%S UTC')" >> comment.md
echo "" >> comment.md
# Extract number of bugfix commits and hotspots from the summary
bugfix_commits=$(grep -oP 'Found \K\d+(?= bugfix commits)' "bugspots-results/bugspots-${repo_name}.log" || echo "unknown")
total_hotspots=$(grep -oP 'with \K\d+(?= hotspots)' "bugspots-results/bugspots-${repo_name}.log" || echo "unknown")
echo "**Analysis Summary:**" >> comment.md
echo "- Found **${bugfix_commits}** bugfix commits" >> comment.md
echo "- Identified **${total_hotspots}** total hotspots" >> comment.md
echo "- Showing top **${LIMIT}** files most likely to contain bugs" >> comment.md
echo "" >> comment.md
# Extract hotspots section and get top N entries
echo "### 🔥 Top ${LIMIT} Hotspots" >> comment.md
echo "" >> comment.md
echo '```' >> comment.md
echo "Score File" >> comment.md
echo "------- ----" >> comment.md
# Use the pre-processed top N file created by gw.sh
if [ -f "bugspots-results/bugspots-${repo_name}-top.log" ]; then
cat "bugspots-results/bugspots-${repo_name}-top.log" >> comment.md
else
# Fallback to manual extraction
sed -n '/Hotspots:/,/^$/p' "bugspots-results/bugspots-${repo_name}.log" | \
grep -E '^\s*[0-9]+\.[0-9]+.*' | \
head -n "$LIMIT" | \
sed 's/^\s*//' >> comment.md
fi
echo '```' >> comment.md
echo "" >> comment.md
echo "> 💡 **How to read this:** Higher scores indicate files more likely to contain bugs." >> comment.md
echo "> Scores are based on frequency and recency of bug-fix commits affecting each file." >> comment.md
echo "" >> comment.md
else
# No hotspots section found
echo "## ⚠️ Bugspots Analysis Results" > comment.md
echo "" >> comment.md
echo "**Repository:** \`$REPO_URL\`" >> comment.md
echo "**Analysis Date:** $(date '+%Y-%m-%d %H:%M:%S UTC')" >> comment.md
echo "" >> comment.md
echo "### 📭 No Hotspots Found" >> comment.md
echo "" >> comment.md
echo "The analysis completed but no hotspots were identified." >> comment.md
echo "" >> comment.md
echo "**Possible reasons:**" >> comment.md
echo "- Repository has very few or no bug-fix commits" >> comment.md
echo "- Commit messages don't match standard bug-fix patterns" >> comment.md
echo "- Repository is well-maintained with minimal bugs" >> comment.md
echo "" >> comment.md
echo "**Raw output preview:**" >> comment.md
echo '```' >> comment.md
head -n 20 "bugspots-results/bugspots-${repo_name}.log" >> comment.md
echo '```' >> comment.md
fi
else
echo "## ⚠️ Bugspots Analysis Results" > comment.md
echo "" >> comment.md
echo "**Repository:** \`$REPO_URL\`" >> comment.md
echo "**Analysis Date:** $(date '+%Y-%m-%d %H:%M:%S UTC')" >> comment.md
echo "" >> comment.md
echo "### 📭 No Results Found" >> comment.md
echo "" >> comment.md
echo "No analysis results were generated." >> comment.md
echo "" >> comment.md
echo "**This could mean:**" >> comment.md
echo "- The repository has no commit history" >> comment.md
echo "- The repository could not be accessed" >> comment.md
echo "- The bugspots analysis encountered an unexpected issue" >> comment.md
fi
- name: Comment on issue
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const comment = fs.readFileSync('comment.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});