Skip to content
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

Maintenance and adjustment to "Schedule Monthly" workflow #7638

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ const botMembers = ['elizabethhonest', 'hfla-website-checklist', 'HackforLABot']

// Set date limits: we are sorting inactive members into groups to notify after 1 month and remove after 2 months.
// Since the teams take off December and July, the Jan. 1st and Aug. 1st runs are skipped (via `schedule-monthly.yml`).
// The Feb. 1st and Sept. 1st runs account for skipped months: 'oneMonth' & 'twoMonths' = 2 & 3 months respectively
// The Feb. 1st and Sept. 1st runs account for skipped months: 'oneMonth' & 'twoMonths' = 1 & 3 months respectively
let today = new Date();
let oneMonth = (today.getMonth() === 1 || today.getMonth() === 8) ? 2 : 1;
let twoMonths = (today.getMonth() === 1 || today.getMonth() === 8) ? 3 : 2;

let oneMonthAgo = new Date(); // oneMonthAgo instantiated with date of "today"
oneMonthAgo.setMonth(oneMonthAgo.getMonth() - oneMonth); // then set oneMonthAgo from "today"
let oneMonthAgo = new Date(); // oneMonthAgo instantiated with date of "today"
oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); // then set oneMonthAgo from "today"
oneMonthAgo = oneMonthAgo.toISOString();
let twoMonthsAgo = new Date(); // twoMonthsAgo instantiated with date of "today"
twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - twoMonths); // then set twoMonthsAgo from "today"
Expand All @@ -37,7 +36,7 @@ async function main({ g, c }) {
context = c;

const [contributorsOneMonthAgo, contributorsTwoMonthsAgo, inactiveWithOpenIssue] = await fetchContributors(dates);
console.log('-------------------------------------------------------');
console.log(`-`.repeat(60));
console.log('List of active contributors since ' + dates[0].slice(0, 10) + ':');
console.log(contributorsOneMonthAgo);

Expand Down Expand Up @@ -122,10 +121,11 @@ async function fetchContributors(dates){
if(responseObject.result === false){
allContributorsSince[assignee] = true;
}
// If timeline is more than two months ago, add to open issues with inactive
// comments with flag = true if issue is "Pre-work Checklist", false otherwise
else if(date === dates[1]){
if(contributorInfo.title.includes("Pre-work Checklist")){
// If timeline is more than two months ago, add to open issues with inactive. Then check if
// issue title includes "Pre-work Checklist" or "Skills Issue" and set flag = true, else set false
else if (date === dates[1]) {
const regex = /Pre-work checklist|Skills Issue/i;
if (regex.test(contributorInfo.title)) {
inactiveWithOpenIssue[assignee] = [issueNum, true];
} else {
inactiveWithOpenIssue[assignee] = [issueNum, false];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The bot is checking for the following activity:
- If you are assigned to an issue, that you have provided an update on the issue in the past 30 days. The updates are due weekly.
- If your issue is a `Draft` in the "New Issue Approval" column, that you have added to it within the last 30 days.
- If you are reviewing PRs, that you have posted a review comment within the past 30 days.
- If you are newly onboarded, that you are assigned to your "Pre-work checklist" and you have cloned the HfLA website repo to your personal repo.
- If you are newly onboarded, that you are assigned to your "Skills Issue" and you have cloned the HfLA website repo to your personal repo.

If you have been inactive in the last 30 days (using the above measurements), you can become active again by doing at least one of the above actions. If you do not do at least one of the above actions, the bot will automatically remove you from the 'website-write' team in the next 30 days.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,23 @@ async function main({ g, c }, { recentContributors, previousContributors, inacti
context = c;

const currentTeamMembers = await getTeamMembers(github, context, writeTeam);
console.log('-------------------------------------------------------');
console.log(`-`.repeat(60));
console.log('Current members of ' + writeTeam + ':');
console.log(currentTeamMembers);

const [removedContributors, cannotRemoveYet] = await removeInactiveMembers(previousContributors, inactiveWithOpenIssue);
console.log('-------------------------------------------------------');
const [removedContributors, cannotRemoveYet] = await removeInactiveMembers(previousContributors, inactiveWithOpenIssue, currentTeamMembers);
console.log(`-`.repeat(60));
console.log('Removed members from ' + writeTeam + ' inactive since ' + dates[1].slice(0, 10) + ':');
console.log(removedContributors);

console.log('-------------------------------------------------------');
console.log(`-`.repeat(60));
console.log('Members inactive since ' + dates[1].slice(0, 10) + ' with open issues preventing removal:');
console.log(cannotRemoveYet);

// Repeat getTeamMembers() after removedContributors to compare with recentContributors
const updatedTeamMembers = await getTeamMembers(github, context, writeTeam);
const notifiedContributors = await notifyInactiveMembers(updatedTeamMembers, recentContributors);
console.log('-------------------------------------------------------');
console.log(`-`.repeat(60));
console.log('Notified members from ' + writeTeam + ' inactive since ' + dates[0].slice(0, 10) + ':');
console.log(notifiedContributors);

Expand All @@ -61,11 +61,10 @@ async function main({ g, c }, { recentContributors, previousContributors, inacti
* @returns {Array} removedMembers - List of members that were removed
* @returns {Object} cannotRemoveYet - List of members that cannot be removed due to open issues
*/
async function removeInactiveMembers(previousContributors, inactiveWithOpenIssue){
async function removeInactiveMembers(previousContributors, inactiveWithOpenIssue, currentTeamMembers){
const removedMembers = [];
const cannotRemoveYet = {};
const previouslyNotified = await readPreviousNotifyList();
const currentTeamMembers = await getTeamMembers(github, context, writeTeam);

// Loop over team members and remove them from the team if they are not in previousContributors list
for(const username in currentTeamMembers){
Expand All @@ -81,14 +80,15 @@ async function removeInactiveMembers(previousContributors, inactiveWithOpenIssue
// Remove member from all teams (except baseTeam)
const teams = [writeTeam, mergeTeam];
for(const team of teams){
// https://docs.github.com/en/rest/teams/members?apiVersion=2022-11-28#remove-team-membership-for-a-user
await github.request('DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}', {
org: context.repo.owner,
team_slug: team,
username: username,
});
}
removedMembers.push(username);
// After removal, close member's "Pre-work checklist" if open
// After removal, close member's "Skills Issue", if open
if(username in inactiveWithOpenIssue && inactiveWithOpenIssue[username][1] === true){
closePrework(username, inactiveWithOpenIssue[username][0]);
}
Expand All @@ -101,20 +101,20 @@ async function removeInactiveMembers(previousContributors, inactiveWithOpenIssue


/**
* Function to close a just-removed inactive member's "Pre-work checklist", if open, and add a comment
* @param {String} member - name of member whose "Pre-work checklist" will be closed
* @param {Number} issueNum - number of member's "Pre-work checklist"
* Function to close a just-removed inactive member's "Skills Issue", if open, and add a comment
* @param {String} member - name of member whose "Skills Issue" will be closed
* @param {Number} issueNum - number of member's "Skills Issue"
*/
async function closePrework(member, issueNum){
// Close the assignee's "Pre-work Checklist" and add comment
// https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#update-an-issue
await github.request('PATCH /repos/{owner}/{repo}/issues/{issue_number}', {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNum,
state: 'closed'
});
console.log('Closing "Pre-work Checklist" issue number ' + issueNum + ' for ' + member);
// Add comment to issue
console.log(`Closing "Skills Issue" issue number ${issueNum} for ${member}`);
// https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#create-an-issue-comment
await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', {
owner: context.repo.owner,
repo: context.repo.repo,
Expand Down Expand Up @@ -211,8 +211,8 @@ function writeData(removedContributors, notifiedContributors, cannotRemoveYet){

fs.writeFile(filepath, JSON.stringify(inactiveMemberLists, null, 2), (err) => {
if (err) throw err;
console.log('-------------------------------------------------------');
console.log("File 'inactive-members.json' saved successfully!");
console.log(`-`.repeat(60));
console.log("File `inactive-members.json` saved successfully!");
});
}

Expand Down