Skip to content
63 changes: 29 additions & 34 deletions .github/workflows/autolabel-pr-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ jobs:
runs-on: ubuntu-latest

steps:
# Step 1: Checkout repository
- name: Checkout
uses: actions/checkout@v4

# Step 2: Extract linked issues from PR
- name: Extract linked issue(s) from PR
id: extract-issues
uses: actions/github-script@v7
Expand All @@ -28,7 +30,6 @@ jobs:
const prTitle = context.payload.pull_request.title || '';
const prBody = context.payload.pull_request.body || '';

// Regex patterns for issue references
const patterns = [
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi,
/#(\d+)/g
Expand All @@ -43,25 +44,34 @@ jobs:
}
}

return JSON.stringify({ issues: Array.from(issueNumbers), pr: prNumber });
core.setOutput('issues', JSON.stringify(Array.from(issueNumbers)));
core.setOutput('pr', prNumber.toString());

# Step 3: Sync issue metadata to PR
- name: Sync Issue Metadata to PR
if: steps.extract-issues.outputs.issues != '' && steps.extract-issues.outputs.issues != '[]'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const data = JSON.parse('${{ steps.extract-issues.outputs.result }}');
const prNumber = data.pr;
const issueNumbers = data.issues || [];
const issuesOutput = '${{ steps.extract-issues.outputs.issues }}';
const prNumber = parseInt('${{ steps.extract-issues.outputs.pr }}');

let issues = [];
try {
issues = JSON.parse(issuesOutput);
} catch (e) {
console.error("Failed to parse issues:", issuesOutput);
}

if (issueNumbers.length === 0) {
if (!issues || issues.length === 0) {
console.log("No linked issues found");
return;
}

for (const issueNumber of issueNumbers) {
for (const issueNumber of issues) {
try {
// Fetch issue
// Fetch issue details
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
Expand All @@ -80,13 +90,15 @@ jobs:
const currentPRLabels = pr.labels.map(l => l.name);
const combinedLabels = Array.from(new Set([...currentPRLabels, ...issueLabels]));

await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: combinedLabels
});
console.log(`Labels applied: ${combinedLabels.join(', ')}`);
if (combinedLabels.length > 0) {
await github.rest.issues.setLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: combinedLabels
});
console.log(`Labels applied: ${combinedLabels.join(', ')}`);
}

// --- Sync Milestone ---
if (issue.milestone) {
Expand All @@ -99,29 +111,12 @@ jobs:
console.log(`Milestone synced: ${issue.milestone.title}`);
}

// --- Sync Projects (GitHub Projects v2) ---
if(issue.project_cards_url) {
// Fetch project cards of issue
const cardsResponse = await github.rest.projects.listCards({
column_id: issue.project_cards_url.split('/').pop() // last part is column_id
}).catch(()=>({data:[]}));

for(const card of cardsResponse.data || []) {
await github.rest.projects.createCard({
column_id: card.column_id,
content_id: prNumber,
content_type: 'PullRequest'
});
console.log(`Added PR #${prNumber} to project card in column ${card.column_id}`);
}
}

// --- Optionally: Add a comment on PR ---
// --- Optionally add comment on PR ---
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `✅ Synchronized metadata from Issue #${issueNumber}:\nLabels: ${issueLabels.join(', ')}\nMilestone: ${issue.milestone ? issue.milestone.title : 'None'}`
body: `✅ Synchronized metadata from Issue #${issueNumber}:\n- Labels: ${issueLabels.length > 0 ? issueLabels.join(', ') : 'None'}\n- Milestone: ${issue.milestone ? issue.milestone.title : 'None'}`
});

} catch (error) {
Expand Down
Loading