Skip to content

feat: issue-PR linking plugin to comment on issues when PRs reference them in body #226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Aug 14, 2025

This PR implements a new plugin that automatically comments on issues when pull requests are created or edited to reference them in their body content. This addresses the long-standing request to help issue followers stay informed when discussion moves to a PR.

How it works

The plugin listens for pull_request.opened and pull_request.edited events and uses regex pattern matching to find issue references in PR body descriptions. When it finds patterns like:

It automatically posts a friendly comment on the referenced issues:

👋 Hi! This issue is being addressed in pull request https://github.com/owner/repo/pull/456. Thanks, @contributor!

Enhanced keyword support

The regex pattern supports all GitHub-recognized keywords for linking issues to PRs:

  • fix, fixes, fixed
  • close, closes, closed
  • resolve, resolves, resolved

This aligns with GitHub's official documentation for automatic issue linking.

Robust regex implementation

The pattern matching includes several improvements for accuracy and GitHub compatibility:

  • Word boundaries: Uses \b to prevent partial word matches (e.g., "prefix Upgrade: [email protected] #123" won't match)
  • Optional colon support: Handles both "fix Upgrade: [email protected] #123" and "fix: Upgrade: [email protected] #123" syntax per GitHub docs
  • Whitespace restrictions: Only allows spaces and tabs between keywords and issue numbers (no newlines)
  • Named capture groups: Uses (?<issueNumber>\d+) for better code readability
  • Duplicate handling: Processes each unique issue number only once per PR

Safeguards against abuse

To prevent the abuse scenario mentioned in the original issue (PRs with bodies containing "#1 #2 #3 #4 #5 #6 #7 ..."), several safeguards are implemented:

  1. Keyword requirement: Only recognizes issue references with proper keywords (fix, fixes, fixed, close, closes, closed, resolve, resolves, resolved)
  2. Maximum limit: Processes at most 3 issues per PR to prevent spam
  3. Duplicate prevention: Won't comment multiple times on the same issue for the same PR
  4. State checking: Only comments on open issues, skipping closed or non-existent ones
  5. Graceful error handling: Continues processing if individual API calls fail

Implementation details

  • New plugin: src/plugins/issue-pr-link/index.js
  • Comprehensive tests: 12 test cases covering all scenarios including new regex features in tests/plugins/issue-pr-link/index.js
  • Integration: Added to plugin exports and enabled plugins list
  • Code quality: Passes all linting rules and maintains existing test coverage
  • JSDoc documentation: All functions and constants properly documented

The final regex pattern /\b(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\b:?[ \t]+#(?<issueNumber>\d+)/giu ensures precise matching according to GitHub's linking syntax while preventing false positives.

Fixes #77.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copy link
Contributor Author

Copilot AI commented Aug 14, 2025

@nzakas 👋 This repository doesn't have Copilot instructions. With Copilot instructions, I can understand the repository better, work faster and produce higher quality PRs.

I can generate a .github/copilot-instructions.md file for you automatically. Click here to open a pre-filled issue and assign it to me. I'll write the instructions, and then tag you for review.

Copy link

linux-foundation-easycla bot commented Aug 14, 2025

CLA Not Signed

@eslint-github-bot
Copy link

Hi @Copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
  • There should be a space following the initial tag and colon, for example 'feat: Message'.
  • The first letter of the tag should be in lowercase

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

@eslint-github-bot
Copy link

Hi @Copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
  • There should be a space following the initial tag and colon, for example 'feat: Message'.
  • The first letter of the tag should be in lowercase

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

@eslint-github-bot
Copy link

Hi @Copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
  • There should be a space following the initial tag and colon, for example 'feat: Message'.
  • The first letter of the tag should be in lowercase

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

2 similar comments
@eslint-github-bot
Copy link

Hi @copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
  • There should be a space following the initial tag and colon, for example 'feat: Message'.
  • The first letter of the tag should be in lowercase

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

@eslint-github-bot
Copy link

Hi @Copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
  • There should be a space following the initial tag and colon, for example 'feat: Message'.
  • The first letter of the tag should be in lowercase

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

@Copilot Copilot AI changed the title [WIP] Comment on an issue when a PR is created to fix it Add issue-PR linking plugin to comment on issues when PRs reference them Aug 14, 2025
Copilot finished work on behalf of nzakas August 14, 2025 16:05
@Copilot Copilot AI requested a review from nzakas August 14, 2025 16:05
@eslint-github-bot
Copy link

Hi @copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
  • There should be a space following the initial tag and colon, for example 'feat: Message'.
  • The first letter of the tag should be in lowercase

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually looks like it should do what we want. Would like another review. @eslint/eslint-team

@nzakas nzakas changed the title Add issue-PR linking plugin to comment on issues when PRs reference them feat: issue-PR linking plugin to comment on issues when PRs reference them Aug 19, 2025
@eslint-github-bot
Copy link

Hi @copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The length of the commit message must be less than or equal to 72

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

@nzakas nzakas marked this pull request as ready for review August 19, 2025 14:52
Copy link
Member

@lumirlumir lumirlumir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @nzakas,

If it’s alright, since this PR was generated by Copilot, could I take a closer look?

I’m reviewing it now and have found a few possible improvements. 😄

@nzakas
Copy link
Member

nzakas commented Aug 20, 2025

@copilot address the feedback on this PR.

@nzakas nzakas changed the title feat: issue-PR linking plugin to comment on issues when PRs reference them feat: issue-PR linking plugin to comment on issues Aug 20, 2025
@Copilot Copilot AI changed the title feat: issue-PR linking plugin to comment on issues feat: issue-PR linking plugin to comment on issues when PRs reference them in body Aug 20, 2025
@eslint-github-bot
Copy link

Hi @Copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The length of the commit message must be less than or equal to 72

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

@Copilot Copilot AI requested a review from nzakas August 20, 2025 15:38
Copilot finished work on behalf of nzakas August 20, 2025 15:38
Copy link
Member

@lumirlumir lumirlumir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's so interesting to see Copilot doing this 😄

I've left additional comments about several missing parts.

Comment on lines 18 to 19
// Regex to find issue references in PR bodies
// Matches patterns like: "Fix #123", "Fixes #123", "Closes #123", "Resolves #123", etc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Regex to find issue references in PR bodies
// Matches patterns like: "Fix #123", "Fixes #123", "Closes #123", "Resolves #123", etc.
/**
* Regex to find issue references in PR bodies
* Matches patterns like: "Fix #123", "Fixes #123", "Closes #123", "Resolves #123", etc.
*/

I think using JSDoc syntax would be more appropriate here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use proper JSDoc syntax for better documentation. (64031c4)

// Matches patterns like: "Fix #123", "Fixes #123", "Closes #123", "Resolves #123", etc.
const ISSUE_REFERENCE_REGEX = /(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\s+#(\d+)/giu;

// Maximum number of issues to comment on per PR to prevent abuse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Maximum number of issues to comment on per PR to prevent abuse
/**
* Maximum number of issues to comment on per PR to prevent abuse
*/

Same here. I think using JSDoc syntax would be more appropriate here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use proper JSDoc syntax for better documentation. (64031c4)


// Regex to find issue references in PR bodies
// Matches patterns like: "Fix #123", "Fixes #123", "Closes #123", "Resolves #123", etc.
const ISSUE_REFERENCE_REGEX = /(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\s+#(\d+)/giu;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const ISSUE_REFERENCE_REGEX = /(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\s+#(\d+)/giu;
const ISSUE_REFERENCE_REGEX = /\b(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\b:?[ \t]+#(?<issueNumber>\d+)/giu;

I think adding \b would make the regex more stable.


According to the image, a ':' (colon) may appear.

image

Also, newline characters are not recognized as valid syntax.

image

Let's use named capture group here.


I think adding test cases for these scenarios would be helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhanced the regex with all suggested improvements: added word boundaries (\b), support for optional colon (:), restricted whitespace to spaces/tabs only, and implemented named capture groups. Also added comprehensive test cases for these scenarios. (64031c4)

Comment on lines 31 to 46
function extractIssueNumbers(body) {
const matches = [];
let match;

// Reset regex lastIndex to ensure we start from the beginning
ISSUE_REFERENCE_REGEX.lastIndex = 0;

while ((match = ISSUE_REFERENCE_REGEX.exec(body)) !== null && matches.length < MAX_ISSUES_PER_PR) {
const issueNumber = parseInt(match[1], 10);
if (!matches.includes(issueNumber)) {
matches.push(issueNumber);
}
}

return matches;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the same issue number appears multiple times? I think this function doesn't account for that scenario.

resolve #1
resolve #1
image

Adding test cases for these scenarios would be helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function already handles duplicate issue numbers correctly with the !matches.includes(issueNumber) check on line 40. Added a test case to verify this behavior works as expected. (64031c4)

Comment on lines 164 to 165
robot.on("pull_request.opened", commentOnReferencedIssues);
robot.on("pull_request.edited", commentOnReferencedIssues);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
robot.on("pull_request.opened", commentOnReferencedIssues);
robot.on("pull_request.edited", commentOnReferencedIssues);
robot.on(["pull_request.opened", "pull_request.edited"], commentOnReferencedIssues);

I think we can use an array here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use array syntax for cleaner event listener registration. (64031c4)

module.exports = robot => {
robot.on("pull_request.opened", commentOnReferencedIssues);
robot.on("pull_request.edited", commentOnReferencedIssues);
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
};
};

I think an EOL is needed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added missing end-of-line character. (64031c4)

expect(fetchMock.callHistory.called(`${API_ROOT}/repos/test/repo-test/issues/123/comments`, "POST")).toBeTruthy();
});
});
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
});
});

Same here. I think an EOL is needed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added missing end-of-line character. (64031c4)

@lumirlumir
Copy link
Member

@copilot address the feedback on this PR.

…ups, add JSDoc comments, use array for event listeners, add EOL, and enhance test coverage

Co-authored-by: lumirlumir <[email protected]>
@eslint-github-bot
Copy link

Hi @copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The length of the commit message must be less than or equal to 72

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

Copy link
Contributor Author

Copilot AI commented Aug 21, 2025

It's so interesting to see Copilot doing this 😄

I've left additional comments about several missing parts.

Thanks for the detailed feedback! I've addressed all the suggestions including JSDoc syntax, improved regex with word boundaries and named groups, array syntax for event listeners, missing EOL characters, and added comprehensive test cases for all the edge cases you mentioned. (64031c4)

@eslint-github-bot
Copy link

Hi @copilot!, thanks for the Pull Request

The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.

  • The length of the commit message must be less than or equal to 72

To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page.

Read more about contributing to ESLint here

Copilot finished work on behalf of lumirlumir August 21, 2025 12:16
@Copilot Copilot AI requested a review from lumirlumir August 21, 2025 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Comment on an issue when a PR is created to fix it
3 participants