Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions scripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ const CLOSE_CONTRIBUTORS = [
'muditchoudhary',
'nathanaelg16',
'nikkuAg',
'Prashant-thakur77',
'Sahil-Sinha-11',
'shivam-daksh',
'shruti862',
'thesujai',
'vtushar06',
'WinnyChang',
'yeshwanth235',
];
Expand Down Expand Up @@ -96,6 +98,9 @@ const PR_STATS_REPOS = [
'ricecooker',
];

// Repositories in which we accept open-source contributions
const COMMUNITY_REPOS = [...PR_STATS_REPOS];

module.exports = {
LE_BOT_USERNAME,
SENTRY_BOT_USERNAME,
Expand All @@ -109,4 +114,5 @@ module.exports = {
TEAMS_WITH_CLOSE_CONTRIBUTORS,
HOLIDAY_MESSAGE,
PR_STATS_REPOS,
COMMUNITY_REPOS,
};
53 changes: 6 additions & 47 deletions scripts/contributor-issue-comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,18 @@ const {
ISSUE_LABEL_HELP_WANTED,
BOT_MESSAGE_ISSUE_NOT_OPEN,
BOT_MESSAGE_ALREADY_ASSIGNED,
COMMUNITY_REPOS,
} = require('./constants');
const {
isCloseContributor,
sendBotMessage,
escapeIssueTitleForSlackMessage,
hasRecentBotComment,
hasLabel,
getIssues,
getPullRequests,
} = require('./utils');

async function hasLabel(name, owner, repo, issueNumber, github, core) {
let labels = [];
try {
const response = await github.rest.issues.listLabelsOnIssue({
owner,
repo,
issue_number: issueNumber,
});
labels = response.data.map(label => label.name);
} catch (error) {
core.warning(`Failed to fetch labels on issue #${issueNumber}: ${error.message}`);
labels = [];
}
return labels.some(label => label.toLowerCase() === name.toLowerCase());
}

async function getIssues(assignee, state, owner, repo, github, core) {
try {
const response = await github.rest.issues.listForRepo({
owner,
repo,
assignee,
state,
});
return response.data.filter(issue => !issue.pull_request);
} catch (error) {
core.warning(`Failed to fetch issues: ${error.message}`);
return [];
}
}

async function getPullRequests(assignee, state, owner, repo, github, core) {
try {
const response = await github.rest.pulls.list({
owner,
repo,
state,
});
return response.data.filter(pr => pr.user.login === assignee);
} catch (error) {
core.warning(`Failed to fetch pull requests: ${error.message}`);
return [];
}
}

// Format information about author's assigned open issues
// as '(Issues #1 #2 | PRs #3)' and PRs for Slack message
function formatAuthorActivity(issues, pullRequests) {
Expand Down Expand Up @@ -201,8 +160,8 @@ module.exports = async ({ github, context, core }) => {

if (contactSupport) {
const [assignedOpenIssues, openPRs] = await Promise.all([
getIssues(commentAuthor, 'open', owner, repo, github, core),
getPullRequests(commentAuthor, 'open', owner, repo, github, core),
getIssues(commentAuthor, 'open', owner, COMMUNITY_REPOS, github, core),
getPullRequests(commentAuthor, 'open', owner, COMMUNITY_REPOS, github, core),
]);
const authorActivity = formatAuthorActivity(assignedOpenIssues, openPRs);
slackMessage += ` _${authorActivity}_`;
Expand Down
67 changes: 67 additions & 0 deletions scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,78 @@ async function hasRecentBotComment(
}
}

/**
* Checks if an issue has a label with the given name (case-insensitive).
*/
async function hasLabel(name, owner, repo, issueNumber, github, core) {
let labels = [];
try {
const response = await github.rest.issues.listLabelsOnIssue({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one question here the data received is it paginated? Do we get all the issues in one go?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Do we get all the issues in one go?

We're fetching only one issue here - by the issue number.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As for labels, I will look into it

owner,
repo,
issue_number: issueNumber,
});
labels = response.data.map(label => label.name);
} catch (error) {
core.warning(`Failed to fetch labels on issue #${issueNumber}: ${error.message}`);
labels = [];
}
return labels.some(label => label.toLowerCase() === name.toLowerCase());
}

/**
* Fetches issues assigned to an assignee in given repositories.
*/
async function getIssues(assignee, state, owner, repos, github, core) {
const promises = repos.map(repo =>
github.rest.issues
.listForRepo({
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same for this and getPullRequests function as well? If we are getting a limited amount of issues in one pass then its not whats expected right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, I will have a look

owner,
repo,
assignee,
state,
})
.then(response => response.data.filter(issue => !issue.pull_request))
.catch(error => {
core.warning(`Failed to fetch issues from ${repo}: ${error.message}`);
return [];
}),
);

const results = await Promise.all(promises);
return results.flat();
}

/**
* Fetches pull requests by an author in given repositories.
*/
async function getPullRequests(author, state, owner, repos, github, core) {
const promises = repos.map(repo =>
github.rest.pulls
.list({
owner,
repo,
state,
})
.then(response => response.data.filter(pr => pr.user.login === author))
.catch(error => {
core.warning(`Failed to fetch pull requests from ${repo}: ${error.message}`);
return [];
}),
);

const results = await Promise.all(promises);
return results.flat();
}

module.exports = {
isContributor,
isCloseContributor,
isBot,
sendBotMessage,
escapeIssueTitleForSlackMessage,
hasRecentBotComment,
hasLabel,
getIssues,
getPullRequests,
};