@@ -211,6 +211,13 @@ jobs:
211211 console.log(`💬 Posting ${results.inlineComments.length} inline comments...`);
212212
213213 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+
214221 // Get the latest commit SHA for the PR
215222 const prData = await github.rest.pulls.get({
216223 owner: context.repo.owner,
@@ -220,22 +227,48 @@ jobs:
220227
221228 const commitSha = prData.data.head.sha;
222229
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 = [];
237232
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+ }
239272
240273 // If we had to truncate comments, add a note
241274 if (results.hasMoreIssues) {
@@ -253,13 +286,13 @@ jobs:
253286 }
254287
255288 } catch (error) {
256- console.error('Failed to post inline comments:', error);
289+ console.error('Failed to post inline comments:', error.message );
257290
258291 // Fallback: post inline comments as a single comment
259292 let fallbackComment = '## 📝 Detailed Suggestions\n\n*Unable to post inline comments, here are the specific suggestions:*\n\n';
260293
261294 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`;
263296 });
264297
265298 await github.rest.issues.createComment({
@@ -273,6 +306,38 @@ jobs:
273306 }
274307 }
275308
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+
276341 // Set appropriate exit code
277342 if (results.issues.errors.length > 0) {
278343 core.setFailed(`Found ${results.issues.errors.length} critical errors that must be fixed before merging.`);
0 commit comments