Skip to content

Commit 9724352

Browse files
authored
Merge pull request #955 from iitzIrFan/my-changes
My changes
2 parents 3c16f34 + db8a8b9 commit 9724352

File tree

1 file changed

+77
-140
lines changed

1 file changed

+77
-140
lines changed
Lines changed: 77 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Auto Label PR from Linked Issue
1+
name: Sync Issue Metadata to PR
22

33
on:
44
pull_request_target:
@@ -8,186 +8,123 @@ permissions:
88
pull-requests: write
99
issues: write
1010
contents: read
11+
repository-projects: write
1112

1213
jobs:
13-
label-pr:
14+
sync-pr-metadata:
1415
runs-on: ubuntu-latest
15-
16+
1617
steps:
17-
- name: Checkout code
18+
- name: Checkout
1819
uses: actions/checkout@v4
1920

20-
- name: Extract Issue Numbers from PR Body
21+
- name: Extract linked issue(s) from PR
2122
id: extract-issues
2223
uses: actions/github-script@v7
2324
with:
2425
github-token: ${{ secrets.GITHUB_TOKEN }}
25-
result-encoding: string
2626
script: |
27-
let prNumber, prBody, prTitle;
28-
29-
// Check if triggered by issue event
30-
if (context.eventName === 'issues') {
31-
const issueNumber = context.payload.issue.number;
32-
console.log(`Issue #${issueNumber} labels were updated`);
33-
34-
const { data: pullRequests } = await github.rest.pulls.list({
35-
owner: context.repo.owner,
36-
repo: context.repo.repo,
37-
state: 'open'
38-
});
39-
40-
const linkedPRs = [];
41-
for (const pr of pullRequests) {
42-
const prText = `${pr.title} ${pr.body || ''}`;
43-
const patterns = [
44-
new RegExp(`(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s+#${issueNumber}\\b`, 'i'),
45-
new RegExp(`#${issueNumber}\\b`)
46-
];
47-
if (patterns.some(p => p.test(prText))) {
48-
linkedPRs.push(pr.number);
49-
}
50-
}
51-
52-
if (linkedPRs.length === 0) {
53-
console.log('No linked PRs found for this issue');
54-
return JSON.stringify({ prs: [], issue: issueNumber });
27+
const prNumber = context.payload.pull_request.number;
28+
const prTitle = context.payload.pull_request.title || '';
29+
const prBody = context.payload.pull_request.body || '';
30+
31+
// Regex patterns for issue references
32+
const patterns = [
33+
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi,
34+
/#(\d+)/g
35+
];
36+
37+
const issueNumbers = new Set();
38+
const text = prTitle + ' ' + prBody;
39+
40+
for (const pattern of patterns) {
41+
for (const match of text.matchAll(pattern)) {
42+
issueNumbers.add(match[1]);
5543
}
56-
57-
console.log(`Found linked PRs: ${linkedPRs.join(', ')}`);
58-
return JSON.stringify({ prs: linkedPRs, issue: issueNumber });
59-
} else {
60-
prBody = context.payload.pull_request.body || '';
61-
prTitle = context.payload.pull_request.title || '';
62-
63-
const patterns = [
64-
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi,
65-
/#(\d+)/g
66-
];
67-
68-
const issueNumbers = new Set();
69-
const textToSearch = prBody + ' ' + prTitle;
70-
71-
patterns.forEach(pattern => {
72-
const matches = [...textToSearch.matchAll(pattern)];
73-
matches.forEach(match => issueNumbers.add(match[1]));
74-
});
75-
76-
const issues = Array.from(issueNumbers);
77-
console.log('Found linked issues:', issues);
78-
79-
return JSON.stringify({
80-
prs: [context.payload.pull_request.number],
81-
issues: issues
82-
});
8344
}
8445
85-
- name: Get Labels from Linked Issues
86-
id: get-labels
46+
return JSON.stringify({ issues: Array.from(issueNumbers), pr: prNumber });
47+
48+
- name: Sync Issue Metadata to PR
8749
uses: actions/github-script@v7
8850
with:
8951
github-token: ${{ secrets.GITHUB_TOKEN }}
90-
result-encoding: string
9152
script: |
92-
const extractData = JSON.parse('${{ steps.extract-issues.outputs.result }}');
93-
94-
let issueNumbers = [];
95-
let prsToUpdate = [];
96-
97-
if (extractData.issue) {
98-
issueNumbers = [extractData.issue];
99-
prsToUpdate = extractData.prs || [];
100-
} else {
101-
issueNumbers = extractData.issues || [];
102-
prsToUpdate = extractData.prs || [];
103-
}
104-
105-
if (!issueNumbers || issueNumbers.length === 0) {
106-
console.log('No linked issues found');
107-
return JSON.stringify({ labels: [], prs: prsToUpdate });
53+
const data = JSON.parse('${{ steps.extract-issues.outputs.result }}');
54+
const prNumber = data.pr;
55+
const issueNumbers = data.issues || [];
56+
57+
if (issueNumbers.length === 0) {
58+
console.log("No linked issues found");
59+
return;
10860
}
109-
110-
const allLabels = new Set();
111-
61+
11262
for (const issueNumber of issueNumbers) {
11363
try {
114-
const issue = await github.rest.issues.get({
64+
// Fetch issue
65+
const { data: issue } = await github.rest.issues.get({
11566
owner: context.repo.owner,
11667
repo: context.repo.repo,
11768
issue_number: parseInt(issueNumber)
11869
});
119-
120-
console.log(`Issue #${issueNumber} labels:`, issue.data.labels.map(l => l.name));
121-
issue.data.labels.forEach(label => allLabels.add(label.name));
122-
} catch (error) {
123-
console.log(`Could not fetch issue #${issueNumber}:`, error.message);
124-
}
125-
}
126-
127-
const labels = Array.from(allLabels);
128-
console.log('All labels to apply:', labels);
129-
130-
return JSON.stringify({ labels: labels, prs: prsToUpdate });
13170
132-
- name: Apply Labels to PR
133-
uses: actions/github-script@v7
134-
with:
135-
github-token: ${{ secrets.GITHUB_TOKEN }}
136-
script: |
137-
const data = JSON.parse('${{ steps.get-labels.outputs.result }}');
138-
const labels = data.labels || [];
139-
const prsToUpdate = data.prs || [];
140-
141-
if (!labels || labels.length === 0) {
142-
console.log('No labels to apply');
143-
return;
144-
}
145-
146-
if (!prsToUpdate || prsToUpdate.length === 0) {
147-
console.log('No PRs to update');
148-
return;
149-
}
150-
151-
for (const prNumber of prsToUpdate) {
152-
try {
71+
console.log(`Syncing metadata from Issue #${issueNumber} to PR #${prNumber}`);
72+
73+
// --- Sync Labels ---
74+
const issueLabels = issue.labels.map(l => l.name);
15375
const { data: pr } = await github.rest.pulls.get({
15476
owner: context.repo.owner,
15577
repo: context.repo.repo,
15678
pull_number: prNumber
15779
});
158-
159-
const currentLabels = pr.labels.map(l => l.name);
160-
if (currentLabels.length > 0) {
161-
for (const label of currentLabels) {
162-
try {
163-
await github.rest.issues.removeLabel({
164-
owner: context.repo.owner,
165-
repo: context.repo.repo,
166-
issue_number: prNumber,
167-
name: label
168-
});
169-
} catch (e) {
170-
console.log(`Could not remove label ${label}: ${e.message}`);
171-
}
172-
}
173-
}
174-
80+
const currentPRLabels = pr.labels.map(l => l.name);
81+
const combinedLabels = Array.from(new Set([...currentPRLabels, ...issueLabels]));
82+
17583
await github.rest.issues.addLabels({
17684
owner: context.repo.owner,
17785
repo: context.repo.repo,
17886
issue_number: prNumber,
179-
labels: labels
87+
labels: combinedLabels
18088
});
181-
182-
console.log(`✅ Successfully applied ${labels.length} labels to PR #${prNumber}`);
183-
89+
console.log(`Labels applied: ${combinedLabels.join(', ')}`);
90+
91+
// --- Sync Milestone ---
92+
if (issue.milestone) {
93+
await github.rest.issues.update({
94+
owner: context.repo.owner,
95+
repo: context.repo.repo,
96+
issue_number: prNumber,
97+
milestone: issue.milestone.number
98+
});
99+
console.log(`Milestone synced: ${issue.milestone.title}`);
100+
}
101+
102+
// --- Sync Projects (GitHub Projects v2) ---
103+
if(issue.project_cards_url) {
104+
// Fetch project cards of issue
105+
const cardsResponse = await github.rest.projects.listCards({
106+
column_id: issue.project_cards_url.split('/').pop() // last part is column_id
107+
}).catch(()=>({data:[]}));
108+
109+
for(const card of cardsResponse.data || []) {
110+
await github.rest.projects.createCard({
111+
column_id: card.column_id,
112+
content_id: prNumber,
113+
content_type: 'PullRequest'
114+
});
115+
console.log(`Added PR #${prNumber} to project card in column ${card.column_id}`);
116+
}
117+
}
118+
119+
// --- Optionally: Add a comment on PR ---
184120
await github.rest.issues.createComment({
185121
owner: context.repo.owner,
186122
repo: context.repo.repo,
187123
issue_number: prNumber,
188-
body: `🏷️ Labels automatically synced from linked issue(s): ${labels.map(l => `\`${l}\``).join(', ')}`
124+
body: `✅ Synchronized metadata from Issue #${issueNumber}:\nLabels: ${issueLabels.join(', ')}\nMilestone: ${issue.milestone ? issue.milestone.title : 'None'}`
189125
});
126+
190127
} catch (error) {
191-
console.error(`Error updating PR #${prNumber}:`, error.message);
128+
console.error(`Error syncing issue #${issueNumber} to PR #${prNumber}:`, error.message);
192129
}
193130
}

0 commit comments

Comments
 (0)