Skip to content

Commit 614f13c

Browse files
authored
ci: add linked PR feature to popular-issues action (#15355)
# Overview Adds linked PR detection to the popular-issues Slack notification, matching the existing feature in new-issues action. ## Key Changes - **Linked PR detection** - Fetches timeline events for each issue to find cross-referenced PRs - **Slack message enhancement** - Appends `:link: Linked PR` link when a PR references the issue ## Design Decisions Reused the same pattern from `new-issues.ts` for consistency: - `getLinkedPRUrl` queries the issues timeline API for `cross-referenced` events with PR sources - `Promise.all` fetches linked PRs concurrently for all 10 issues
1 parent e833fe6 commit 614f13c

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

.github/actions/activity/dist/popular-issues/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/actions/activity/src/popular-issues.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { SlimIssue } from './types'
88

99
const DAYS_WINDOW = 90
1010

11-
function generateText(issues: SlimIssue[]) {
11+
function generateText(issues: { issue: SlimIssue; linkedPRUrl?: string }[]) {
1212
let text = `*A list of the top 10 issues sorted by the most reactions over the last ${DAYS_WINDOW} days:*\n\n`
1313

1414
// Format date as "X days ago"
@@ -20,13 +20,33 @@ function generateText(issues: SlimIssue[]) {
2020
return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`
2121
}
2222

23-
issues.forEach((issue) => {
24-
text += `• ${issue?.reactions?.total_count || 0} 👍 ${issue.title} - <${issue.html_url}|#${issue.number}>, ${formattedDaysAgo(issue.created_at)}\n`
23+
issues.forEach(({ issue, linkedPRUrl }) => {
24+
text += `• ${issue?.reactions?.total_count || 0} 👍 ${issue.title} - <${issue.html_url}|#${issue.number}>, ${formattedDaysAgo(issue.created_at)}`
25+
if (linkedPRUrl) {
26+
text += ` - <${linkedPRUrl}|:link: Linked PR>`
27+
}
28+
text += `\n`
2529
})
2630

2731
return text.trim()
2832
}
2933

34+
async function getLinkedPRUrl(
35+
octoClient: ReturnType<typeof getOctokit>,
36+
issue: SlimIssue,
37+
): Promise<string | undefined> {
38+
const { data: events } = await octoClient.rest.issues.listEventsForTimeline({
39+
owner: 'payloadcms',
40+
repo: 'payload',
41+
issue_number: issue.number,
42+
})
43+
44+
const crossReferencedEvent = events.find(
45+
(event) => event.event === 'cross-referenced' && event.source?.issue?.pull_request,
46+
)
47+
return crossReferencedEvent?.source?.issue?.html_url
48+
}
49+
3050
export async function run() {
3151
try {
3252
if (!process.env.GITHUB_TOKEN) throw new TypeError('GITHUB_TOKEN not set')
@@ -47,7 +67,14 @@ export async function run() {
4767
return
4868
}
4969

50-
const messageText = generateText(data.items)
70+
const issuesWithLinkedPRs = await Promise.all(
71+
data.items.map(async (issue) => {
72+
const linkedPRUrl = await getLinkedPRUrl(octoClient, issue)
73+
return { issue, linkedPRUrl }
74+
}),
75+
)
76+
77+
const messageText = generateText(issuesWithLinkedPRs)
5178
console.log(messageText)
5279

5380
await slackClient.chat.postMessage({

0 commit comments

Comments
 (0)