Skip to content

Commit

Permalink
Update requirments
Browse files Browse the repository at this point in the history
  • Loading branch information
AayushSaini101 committed Jul 8, 2024
1 parent 998863c commit 8b7fb66
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 114 deletions.
287 changes: 173 additions & 114 deletions .github/scripts/vote_tracker.js
Original file line number Diff line number Diff line change
@@ -1,128 +1,187 @@
const yaml = require('js-yaml');
const fs = require('fs');
const { readFile, writeFile } = require('fs').promises;
const path = require('path');

module.exports = async ({ github, context, core }) => {

const message = context.payload.comment.body;
const eventNumber = context.issue.number;
const eventTitle = context.payload.issue.title
const orgName = context.issue.owner
const repoName = context.issue.repo

const filePath = path.join('VoteTracking.json');

const bindingVotesSectionMatch = message.match(/Binding votes \(\d+\)[\s\S]*?(?=(<details>|$))/);
const bindingVotesSection = bindingVotesSectionMatch ? bindingVotesSectionMatch[0] : '';
const rows = bindingVotesSection.match(/\| @\w+.*?\|.*?\|.*?\|/g) || [];
const latestVotes = rows.map(row => {
const [, user, vote, timestamp] = row.split('|').map(col => col.trim());
return { user: user.replace('@', ''), vote, timestamp, isVotedInLast3Months: true };
});

const yamlData = fs.readFileSync('MAINTAINERS.yaml', 'utf8');
const parsedData = yaml.load(yamlData);
// Initialize vote tracking file if it doesn't exist
if (!fs.existsSync(filePath)) {
const tscMembers = parsedData.filter(entry => entry.isTscMember).map(entry => ({
name: entry.github,
lastParticipatedVoteTime: '',
isVotedInLast3Months: 'false',
lastVoteClosedTime: new Date().toISOString().split('T')[0],
agreeCount: 0,
disagreeCount: 0,
abstainCount: 0,
notParticipatingCount: 0
}));
fs.writeFileSync(filePath, JSON.stringify(tscMembers, null, 2));
}
module.exports = async ({ context }) => {
try {
// Extract necessary details from the context
const message = context.payload.comment.body;
const eventNumber = context.issue.number;
const eventTitle = context.payload.issue.title;
const orgName = context.issue.owner;
const repoName = context.issue.repo;

// Path to the vote tracking file
const voteTrackingFile = path.join('voteTrackingFile.json');

// Parse the vote-closed comment to get voting rows
const votingRows = await parseVoteClosedComment();

// Extract latest votes information from the parsed voting rows
const latestVotes = votingRows.map(row => {
const [, user, vote, timestamp] = row.split('|').map(col => col.trim());
return { user: user.replace('@', ''), vote, timestamp, isVotedInLast3Months: true };
});

// Read and parse the MAINTAINERS.yaml file
const maintainerInfo = await readFile('MAINTAINERS.yaml', 'utf8');
const maintainerInformation = yaml.load(maintainerInfo);

// Update the TSC Members if new one added in the community
await updateVoteTrackingFile();

// Read and parse the vote tracking file
const voteDetails = JSON.parse(await readFile(voteTrackingFile, 'utf8'));

const updatedVoteDetails = [];

const voteDetails = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const latestVotesInfo = []
voteDetails.map(voteInfo => {
const checkPersonisTSC = parsedData.some(item => item.github === voteInfo.name);
if (checkPersonisTSC) {
const currentTime = new Date().toISOString().split('T')[0];
const userInfo = latestVotes.find(vote => vote.user === voteInfo.name);
const choice = userInfo ? userInfo.vote : "Not participated";

if (userInfo) {
voteInfo.isVotedInLast3Months = true;
voteInfo.lastParticipatedVoteTime = currentTime;
voteInfo[choice === "In favor" ? 'agreeCount' : choice === "Against" ? 'disagreeCount' : 'abstainCount']++;
} else {
voteInfo.notParticipatingCount++;
voteInfo.lastVoteClosedTime = currentTime;
if (!checkVotingDurationMoreThanThreeMonths(voteInfo)) {
voteInfo.isVotedInLast3Months = false;
// Process each vote detail to update voting information
voteDetails.forEach(voteInfo => {
// Checking only valid vote done by TSC Member
const isTscMember = maintainerInformation.some(item => item.github === voteInfo.name);

if (isTscMember) {
const currentTime = new Date().toISOString().split('T')[0];
const userInfo = latestVotes.find(vote => vote.user === voteInfo.name);
const voteChoice = userInfo ? userInfo.vote : "Not participated";

if (userInfo) {
voteInfo.isVotedInLast3Months = true;
voteInfo.lastParticipatedVoteTime = currentTime;
voteInfo[voteChoice === "In favor" ? 'agreeCount' : voteChoice === "Against" ? 'disagreeCount' : 'abstainCount']++;
} else {
voteInfo.notParticipatingCount++;
voteInfo.lastVoteClosedTime = currentTime;
if (!isVotingWithinLastThreeMonths(voteInfo)) {
voteInfo.isVotedInLast3Months = false;
}
}

// Update vote information with the issue title and number
// The order is after name the Issue number or PR number should be present
let updatedVoteInfo = {};
Object.keys(voteInfo).forEach(key => {
if (key === 'name') {
updatedVoteInfo['name'] = voteInfo.name;
updatedVoteInfo[eventTitle + "$$" + eventNumber] = voteChoice;
} else {
updatedVoteInfo[key] = voteInfo[key];
}
});
updatedVoteDetails.push(updatedVoteInfo);
}

let updatedVoteInfo = {};
Object.keys(voteInfo).forEach(key => {
if (key == 'name') {
updatedVoteInfo['name'] = voteInfo.name
updatedVoteInfo[eventTitle + "$$" + eventNumber] = choice
});

// Write the updated vote details back to the file
try {
await writeFile(voteTrackingFile, JSON.stringify(updatedVoteDetails, null, 2));
} catch (writeError) {
console.error('Error writing to voteTrackingFile.json:', writeError);
}

// Generate the markdown table and write it to a file
const markdownTable = await jsonToMarkdownTable(updatedVoteDetails);
try {
await writeFile('voteTrackingDetails.md', markdownTable);
console.log('Markdown table has been written to voteTrackingDetails.md');
} catch (writeError) {
console.error('Error writing to voteTrackingDetails.md:', writeError);
}

// Functions are defined below
// Convert JSON data to a markdown table
async function jsonToMarkdownTable(data) {
const keys = Object.keys(data[0]);
let markdownTable = '| ' + keys.map(key => {
if (key.includes('$$')) {
const [title, number] = key.split('$$');
return `[${title}](https://github.com/${orgName}/${repoName}/issues/${number})`;
}
else {
updatedVoteInfo[key] = voteInfo[key];
const titles = {
name: "GitHub user name",
lastParticipatedVoteTime: "Last time the TSC member participated in a vote",
hasVotedInLast3Months: "Flag indicating if TSC member voted in last 3 months. This information is calculated after each voting, and not basing on a schedule as there might be moments when there is no voting in place for 3 months and therefore no TSC member votes.",
lastVoteClosedTime: "Date when last vote was closed. It indicated when the last voting took place and marks the date when this tracking document was updated.",
agreeCount: "Number of times TSC member agreed in a vote.",
disagreeCount: "Number of times TSC member did not agree in a vote.",
abstainCount: "Number of times TSC member abstained from voting.",
notParticipatingCount: "Number of times TSC member did not participate in voting."
};
return `<span style="position: relative; cursor: pointer;" title="${titles[key] || key}">${key}</span>`;
}).join(' | ') + ' |\n';

markdownTable += '| ' + keys.map(() => '---').join(' | ') + ' |\n';
markdownTable += data.map(obj => '| ' + keys.map(key => {
if (key === 'name') return `[${obj[key]}](https://github.com/${obj[key]})`;
if (key.includes('$$')) {
const icons = {
"In favor": "👍",
"Against": "👎",
"Abstain": "👀",
"Not participated": "🔕"
};
return `<span style="position: relative; cursor: pointer;" title="${obj[key]}">${icons[obj[key]] || obj[key]}</span>`;
}
})
latestVotesInfo.push(updatedVoteInfo)
return obj[key];
}).join(' | ') + ' |').join('\n');

return markdownTable;
}
});

fs.writeFileSync(filePath, JSON.stringify(latestVotesInfo, null, 2));

// Check voting duration
function checkVotingDurationMoreThanThreeMonths(voteInfo) {
const currentDate = new Date();
const threeMonthsAgoDate = new Date(currentDate);
threeMonthsAgoDate.setMonth(currentDate.getMonth() - 3);
return new Date(voteInfo.lastVoteClosedTime) >= threeMonthsAgoDate &&
new Date(voteInfo.lastParticipatedVoteTime) <= threeMonthsAgoDate;
}

// Convert JSON data to markdown table
function jsonToMarkdownTable(data) {
const keys = Object.keys(data[0]);
let markdownTable = '| ' + keys.map(key => {
if (key.includes('$$')) {
const [title, number] = key.split('$$');
return `[${title}](https://github.com/${orgName}/${repoName}/issues/${number})`;
}
const titles = {
name: "GitHub user name",
lastParticipatedVoteTime: "Last time the TSC member participated in a vote",
hasVotedInLast3Months: "Flag indicating if TSC member voted in last 3 months. This information is calculated after each voting, and not basing on a schedule as there might be moments when there is no voting in place for 3 months and therefore no TSC member votes.",
lastVoteClosedTime: "Date when last vote was closed. It indicated when the last voting took place and marks the date when this tracking document was updated.",
agreeCount: "Number of times TSC member agreed in a vote.",
disagreeCount: "Number of times TSC member did not agree in a vote.",
abstainCount: "Number of times TSC member abstained from voting.",
notParticipatingCount: "Number of times TSC member did not participate in voting."
};
return `<span style="position: relative; cursor: pointer;" title="${titles[key] || key}">${key}</span>`;
}).join(' | ') + ' |\n';

markdownTable += '| ' + keys.map(() => '---').join(' | ') + ' |\n';
markdownTable += data.map(obj => '| ' + keys.map(key => {
if (key === 'name') return `[${obj[key]}](https://github.com/${obj[key]})`;
if (key.includes('$$')) {
const icons = {
"In favor": "👍",
"Against": "👎",
"Abstain": "👀",
"Not participated": "🔕"
};
return `<span style="position: relative; cursor: pointer;" title="${obj[key]}">${icons[obj[key]] || obj[key]}</span>`;
// Parse the vote-closed comment created by git-vote[bot]
async function parseVoteClosedComment() {
const bindingVotesSectionMatch = message.match(/Binding votes \(\d+\)[\s\S]*?(?=(<details>|$))/);
const bindingVotesSection = bindingVotesSectionMatch ? bindingVotesSectionMatch[0] : '';
return bindingVotesSection.match(/\| @\w+.*?\|.*?\|.*?\|/g) || [];
}

// Check if voting duration is within the last three months
function isVotingWithinLastThreeMonths(voteInfo) {
const currentDate = new Date();
const threeMonthsAgoDate = new Date(currentDate);
threeMonthsAgoDate.setMonth(currentDate.getMonth() - 3);
return new Date(voteInfo.lastVoteClosedTime) >= threeMonthsAgoDate &&
new Date(voteInfo.lastParticipatedVoteTime) <= threeMonthsAgoDate;
}

// Function to update the voteTrackingFile with updated TSC Members
async function updateVoteTrackingFile() {
const tscMembers = maintainerInformation.filter(entry => entry.isTscMember);
let voteDetails = [];
try {
voteDetails = JSON.parse(await readFile(voteTrackingFile, 'utf8'));
} catch (readError) {
console.error('Error reading voteTrackingFile.json:', readError);
}
return obj[key];
}).join(' | ') + ' |').join('\n');

return markdownTable;
const newTSCMembers = [];

tscMembers.forEach(member => {
const existingMember = voteDetails.find(voteInfo => voteInfo.name === member.github);
if (!existingMember) {
newTSCMembers.push({
name: member.github,
lastParticipatedVoteTime: '',
isVotedInLast3Months: 'false',
lastVoteClosedTime: new Date().toISOString().split('T')[0],
agreeCount: 0,
disagreeCount: 0,
abstainCount: 0,
notParticipatingCount: 0
});
}
});
if (updatedTSCMembers.length > 0) {
try {
const combinedData = [...voteDetails, ...newTSCMembers];
await writeFile(voteTrackingFile, JSON.stringify(combinedData, null, 2));
} catch (writeError) {
console.error('Error writing to voteTrackingFile.json:', writeError);
}
}
}
} catch (error) {
console.error('Error in while running the vote_tracker workflow:', error);
}

const markdownTable = jsonToMarkdownTable(latestVotesInfo);
fs.writeFileSync('voteTrackingDetails.md', markdownTable);
console.log('Markdown table has been written to voteTrackingDetails.md');
}
};
12 changes: 12 additions & 0 deletions voteTrackingFile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"name": "Mayaleeeee",
"lastParticipatedVoteTime": "",
"isVotedInLast3Months": "false",
"lastVoteClosedTime": "2024-07-07",
"agreeCount": 0,
"disagreeCount": 0,
"abstainCount": 0,
"notParticipatingCount": 0
}
]

0 comments on commit 8b7fb66

Please sign in to comment.