Skip to content

Commit de1b4be

Browse files
committed
Added a fix
1 parent 8e358cb commit de1b4be

File tree

1 file changed

+165
-33
lines changed

1 file changed

+165
-33
lines changed
Lines changed: 165 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Auto Label PR from Linked Issue
22

33
on:
4-
pull_request_target:
4+
pull_request_target:
55
types: [opened, edited, synchronize, reopened]
66

77
permissions:
@@ -12,30 +12,81 @@ permissions:
1212
jobs:
1313
label-pr:
1414
runs-on: ubuntu-latest
15-
15+
1616
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
1720
- name: Extract Issue Numbers from PR Body
1821
id: extract-issues
1922
uses: actions/github-script@v7
2023
with:
2124
github-token: ${{ secrets.GITHUB_TOKEN }}
2225
result-encoding: string
2326
script: |
24-
const prBody = context.payload.pull_request.body || '';
25-
const prTitle = context.payload.pull_request.title || '';
26-
const patterns = [
27-
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi,
28-
/#(\d+)/g
29-
];
30-
const issueNumbers = new Set();
31-
const textToSearch = prBody + ' ' + prTitle;
32-
patterns.forEach(pattern => {
33-
const matches = [...textToSearch.matchAll(pattern)];
34-
matches.forEach(match => {
35-
if (/^\d+$/.test(match[1])) issueNumbers.add(match[1]);
27+
let prNumber, prBody, prTitle;
28+
29+
// Check if triggered by issue event
30+
if (context.eventName === 'issues') {
31+
// Find all open PRs that link to this issue
32+
const issueNumber = context.payload.issue.number;
33+
console.log(`Issue #${issueNumber} labels were updated`);
34+
35+
// Search for PRs that mention this issue
36+
const { data: pullRequests } = await github.rest.pulls.list({
37+
owner: context.repo.owner,
38+
repo: context.repo.repo,
39+
state: 'open'
40+
});
41+
42+
const linkedPRs = [];
43+
for (const pr of pullRequests) {
44+
const prText = `${pr.title} ${pr.body || ''}`;
45+
const patterns = [
46+
new RegExp(`(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s+#${issueNumber}\\b`, 'i'),
47+
new RegExp(`#${issueNumber}\\b`)
48+
];
49+
50+
if (patterns.some(p => p.test(prText))) {
51+
linkedPRs.push(pr.number);
52+
}
53+
}
54+
55+
if (linkedPRs.length === 0) {
56+
console.log('No linked PRs found for this issue');
57+
return JSON.stringify({ prs: [], issue: issueNumber });
58+
}
59+
60+
console.log(`Found linked PRs: ${linkedPRs.join(', ')}`);
61+
return JSON.stringify({ prs: linkedPRs, issue: issueNumber });
62+
} else {
63+
// Triggered by PR event - original logic
64+
prBody = context.payload.pull_request.body || '';
65+
prTitle = context.payload.pull_request.title || '';
66+
67+
const patterns = [
68+
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi,
69+
/#(\d+)/g
70+
];
71+
72+
const issueNumbers = new Set();
73+
const textToSearch = prBody + ' ' + prTitle;
74+
75+
patterns.forEach(pattern => {
76+
const matches = [...textToSearch.matchAll(pattern)];
77+
matches.forEach(match => {
78+
issueNumbers.add(match[1]);
79+
});
80+
});
81+
82+
const issues = Array.from(issueNumbers);
83+
console.log('Found linked issues:', issues);
84+
85+
return JSON.stringify({
86+
prs: [context.payload.pull_request.number],
87+
issues: issues
3688
});
37-
});
38-
return JSON.stringify([...issueNumbers]);
89+
}
3990
4091
- name: Get Labels from Linked Issues
4192
id: get-labels
@@ -44,43 +95,124 @@ jobs:
4495
github-token: ${{ secrets.GITHUB_TOKEN }}
4596
result-encoding: string
4697
script: |
47-
const issueNumbers = JSON.parse('${{ steps.extract-issues.outputs.result }}');
98+
const extractData = JSON.parse('${{ steps.extract-issues.outputs.result }}');
99+
100+
// Labels to exclude from being applied to PRs
48101
const excludedLabels = ['recode', 'hacktoberfest-accepted'];
102+
103+
let issueNumbers = [];
104+
let prsToUpdate = [];
105+
106+
// Handle both PR and issue events
107+
if (extractData.issue) {
108+
// Issue event - update all linked PRs
109+
issueNumbers = [extractData.issue];
110+
prsToUpdate = extractData.prs || [];
111+
} else {
112+
// PR event - update the current PR
113+
issueNumbers = extractData.issues || [];
114+
prsToUpdate = extractData.prs || [];
115+
}
116+
117+
if (!issueNumbers || issueNumbers.length === 0) {
118+
console.log('No linked issues found');
119+
return JSON.stringify({ labels: [], prs: prsToUpdate });
120+
}
121+
49122
const allLabels = new Set();
50-
123+
51124
for (const issueNumber of issueNumbers) {
52125
try {
53126
const issue = await github.rest.issues.get({
54127
owner: context.repo.owner,
55128
repo: context.repo.repo,
56129
issue_number: parseInt(issueNumber)
57130
});
58-
for (const label of issue.data.labels) {
59-
if (!excludedLabels.includes(label.name.toLowerCase()))
131+
132+
console.log(`Issue #${issueNumber} labels:`, issue.data.labels.map(l => l.name));
133+
134+
issue.data.labels.forEach(label => {
135+
// Only add label if it's not in the excluded list
136+
if (!excludedLabels.includes(label.name.toLowerCase())) {
60137
allLabels.add(label.name);
61-
}
138+
} else {
139+
console.log(`Excluding label: ${label.name}`);
140+
}
141+
});
62142
} catch (error) {
63143
console.log(`Could not fetch issue #${issueNumber}:`, error.message);
64144
}
65145
}
66-
67-
return JSON.stringify([...allLabels]);
146+
147+
const labels = Array.from(allLabels);
148+
console.log('All labels to apply:', labels);
149+
150+
return JSON.stringify({ labels: labels, prs: prsToUpdate });
68151
69152
- name: Apply Labels to PR
70153
uses: actions/github-script@v7
71154
with:
72155
github-token: ${{ secrets.GITHUB_TOKEN }}
73156
script: |
74-
const labels = JSON.parse('${{ steps.get-labels.outputs.result }}')
75-
.filter(l => typeof l === 'string' && l.trim() !== '');
76-
if (labels.length === 0) {
157+
const data = JSON.parse('${{ steps.get-labels.outputs.result }}');
158+
const labels = data.labels || [];
159+
const prsToUpdate = data.prs || [];
160+
161+
if (!labels || labels.length === 0) {
77162
console.log('No labels to apply');
78163
return;
79164
}
80-
await github.rest.issues.addLabels({
81-
owner: context.repo.owner,
82-
repo: context.repo.repo,
83-
issue_number: context.payload.pull_request.number,
84-
labels
85-
});
86-
console.log(`Applied labels: ${labels.join(', ')}`);
165+
166+
if (!prsToUpdate || prsToUpdate.length === 0) {
167+
console.log('No PRs to update');
168+
return;
169+
}
170+
171+
// Update each PR
172+
for (const prNumber of prsToUpdate) {
173+
try {
174+
// First, get current PR labels
175+
const { data: pr } = await github.rest.pulls.get({
176+
owner: context.repo.owner,
177+
repo: context.repo.repo,
178+
pull_number: prNumber
179+
});
180+
181+
// Remove all existing labels first (to handle removed issue labels)
182+
const currentLabels = pr.labels.map(l => l.name);
183+
if (currentLabels.length > 0) {
184+
for (const label of currentLabels) {
185+
try {
186+
await github.rest.issues.removeLabel({
187+
owner: context.repo.owner,
188+
repo: context.repo.repo,
189+
issue_number: prNumber,
190+
name: label
191+
});
192+
} catch (e) {
193+
console.log(`Could not remove label ${label}: ${e.message}`);
194+
}
195+
}
196+
}
197+
198+
// Apply new labels
199+
await github.rest.issues.addLabels({
200+
owner: context.repo.owner,
201+
repo: context.repo.repo,
202+
issue_number: prNumber,
203+
labels: labels
204+
});
205+
206+
console.log(`Successfully applied ${labels.length} labels to PR #${prNumber}`);
207+
208+
// Add a comment to the PR
209+
await github.rest.issues.createComment({
210+
owner: context.repo.owner,
211+
repo: context.repo.repo,
212+
issue_number: prNumber,
213+
body: `🏷️ Labels automatically synced from linked issue(s): ${labels.map(l => `\`${l}\``).join(', ')}`
214+
});
215+
} catch (error) {
216+
console.error(`Error updating PR #${prNumber}:`, error.message);
217+
}
218+
}

0 commit comments

Comments
 (0)