Skip to content

Commit

Permalink
Fix checkForReproducer action not adding Missing Repro comment (#38531)
Browse files Browse the repository at this point in the history
Summary:
This PR fixes a bug where GitHub Actions bot didn't add a comment when "Needs: Repro" label was present in an issue.

When a maintainer adds the label manually the bot comments with "Missing Reproductible Example" as normally.

It seems like the problem occurred because of a difference in a sandbox repository and the proper facebook/react-native repo environment.

My sandbox that I used to test #38338 had an "bot" account with Personal Access Token setup to reply to issues. Turns out that bots using PAT have more permissions and can trigger one action from the other.

**The solution is to send the comment directly from the `checkForReproducer` action.** This won't collide with other actions but sadly will duplicate the sending logic into two actions.

This PR also makes the bot respect when a maintainer removes and adds a label by hand and won't alter the maintainer decision.

Related to ☂️ #35591

## Changelog:

[INTERNAL] [FIXED] - Message

Pull Request resolved: #38531

Test Plan: ![image](https://github.com/facebook/react-native/assets/39658211/b956416f-9834-4c61-981f-fe6c17a5eec5)

Reviewed By: cipolleschi

Differential Revision: D47666922

Pulled By: cortinico

fbshipit-source-id: 4a6a471cb11c6ed9b48263d18bf8e283577a14bb
  • Loading branch information
kacperkapusciak authored and facebook-github-bot committed Jul 21, 2023
1 parent f6197cd commit 3f78fa9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 17 deletions.
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ body:
- type: textarea
id: extra
attributes:
label: Snack, code example, screenshot, or link to a repository
label: Snack, screenshot, or link to a repository
description: |
Please provide a Snack (https://snack.expo.dev/), a link to a repository on GitHub, or provide a minimal code example that reproduces the problem.
Please provide a Snack (https://snack.expo.dev/), a link to a repository on GitHub that reproduces the problem.
You may provide a screenshot of the application if you think it is relevant to your bug report.
Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve
Please note that a reproducer is **mandatory**. Issues without reproducer are more likely to stall and will be closed.
Expand Down
59 changes: 45 additions & 14 deletions .github/workflow-scripts/checkForReproducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
*/

const NEEDS_REPRO_LABEL = 'Needs: Repro';
const NEEDS_REPRO_MESSAGE = '| Missing Reproducible Example |';
const NEEDS_REPRO_HEADER = 'Missing Reproducible Example';
const NEEDS_REPRO_MESSAGE =
`| :warning: | Missing Reproducible Example |\n` +
`| --- | --- |\n` +
`| :information_source: | We could not detect a reproducible example in your issue report. Please provide either: <br /><ul><li>If your bug is UI related: a [Snack](https://snack.expo.dev)</li><li> If your bug is build/update related: use our [Reproducer Template](https://github.com/react-native-community/reproducer-react-native/generate). A reproducer needs to be in a GitHub repository under your username.</li></ul> |`;

module.exports = async (github, context) => {
const issueData = {
Expand All @@ -20,30 +24,35 @@ module.exports = async (github, context) => {
const issue = await github.rest.issues.get(issueData);
const comments = await github.rest.issues.listComments(issueData);

const botComment = comments.data.find(comment =>
comment.body.includes(NEEDS_REPRO_MESSAGE),
const author = issue.data.user.login;

const maintainerChangedLabel = await hasMaintainerChangedLabel(
github,
issueData,
author,
);

let commentBodies = comments.data.map(comment => comment.body);
if (botComment) {
commentBodies = commentBodies.filter(body => body !== botComment.body);
if (maintainerChangedLabel) {
return;
}

const issueAndComments = [issue.data.body, ...commentBodies];
const issueAndCommentsUniq = [...new Set(issueAndComments)];
const botComment = comments.data.find(comment =>
comment.body.includes(NEEDS_REPRO_HEADER),
);

const user = issue.data.user.login;
const entities = [issue.data, ...comments.data];

const hasValidReproducer = issueAndCommentsUniq.some(body => {
// Look for Snack or a GH repo associated with the user that added an issue or comment
const hasValidReproducer = entities.some(entity => {
const hasExpoSnackLink = containsPattern(
body,
entity.body,
`https?:\\/\\/snack\\.expo\\.dev\\/[^\\s)\\]]+`,
);

const hasGithubRepoLink = containsPattern(
body,
`https?:\\/\\/github\\.com\\/(${user})\\/[^/]+\\/?\\s?`,
entity.body,
`https?:\\/\\/github\\.com\\/(${entity.user.login})\\/[^/]+\\/?\\s?`,
);

return hasExpoSnackLink || hasGithubRepoLink;
});

Expand All @@ -70,10 +79,32 @@ module.exports = async (github, context) => {
...issueData,
labels: [NEEDS_REPRO_LABEL],
});

if (botComment) return;

await github.rest.issues.createComment({
...issueData,
body: NEEDS_REPRO_MESSAGE,
});
}
};

function containsPattern(body, pattern) {
const regexp = new RegExp(pattern, 'gm');
return body.search(regexp) !== -1;
}

// Prevents the bot from responding when maintainer has changed Needs: Repro the label
async function hasMaintainerChangedLabel(github, issueData, author) {
const timeline = await github.rest.issues.listEventsForTimeline(issueData);

const labeledEvents = timeline.data.filter(
event => event.event === 'labeled' || event.event === 'unlabeled',
);
const userEvents = labeledEvents.filter(event => event.actor.type !== 'Bot');

return userEvents.some(
event =>
event.actor.login !== author && event.label.name === NEEDS_REPRO_LABEL,
);
}
2 changes: 1 addition & 1 deletion .github/workflows/check-for-reproducer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
jobs:
check-for-reproducer:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native' && github.event.issue.pull_request == null
if: github.repository == 'facebook/react-native' && github.event.issue.pull_request == null && github.event.issue.state == 'open'
steps:
- uses: actions/checkout@v3
- uses: actions/github-script@v6
Expand Down

0 comments on commit 3f78fa9

Please sign in to comment.