Skip to content

chore: collect customer issues pending triage and send them to slack #2

chore: collect customer issues pending triage and send them to slack

chore: collect customer issues pending triage and send them to slack #2

name: Collect customer issues
on:
pull_request:
schedule:
- cron: "0 15 * * *"
workflow_dispatch:
jobs:
collect-issues-pending-triage:
name: Pending Triage
runs-on: ubuntu-latest
env:
DAYS: 30
steps:
- name: Retrieve and format issues
id: retrieve-issues
uses: actions/github-script@v7
with:
script: |
// List of labels to filter by
const requiredLabels = [
"triage",
];
// List of core developers to exclude
const coreDevelopers = [
"mikeldking",
"axiomofjoy",
"anticorrelator",
"cephalization",
"Parker-Stafford",
"Jgilhuly",
"RogerHYang",
];
// Access the DAYS environment variable
const days = parseInt(process.env.DAYS || '7', 10);
// Calculate the cutoff date
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - days);
// Fetch issues created since DAYS ago
const issues = await github.paginate(
github.rest.issues.listForRepo,
{
owner: context.repo.owner,
repo: context.repo.repo,
state: "open",
since: cutoffDate.toISOString(),
per_page: 100,
}
);
// Check if issue has any of the required labels
function hasRequiredLabel(issueLabels, requiredLabels) {
return issueLabels.some(label => requiredLabels.includes(label.name));
}
// Filter issues
const filteredIssues = issues.filter(issue =>
!coreDevelopers.includes(issue.user.login) &&
hasRequiredLabel(issue.labels, requiredLabels) &&
new Date(issue.created_at) > cutoffDate &&
!issue.pull_request
).sort((a, b) => b.number - a.number);
// Function to calculate "X days ago" from created_at date
function timeAgo(createdAt) {
const createdDate = new Date(createdAt);
const now = new Date();
const diffInMs = now - createdDate;
const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24));
if (diffInDays === 0) {
return "Today";
} else if (diffInDays === 1) {
return "Yesterday";
} else {
return `${diffInDays} days ago`;
}
}
// Format the issues as a Markdown message for Slack
if (filteredIssues.length === 0) {
core.setOutput("has_issues", "false");
} else {
core.setOutput("has_issues", "true");
let message = `*🛠️ Phoenix Customer Issues Opened in the Last ${days} Day(s) Pending Triage*\n\n`;
// Separate issues into two lists: those with the "bug" label and those without
const bugIssues = filteredIssues.filter(issue =>
issue.labels.some(label => label.name === 'bug')
);
const enhancementIssues = filteredIssues.filter(issue =>
!issue.labels.some(label => label.name === 'bug')
);
const issueGroups = [
[bugIssues, "*🐛 Bugs*\n"],
[enhancementIssues, "*💡 Enhancements*\n"]
];
issueGroups.forEach(([issues, header]) => {
if (issues.length > 0) {
message += `${header}`;
issues.forEach((issue, i) => {
bugIssues.forEach((issue, i) => {
message += `${i + 1}. *<${issue.html_url}|#${issue.number}>:* ${issue.title}`
message += ` (by ${issue.user.login}, ${timeAgo(issue.created_at)}, with ${issue.comments} comments`
if (issue.assignees.length > 0) {
message += `, assigned to ${issue.assignees.map(assignee => assignee.login).sort().join(' ')}`;
}
message += `)\n`;
});
}
});
core.setOutput("slack_message", message);
}
- name: Send message to Slack
uses: slackapi/slack-github-action@v1
if: steps.retrieve-issues.outputs.has_issues == 'true'
with:
payload: |
{
"type": "mrkdwn",
"text": ${{ toJSON(steps.retrieve-issues.outputs.slack_message) }}
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}