@@ -211,6 +211,13 @@ jobs:
211
211
console.log(`💬 Posting ${results.inlineComments.length} inline comments...`);
212
212
213
213
try {
214
+ // Get the PR files and their diff hunks for proper positioning
215
+ const prFiles = await github.rest.pulls.listFiles({
216
+ owner: context.repo.owner,
217
+ repo: context.repo.repo,
218
+ pull_number: parseInt(prNumber)
219
+ });
220
+
214
221
// Get the latest commit SHA for the PR
215
222
const prData = await github.rest.pulls.get({
216
223
owner: context.repo.owner,
@@ -220,22 +227,48 @@ jobs:
220
227
221
228
const commitSha = prData.data.head.sha;
222
229
223
- // Create a review with inline comments
224
- const review = await github.rest.pulls.createReview({
225
- owner: context.repo.owner,
226
- repo: context.repo.repo,
227
- pull_number: parseInt(prNumber),
228
- commit_id: commitSha,
229
- body: `## 📝 Detailed Style Review\n\nI've added specific suggestions directly on the lines that need attention. Each comment includes:\n- 🎯 The specific rule being applied\n- 💡 A suggested improvement\n- ✨ An example of the recommended approach\n\nThese suggestions will help make your documentation even more welcoming and clear for our global developer community!`,
230
- event: results.summary.criticalIssues > 0 ? 'REQUEST_CHANGES' : 'COMMENT',
231
- comments: results.inlineComments.map(comment => ({
232
- path: comment.path,
233
- line: comment.line,
234
- body: comment.body
235
- }))
236
- });
230
+ // Process inline comments to ensure they have valid positions
231
+ const validInlineComments = [];
237
232
238
- console.log(`✅ Posted review with ${results.inlineComments.length} inline comments`);
233
+ for (const comment of results.inlineComments) {
234
+ // Find the corresponding file in the PR
235
+ const prFile = prFiles.data.find(file => file.filename === comment.path);
236
+
237
+ if (prFile && prFile.patch) {
238
+ // Calculate the position in the diff for this line
239
+ const position = this.calculateDiffPosition(prFile.patch, comment.line);
240
+
241
+ if (position > 0) {
242
+ validInlineComments.push({
243
+ path: comment.path,
244
+ position: position, // Use position instead of line for diff-based comments
245
+ body: comment.body
246
+ });
247
+ } else {
248
+ console.log(`⚠️ Could not find valid diff position for ${comment.path}:${comment.line}`);
249
+ }
250
+ } else {
251
+ console.log(`⚠️ File ${comment.path} not found in PR files or has no patch`);
252
+ }
253
+ }
254
+
255
+ if (validInlineComments.length > 0) {
256
+ // Create a review with inline comments
257
+ const review = await github.rest.pulls.createReview({
258
+ owner: context.repo.owner,
259
+ repo: context.repo.repo,
260
+ pull_number: parseInt(prNumber),
261
+ commit_id: commitSha,
262
+ body: `## 📝 Detailed Style Review\n\nI've added specific suggestions directly on the lines that need attention. Each comment includes:\n- 🎯 The specific rule being applied\n- 💡 A suggested improvement\n- ✨ An example of the recommended approach\n\nThese suggestions will help make your documentation even more welcoming and clear for our global developer community!`,
263
+ event: results.summary.criticalIssues > 0 ? 'REQUEST_CHANGES' : 'COMMENT',
264
+ comments: validInlineComments
265
+ });
266
+
267
+ console.log(`✅ Posted review with ${validInlineComments.length} inline comments`);
268
+ } else {
269
+ console.log('⚠️ No valid inline comment positions found, falling back to summary comment');
270
+ throw new Error('No valid diff positions found for inline comments');
271
+ }
239
272
240
273
// If we had to truncate comments, add a note
241
274
if (results.hasMoreIssues) {
@@ -253,13 +286,13 @@ jobs:
253
286
}
254
287
255
288
} catch (error) {
256
- console.error('Failed to post inline comments:', error);
289
+ console.error('Failed to post inline comments:', error.message );
257
290
258
291
// Fallback: post inline comments as a single comment
259
292
let fallbackComment = '## 📝 Detailed Suggestions\n\n*Unable to post inline comments, here are the specific suggestions:*\n\n';
260
293
261
294
results.inlineComments.forEach((comment, index) => {
262
- fallbackComment += `### ${comment.path}:${comment.line}\n\n${comment.body}\n\n---\n\n`;
295
+ fallbackComment += `### 📍 ${comment.path}:${comment.line}\n\n${comment.body}\n\n---\n\n`;
263
296
});
264
297
265
298
await github.rest.issues.createComment({
@@ -273,6 +306,38 @@ jobs:
273
306
}
274
307
}
275
308
309
+ // Helper function to calculate diff position
310
+ this.calculateDiffPosition = function(patch, targetLine) {
311
+ const lines = patch.split('\n');
312
+ let position = 0;
313
+ let currentLine = 0;
314
+
315
+ for (const line of lines) {
316
+ position++;
317
+
318
+ if (line.startsWith('@@')) {
319
+ // Parse hunk header: @@ -oldStart,oldCount +newStart,newCount @@
320
+ const match = line.match(/@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
321
+ if (match) {
322
+ currentLine = parseInt(match[1]) - 1; // Start one before the first line
323
+ }
324
+ continue;
325
+ }
326
+
327
+ if (line.startsWith('+')) {
328
+ currentLine++;
329
+ if (currentLine === targetLine) {
330
+ return position;
331
+ }
332
+ } else if (line.startsWith(' ')) {
333
+ currentLine++;
334
+ }
335
+ // Lines starting with '-' don't increment currentLine (they're deleted)
336
+ }
337
+
338
+ return -1; // Line not found in diff
339
+ };
340
+
276
341
// Set appropriate exit code
277
342
if (results.issues.errors.length > 0) {
278
343
core.setFailed(`Found ${results.issues.errors.length} critical errors that must be fixed before merging.`);
0 commit comments