Skip to content

Commit

Permalink
Merge pull request #6376 from payara/ramya-automate
Browse files Browse the repository at this point in the history
Github action to automate additional Community Supporting Processes
  • Loading branch information
fturizo authored Sep 21, 2023
2 parents 4a9e15a + 81310f9 commit 4ce3279
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 0 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/monitor-inactive-issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Monitor Inactive Open Issues
#Runs every Monday and Thursday at 9:00 A.M
on:
schedule:
- cron: "0 9 * * 1,4"
env:
inactiveIntervalDays: ${{ vars.MONITORING_INACTIVE_INTERVAL_DAYS }}
jobs:
retrieve-inactive-issues:
runs-on: ubuntu-latest
permissions:
issues: write
outputs:
issues: ${{ steps.filter-inactive-issues.outputs.result }}
steps:
- name: Check environment
run: |
if [ -z $inactiveIntervalDays ]; then
echo "::error::'MONITORING_INACTIVE_INTERVAL_DAYS' environment variable is not set"
exit 1
fi
- uses: actions/checkout@v3
if: success()
- name: Filter inactive issues
id: filter-inactive-issues
uses: actions/github-script@v6
with:
script: |
const script = require('./.github/workflows/scripts/filterInactiveIssues.js');
return await script({github, context, core});
notify-inactive-issues:
runs-on: ubuntu-latest
needs: retrieve-inactive-issues
if: ${{ needs.retrieve-inactive-issues.outputs.issues }}
strategy:
matrix:
issues: ${{ fromJSON(needs.retrieve-inactive-issues.outputs.issues) }}
steps:
- name: Notify MS Teams channel
id: notify-ms-teams
uses: simbo/msteams-message-card-action@latest
with:
webhook: ${{ secrets.COMMUNITY_EVENTS_WEBHOOK_URL }}
title: Inactive Issue Detected
message: |
It's been <i>${{ env.inactiveIntervalDays }} days</i> since issue number <code>${{ matrix.issues.number }}</code> has received an update. <strong>${{ matrix.issues.assignee }}</strong>, please provide an update soon.
buttons: |
View Issue on GitHub ${{ matrix.issues.url }}
58 changes: 58 additions & 0 deletions .github/workflows/monitor-issues-in-voting.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Monitor issues on voting status
#Runs the first day of each month at 10 A.M
on:
schedule:
- cron: "0 10 1 * *"

jobs:
select-top-voted-issue:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/checkout@v3
- name: Select the most voted enhancement
id: select-top-voted-issue
uses: actions/github-script@v6
with:
script: |
const script = require('./.github/workflows/scripts/selectMostVotedIssue.js')
return await script({github, context, core})
- name: Notify MS Teams channel
id: notify-ms-teams
if: ${{ success() && steps.select-top-voted-issue.outputs.result }}
uses: simbo/msteams-message-card-action@latest
env:
issueTitle: ${{ fromJSON(steps.select-top-voted-issue.outputs.result).title }}
issueURL: ${{ fromJSON(steps.select-top-voted-issue.outputs.result).url }}
assignee: ${{ fromJSON(steps.select-top-voted-issue.outputs.result).assignee }}
with:
webhook: ${{ secrets.COMMUNITY_EVENTS_WEBHOOK_URL }}
title: An Enhancement Proposal Issue has been selected the top-voted issue!
message: <code>${{ env.issueTitle }}</code> assigned to <strong>${{ env.assignee }}</strong>
buttons: |
View Issue on GitHub ${{ env.issueURL }}
close-forgotten-voting-issues:
runs-on: ubuntu-latest
permissions:
issues: write
needs: select-top-voted-issue
env:
maximumVotingThreshold: ${{ vars.MAX_VOTING_THRESHOLD_DAYS }}
steps:
- name: Check environment
run: |
if [ -z $maximumVotingThreshold ]; then
echo "::error::'MAX_VOTING_THRESHOLD_DAYS' environment variable is not set"
exit 1
fi
- uses: actions/checkout@v3
if: success()
- name: Close "forgotten" enhancement requests
id: close-forgotten-enhancements
if: success()
uses: actions/github-script@v6
with:
script: |
const script = require('./.github/workflows/scripts/closeForgottenEnhancements.js')
script({github, context, core})
60 changes: 60 additions & 0 deletions .github/workflows/scripts/closeForgottenEnhancements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module.exports = async ({github, context, core}) => {
const {owner, repo} = context.repo;
// Query all GH issues for Voting

const votingLabel = "Status: Voting";
let response = await github.rest.issues.listForRepo({
owner,
repo,
labels: votingLabel,
state: 'open',
});
if (response.data.length === 0) {
core.debug('No issues marked for voting found. Exiting.');
return;
}
const votingThreshold = process.env.maximumVotingThreshold;
const parsedDays = parseFloat(votingThreshold);

let now = new Date().getTime();
for (let issue of response.data) {
core.debug(`Processing issue #${issue.number}`);
core.debug(`Issue was created ${issue.created_at}`);

let createdDate = new Date(issue.created_at).getTime();
let daysSinceCreated = (now - createdDate) / 1000 / 60 / 60 / 24;
let reactions = issue.reactions['+1'];

core.debug(`Issue +1 reactions count is ${reactions}`);

if (reactions < 2 && daysSinceCreated > parsedDays) {
core.debug(`Closing #${issue.number} because it hasn't received enough votes after ${parsedDays} days`);

const message = `Greetings,
This issue has been open for community voting for more than ${parsedDays} days and sadly it hasn't received enough votes to be considered for its implementation according to our community policies.
As there is not enough interest from the community we'll proceed to close this issue.`;

await github.rest.issues.createComment({
owner : owner,
repo : repo,
issue_number: issue.number,
body: message
});

await github.rest.issues.update({
owner: owner,
repo: repo,
issue_number: issue.number,
labels: [],
state: 'closed'
});

await github.rest.issues.lock({
owner : owner,
repo : repo,
issue_number : issue.number,
lock_reason : 'resolved'
});
}
}
}
43 changes: 43 additions & 0 deletions .github/workflows/scripts/filterInactiveIssues.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module.exports = async ({github, context, core}) => {
const { owner, repo } = context.repo;
const openLabel = "Status: Open";

const parsedDays = process.env.inactiveIntervalDays;
const thresholdInMillis = parsedDays * 24 * 60 * 60 * 1000;

// Query all GH issues that are open
const response = await github.rest.issues.listForRepo({
owner,
repo,
labels: openLabel,
state: "open",
});
core.debug(`Inactive interval days is set to ${parsedDays}`);

let inactiveIssues = [];
for(let issue of response.data){
//Get issue events, which are returned by creation date in descending order
const eventResponse = await github.rest.issues.listEvents({
owner,
repo,
issue_number : issue.number
});
//Filter which events correspond to the 'labeled' event in which the `Status: Open` label was added
let lastOpenEvent = eventResponse.data.filter((event) => event.event === 'labeled' && event.label.name === openLabel)[0];

//If the event date is beyond the threshold date, the issue is added to the result array
if((new Date().getTime() - new Date(lastOpenEvent.created_at).getTime()) > thresholdInMillis){
inactiveIssues.push({
number : issue.number,
title : issue.title,
url: issue.html_url,
assignee: issue.assignees.length ? issue.assignees[0].login : '???'
});
}
}

core.debug(`${inactiveIssues.length} issues detected to be inactive`);
if (inactiveIssues.length > 0) {
return inactiveIssues;
}
}
76 changes: 76 additions & 0 deletions .github/workflows/scripts/selectMostVotedIssue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
module.exports = async ({github, context, core}) => {
let { owner, repo } = context.repo;

const openLabel = "Status: Open";
const votingLabel = "Status: Voting";

// Query all GH issues for Voting
const response = await github.rest.issues.listForRepo({
owner,
repo,
labels: votingLabel,
state: 'open',
direction: 'desc',
});

//response has all the issues labeled with Voting.
if (response.data.length === 0) {
core.debug('No issues marked for voting found. Exiting.');
return;
}
//filter issues with at least 2 votes.
response.data = response.data.filter((issue) => issue.reactions['+1'] > 1)
if (response.data.length === 0) {
core.debug('No issues with more than 2 votes found. Exiting');
return;
}

let mostVotes = 0;
let selectedIssue = 0;
let oldestDate = null;

for (const issue of response.data) {
core.debug(`Processing issue #${issue.number}`);
core.debug(`Number of +1 reactions ${issue.reactions['+1']}`);
core.debug(`Issue was created ${issue.created_at}`);

let votes = issue.reactions['+1'];
let createdDate = new Date(issue.created_at).getTime();

if (oldestDate === null) {
oldestDate = createdDate;
selectedIssue = issue;
mostVotes = votes;
}
if ((votes >= mostVotes) && (createdDate < oldestDate)) {
mostVotes = votes;
selectedIssue = issue;
}
}
core.debug(`Highest votes is ${mostVotes}`);
core.debug(`Final issue selected for enhancement is #${selectedIssue.number} created on ${selectedIssue.created_at}`);

let message = `Greetings,
This enhancement request has been selected by the Payara Community as the most voted enhancement of this month and
thus will be escalated to our product development backlog.`;

await github.rest.issues.createComment({
owner : owner,
repo : repo,
issue_number: selectedIssue.number,
body: message
});
await github.rest.issues.update({
owner : owner,
repo : repo,
issue_number: selectedIssue.number,
labels : [openLabel]
});

return {
number : selectedIssue.number,
title : selectedIssue.title,
url: selectedIssue.html_url,
assignee: selectedIssue.assignees.length ? selectedIssue.assignees[0].login : null
};
}

0 comments on commit 4ce3279

Please sign in to comment.