Skip to content
Open
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
ac5d680
changed content field-removed type field
Adaakal Jan 6, 2023
55ad4d9
removed the space from line 11
Adaakal Jan 10, 2023
a625f1d
Updated Size label to level in github-actions
bzzz-coding Jan 13, 2023
0451435
Merge pull request #2 from bzzz-coding/modify-github-actions-for-labe…
bzzz-coding Jan 13, 2023
d4d5fc1
Revert "Updated Size label to level in github-actions"
bzzz-coding Jan 13, 2023
bcaf9cd
Merge pull request #4 from bzzz-coding/revert-2-modify-github-actions…
bzzz-coding Jan 13, 2023
2f6e401
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Jan 18, 2023
9d4804e
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Jan 19, 2023
c076fec
Merge branch 'hackforla:gh-pages' into gh-pages
Jan 19, 2023
8877384
attempting to putt from upstream gh-pages
Adaakal Jan 19, 2023
1311a1e
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Jan 25, 2023
51703df
bringing my gh-pages current
Adaakal Jan 26, 2023
8eada0b
Merge branch 'hackforla:gh-pages' into gh-pages
Jan 26, 2023
e0c5a91
bringing my gh-pages current
Adaakal Jan 26, 2023
b2f4c3f
Merge branch 'gh-pages' of https://github.com/hackforla/website into …
Adaakal Jan 26, 2023
fc1505c
Merge branch 'gh-pages' of https://github.com/Adaakal/website into gh…
Adaakal Jan 28, 2023
ad8f11f
changed alt text In the file __includes/about-page/about-card-sustain…
Adaakal Jan 28, 2023
48c4ba6
Merge branch 'update-alt-text-3383' into gh-pages
Adaakal Jan 29, 2023
e95530a
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 1, 2023
e38f829
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 2, 2023
9e6b08a
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 7, 2023
3e8830f
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 7, 2023
9a31aae
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 10, 2023
884e658
complete merge
Adaakal Feb 13, 2023
863ec92
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 17, 2023
a43b58b
used justify-content: flex-start to center resource-list
Adaakal Feb 20, 2023
150ea71
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 22, 2023
089c510
Added comment on line 319 for testing
bzzz-coding Feb 23, 2023
c9b59ef
removed added lines from .vscode/settings.json
Adaakal Feb 24, 2023
1eeeeff
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Feb 24, 2023
c81c6a6
Merge branch 'hackforla:gh-pages' into gh-pages
bzzz-coding Mar 2, 2023
4972132
Merge branch 'gh-pages' of https://github.com/bzzz-coding/HfLA-websit…
bzzz-coding Mar 4, 2023
cf4cccd
Merge branch 'gh-pages' of https://github.com/bzzz-coding/HfLA-websit…
bzzz-coding Mar 4, 2023
2968c45
Adjusted logic, Edited isTimelineOutdated function and main function
bzzz-coding Mar 4, 2023
bde9e4d
Removed async keyword from isTimelineOutdated function definition
bzzz-coding Mar 4, 2023
4247125
Updated comments
bzzz-coding Mar 4, 2023
775a83f
Syntax bug fix
bzzz-coding Mar 5, 2023
0303d05
Edited isTimelineOutdated function
bzzz-coding Mar 5, 2023
0c72a70
Edited comments
bzzz-coding Mar 7, 2023
49a3e09
Merge branch 'gh-pages' of https://github.com/bzzz-coding/HfLA-websit…
bzzz-coding Mar 7, 2023
bb1dc3f
Merge branch 'hackforla:gh-pages' into fix-alignment-and-scaling-3118
Mar 7, 2023
34bb9f1
removed margin-left: auto from @media (max-width: 479px) .resource-list
Adaakal Mar 7, 2023
7360107
Merge branch 'fix-alignment-and-scaling-3118' of https://github.com/A…
Adaakal Mar 7, 2023
2d7fa23
Merge branch 'hackforla:gh-pages' into fix-alignment-and-scaling-3118
Mar 7, 2023
5c618c6
Merge branch 'gh-pages' of https://github.com/bzzz-coding/HfLA-websit…
bzzz-coding Mar 7, 2023
32dddfc
Merge branch 'fix-alignment-and-scaling-3118' of https://github.com/A…
bzzz-coding Mar 7, 2023
8aba358
Revised code based on latest discussion
bzzz-coding Mar 14, 2023
4813f98
Updated function logic and comments in add-labels.js
bzzz-coding Mar 14, 2023
6dbb0c8
Sync up helper function
bzzz-coding Mar 14, 2023
c26ce98
Merge branch 'gh-pages' of https://github.com/bzzz-coding/HfLA-websit…
bzzz-coding Mar 14, 2023
d5d8683
Merge branch 'gh-pages' into bzzz-testing-branch
bzzz-coding Mar 14, 2023
f530192
Fixed bug
bzzz-coding Mar 15, 2023
3c12007
Fixed bug and added comments
bzzz-coding Mar 15, 2023
027eb73
Merge branch 'gh-pages' of https://github.com/hackforla/website into …
bzzz-coding Mar 17, 2023
86dacb8
Edited comments and added console logging
bzzz-coding Mar 17, 2023
91d2080
Merge branch 'gh-pages' of https://github.com/bzzz-coding/HfLA-websit…
bzzz-coding Mar 17, 2023
0a03a00
Merge branch 'gh-pages' of https://github.com/hackforla/website into …
bzzz-coding Mar 17, 2023
15921ea
Merge branch 'gh-pages' into bzzz-testing-branch
bzzz-coding Mar 17, 2023
84b4e69
Synced up to upstream and merged 3341
bzzz-coding Mar 17, 2023
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
247 changes: 116 additions & 131 deletions github-actions/add-update-label-weekly/add-label.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ var context;
const statusUpdatedLabel = 'Status: Updated';
const toUpdateLabel = 'To Update !';
const inactiveLabel = '2 weeks inactive';
const updatedByDays = 3; // number of days ago to check for to update label
const inactiveUpdatedByDays = 14; // number of days ago to check for inactive label
const commentByDays = 7; // number of days ago to check for comment by assignee
const updatedByDays = 3; // If there is an update within 3 days, the issue is considered updated
const inactiveUpdatedByDays = 14; // If no update within 14 days, the issue is considered '2 weeks inactive'
const commentByDays = 7; // If there is an update within 14 days but no update within 7 days, the issue is considered outdated and the assignee needs 'To Update !' it
const threeDayCutoffTime = new Date()
threeDayCutoffTime.setDate(threeDayCutoffTime.getDate() - updatedByDays)
const sevenDayCutoffTime = new Date()
Expand All @@ -18,49 +18,53 @@ const fourteenDayCutoffTime = new Date()
fourteenDayCutoffTime.setDate(fourteenDayCutoffTime.getDate() - inactiveUpdatedByDays)

/**
* The main function, which retrieves issues from a specific column in a specific project, before examining the timeline of each issue for outdatedness. If outdated, the old status label is removed, and an updated is requested. Otherwise, the issue is labeled as updated.
* The main function, which retrieves issues from a specific column in a specific project, before examining the timeline of each issue for outdatedness.
* An update to an issue is either 1. a comment by the assignee, or 2. assigning an assignee to the issue. If the last update is not within 7 days or 14 days, apply the according outdate label, and request an update.
* However, if the assignee has submitted a PR that fixed the issue regardless of when, all update-related labels should be removed.

* @param {Object} g github object from actions/github-script
* @param {Object} c context object from actions/github-script
* @param {Number} columnId a number presenting a specific column to examine, supplied by GitHub secrets
*/
async function main({ g, c }, columnId) {
github = g;
context = c;
// Retrieve all issue numbers from a column
const issueNums = getIssueNumsFromColumn(columnId);
for await (let issueNum of issueNums) {
const timeline = await getTimeline(issueNum);
const timelineArray = Array.from(timeline);
const assignees = await getAssignees(issueNum);
// Error catching.
if (assignees.length === 0) {
console.log(`Assignee not found, skipping issue #${issueNum}`)
continue
}

// Add and remove labels as well as post comment if the issue's timeline indicates the issue is inactive, to be updated or up to date accordingly
const responseObject = await isTimelineOutdated(timeline, issueNum, assignees)
if (responseObject.result === true && responseObject.labels === toUpdateLabel) {
console.log(`Going to ask for an update now for issue #${issueNum}`);
await removeLabels(issueNum, statusUpdatedLabel, inactiveLabel);
await addLabels(issueNum, responseObject.labels);
await postComment(issueNum, assignees, toUpdateLabel);
} else if (responseObject.result === true && responseObject.labels === statusUpdatedLabel) {
await removeLabels(issueNum, toUpdateLabel, inactiveLabel);
await addLabels(issueNum, responseObject.labels);
} else if (responseObject.result === true && responseObject.labels === inactiveLabel) {
console.log(`Going to ask for an update now for issue #${issueNum}`);
await removeLabels(issueNum, toUpdateLabel, statusUpdatedLabel);
await addLabels(issueNum, responseObject.labels);
await postComment(issueNum, assignees, inactiveLabel);
} else {
console.log(`No updates needed for issue #${issueNum}`);
await removeLabels(issueNum, toUpdateLabel, inactiveLabel);
await addLabels(issueNum, responseObject.labels);
}
}
}

github = g;
context = c;
// Retrieve all issue numbers from a column
const issueNums = getIssueNumsFromColumn(columnId);
for await (let issueNum of issueNums) {
const timeline = await getTimeline(issueNum);
const timelineArray = Array.from(timeline);
const assignees = await getAssignees(issueNum);
// Error catching.
if (assignees.length === 0) {
console.log(`Assignee not found, skipping issue #${issueNum}`)
continue
}

// Add and remove labels as well as post comment if the issue's timeline indicates the issue is inactive, to be updated or up to date accordingly
const responseObject = await isTimelineOutdated(timeline, issueNum, assignees)


if (responseObject.result === true && responseObject.labels === toUpdateLabel) { // 7-day outdated, add 'To Update !' label
console.log(`Going to ask for an update now for issue #${issueNum}`);
await removeLabels(issueNum, statusUpdatedLabel, inactiveLabel);
await addLabels(issueNum, responseObject.labels);
await postComment(issueNum, assignees, toUpdateLabel);
} else if (responseObject.result === true && responseObject.labels === inactiveLabel) { // 14-day outdated, add '2 Weeks Inactive' label
console.log(`Going to ask for an update now for issue #${issueNum}`);
await removeLabels(issueNum, toUpdateLabel, statusUpdatedLabel);
await addLabels(issueNum, responseObject.labels);
await postComment(issueNum, assignees, inactiveLabel);
} else if (responseObject.result === false && responseObject.labels === statusUpdatedLabel) { // Updated within 3 days, retain 'Status: Updated' label if there is one
console.log(`Updated within 3 days, retain updated label for issue #${issueNum}`);
await removeLabels(issueNum, toUpdateLabel, inactiveLabel);
} else if (responseObject.result === false && responseObject.labels === '') { // Updated between 3 and 7 days, or recently assigned, or fixed by a PR by assignee, remove all three update-related labels
console.log(`No updates needed for issue #${issueNum}, will remove all labels`);
await removeLabels(issueNum, toUpdateLabel, inactiveLabel, statusUpdatedLabel);
}
}
}

/**
* Generator that returns issue numbers from cards in a column.
* @param {Number} columnId the id of the column in GitHub's database
Expand Down Expand Up @@ -99,8 +103,8 @@ async function* getIssueNumsFromColumn(columnId) {
*/

async function getTimeline(issueNum) {
let arra = []
let page = 1
let arra = []
let page = 1
while (true) {
try {
const results = await github.issues.listEventsForTimeline({
Expand All @@ -111,107 +115,88 @@ async function getTimeline(issueNum) {
page: page,
});
if (results.data.length) {
arra = arra.concat(results.data);
arra = arra.concat(results.data);
} else {
break
}
} catch (err) {
console.log(error);
continue
continue
}
finally {
page++
}
}
return arra
return arra
}

/**
* Assesses whether the timeline is outdated.
* @param {Array} timeline a list of events in the timeline of an issue, retrieved from the issues API
* @param {Number} issueNum the issue's number
* @param {String} assignees a list of the issue's assignee's username
* @returns true if timeline indicates the issue is outdated and inactive, false if not; also returns appropriate labels
* Note: Outdated means that the assignee did not make a linked PR or comment within the threedaycutoffTime (see global variables), while inactive is for 14 days
* @returns true if timeline indicates the issue is outdated/inactive, false if not; also returns appropriate labels that should be retained or added to the issue
*/

async function isTimelineOutdated(timeline, issueNum, assignees) {
assignedWithinFourteenDays = false;
for await (let [index, moment] of timeline.entries()) {
if (isMomentRecent(moment.created_at, threeDayCutoffTime)) { // all the events of an issue within last three days will return true
if (moment.event == 'cross-referenced' && isLinkedIssue(moment, issueNum) && assignees == moment.actor.login) { // checks if cross referenced within last three days
return {result: false, labels: statusUpdatedLabel}
}
else if (moment.event == 'commented' && isCommentByAssignees(moment, assignees)) { // checks if commented within last three days
return {result: false, labels: statusUpdatedLabel}
}
else if (moment.event == 'assigned' && assignees == moment.assignee)
{
assignedWithinFourteenDays = true;
}
else if (index === timeline.length-1 && (Date.parse(timeline[0].created_at) < fourteenDayCutoffTime.valueOf())) { // returns true if issue was created before 14 days after comparing the two dates in millisecond format
return {result: true, labels: inactiveLabel}
}
else if (index === timeline.length-1 && (Date.parse(timeline[0].created_at) < threeDayCutoffTime.valueOf())) { // returns true if issue was created before 3 days
return {result: true, labels: toUpdateLabel}
}
else if (index === timeline.length-1) { // returns true if above two else ifs are false meaning issue was created within last 3 days
return {result: true, labels: statusUpdatedLabel}
}
}
else if (isMomentRecent(moment.created_at, sevenDayCutoffTime)) { // all the events of an issue between three and seven days will return true
if (moment.event == 'cross-referenced' && isLinkedIssue(moment, issueNum) && assignees == moment.actor.login) { // checks if cross referenced between 3 and 7 days
console.log('between 3 and 7 cross referenced');
return {result: false, labels: statusUpdatedLabel}
}
else if (moment.event == 'commented' && isCommentByAssignees(moment, assignees)) { // checks if commented between 3 and 7 days
console.log('between 3 and 7 commented');
return {result: false, labels: statusUpdatedLabel}
}
else if (moment.event == 'assigned' && assignees == moment.assignee)
{
assignedWithinFourteenDays = true;
}
else if (index === timeline.length-1 && (Date.parse(timeline[0].created_at) < fourteenDayCutoffTime.valueOf())) { // returns true if issue was created before 14 days after comparing the two dates in millisecond format
return {result: true, labels: inactiveLabel}
}
else if (index === timeline.length-1) { // returns true if the latest event created is between 3 and 7 days
return {result: true, labels: toUpdateLabel}
}
}
else if (isMomentRecent(moment.created_at, fourteenDayCutoffTime)) { // all the events of an issue between seven and fourteen days will return true
if (moment.event == 'cross-referenced' && isLinkedIssue(moment, issueNum) && assignees == moment.actor.login) { // checks if cross referenced between 7 and 14 days
console.log('between 7 and 14 cross referenced');
return {result: false, labels: statusUpdatedLabel}
}
else if (moment.event == 'commented' && isCommentByAssignees(moment, assignees)) { // checks if commented between 3 and 7 days
console.log('between 7 and 14 commented');
return {result: false, labels: statusUpdatedLabel}
}
else if (moment.event == 'assigned' && assignees == moment.assignee)
{
assignedWithinFourteenDays = true;
}
else if (index === timeline.length-1 && (Date.parse(timeline[0].created_at) < fourteenDayCutoffTime.valueOf())) { // returns true if issue was created before 14 days after comparing the two dates in millisecond format
return {result: true, labels: inactiveLabel}
}
else if (index === timeline.length-1) { // returns true if the latest event created is between 7 and 14 days
return {result: true, labels: toUpdateLabel}
}
}
else { // all the events of an issue older than fourteen days will be processed here
if (moment.event == 'cross-referenced' && isLinkedIssue(moment, issueNum) && assignees == moment.actor.login) { // checks if cross referenced older than fourteen days
console.log('14 day event cross referenced');
return {result: false, labels: statusUpdatedLabel}
}
else if (index === timeline.length-1) { // returns true if the latest event created is older than 14 days
return {result: true, labels: inactiveLabel}
}
}
}
if (assignedWithinFourteenDays)
return {result: true, labels: toUpdateLabel}
}
function isTimelineOutdated(timeline, issueNum, assignees) { // assignees is an arrays of `login`'s
let lastAssignedTimestamp = null;
let lastCommentTimestamp = null;

for (let i = timeline.length - 1; i >= 0; i--) {
let eventObj = timeline[i];
let eventType = eventObj.event;

// if cross-referenced and fixed/resolved/closed by assignee, remove all update-related labels, remove all three labels
if (eventType === 'cross-referenced' && isLinkedIssue(eventObj, issueNum) && assignees.includes(eventObj.actor.login)) { // isLinkedIssue checks if the 'body'(comment) of the event mentioned closing/fixing/resolving this current issue
console.log(`Issue #${issueNum} fixed/resolved/closed by assignee, remove all update-related labels`);
return { result: false, labels: '' } // remove all three labels
}

let eventTimestamp = eventObj.updated_at || eventObj.created_at;

// update the lastCommentTimestamp if this is the last (most recent) comment by an assignee
if (!lastCommentTimestamp && eventType === 'commented' && isCommentByAssignees(eventObj, assignees)) {
lastCommentTimestamp = eventTimestamp;
}

// update the lastAssignedTimestamp if this is the last (most recent) time an assignee was assigned to the issue
else if (!lastAssignedTimestamp && eventType === 'assigned' && assignees.includes(eventObj.assignee.login)) {
lastAssignedTimestamp = eventTimestamp;
}
}

if (lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, threeDayCutoffTime)) { // if commented by assignee within 3 days
console.log(`Issue #${issueNum} commented by assignee within 3 days, retain 'Status: Updated' label`);
return { result: false, labels: statusUpdatedLabel } // retain (don't add) updated label, remove the other two
}

if (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, threeDayCutoffTime)) { // if an assignee was assigned within 3 days
console.log(`Issue #${issueNum} assigned to assignee within 3 days, no update-related labels should be used`);
return { result: false, labels: '' } // remove all three labels
}

if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, sevenDayCutoffTime)) || (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, sevenDayCutoffTime))) { // if updated within 7 days
if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, sevenDayCutoffTime))) {
console.log(`Issue #${issueNum} commented by assignee between 3 and 7 days, no update-related labels should be used; timestamp: ${lastCommentTimestamp}`)
} else if (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, sevenDayCutoffTime)) {
console.log(`Issue #${issueNum} assigned between 3 and 7 days, no update-related labels should be used; timestamp: ${lastAssignedTimestamp}`)
}
return { result: false, labels: '' } // remove all three labels
}

if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, fourteenDayCutoffTime)) || (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, fourteenDayCutoffTime))) { // if last comment was between 7-14 days, or no comment but an assginee was assigned during this period, issue is outdated and add 'To Update !' label
if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, fourteenDayCutoffTime))) {
console.log(`Issue #${issueNum} commented by assignee between 7 and 14 days, use 'To Update !' label; timestamp: ${lastCommentTimestamp}`)
} else if (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, fourteenDayCutoffTime)) {
console.log(`Issue #${issueNum} assigned between 7 and 14 days, use 'To Update !' label; timestamp: ${lastAssignedTimestamp}`)
}
return { result: true, labels: toUpdateLabel } // outdated, add 'To Update!' label
}

// if no comment or assigning found within 14 days, issue is outdated and add '2 weeks inactive' label
console.log(`Issue #${issueNum} has no update within 14 days, use '2 weeks inactive' label`)
return { result: true, labels: inactiveLabel }
}

/**
* Removes labels from a specified issue
Expand All @@ -229,7 +214,7 @@ async function removeLabels(issueNum, ...labels) {
name: label,
});
console.log(`Removed "${label}" from issue #${issueNum}`);
} catch (err) {
} catch (err) {
console.error(`Function failed to remove labels. Please refer to the error below: \n `, err);
}
}
Expand All @@ -240,7 +225,7 @@ async function removeLabels(issueNum, ...labels) {
* @param {Array} labels an array containing the labels to add (captures the rest of the parameters)
*/
async function addLabels(issueNum, ...labels) {
try {
try {
// https://octokit.github.io/rest.js/v18#issues-add-labels
await github.issues.addLabels({
owner: context.repo.owner,
Expand All @@ -250,7 +235,7 @@ async function addLabels(issueNum, ...labels) {
});
console.log(`Added these labels to issue #${issueNum}: ${labels}`);
// If an error is found, the rest of the script does not stop.
} catch (err){
} catch (err) {
console.error(`Function failed to add labels. Please refer to the error below: \n `, err);
}
}
Expand Down Expand Up @@ -301,15 +286,15 @@ async function getAssignees(issueNum) {
} catch (err) {
console.error(`Function failed to get assignees. Please refer to the error below: \n `, err);
return null
}
}
}
function filterForAssigneesLogins(data) {
logins = [];
for (let item of data) {
logins.push(item.login);
}
return logins
}
}
function createAssigneeString(assignees) {
const assigneeString = [];
for (let assignee of assignees) {
Expand All @@ -330,5 +315,5 @@ function formatComment(assignees, labelString) {
let completedInstuctions = text.replace('${assignees}', assignees).replace('${cutoffTime}', cutoffTimeString).replace('${label}', labelString);
return completedInstuctions
}

module.exports = main