Skip to content

sql-having-vs-group-by #224

sql-having-vs-group-by

sql-having-vs-group-by #224

name: Sync Issue Metadata to PR
on:
pull_request_target:
types: [opened, edited, synchronize, reopened]
permissions:
pull-requests: write
issues: write
contents: read
repository-projects: write
jobs:
sync-pr-metadata:
if: |
github.event.action != 'edited' ||
(
github.event.changes.body &&
(github.event.changes.body.from || '') != (github.event.pull_request.body || '')
)
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
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number;
const prTitle = context.payload.pull_request.title || '';
const prBody = context.payload.pull_request.body || '';
// Regex patterns to find linked issues
const patterns = [
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi,
/#(\d+)/g
];
const issueNumbers = new Set();
const text = prTitle + ' ' + prBody;
for (const pattern of patterns) {
for (const match of text.matchAll(pattern)) {
issueNumbers.add(match[1]);
}
}
core.setOutput('issues', JSON.stringify(Array.from(issueNumbers)));
core.setOutput('pr', prNumber.toString());
# Step 3: Sync issue metadata to PR safely
- name: Sync Issue Metadata to PR
if: steps.extract-issues.outputs.issues != '' && steps.extract-issues.outputs.issues != '[]'
uses: actions/github-script@v7
env:
ISSUES_JSON: ${{ steps.extract-issues.outputs.issues }}
PR_NUMBER: ${{ steps.extract-issues.outputs.pr }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// Read inputs from environment variables to avoid YAML quoting issues
const issuesOutput = process.env.ISSUES_JSON || '[]';
const prNumber = parseInt(process.env.PR_NUMBER, 10);
let issues = [];
try {
issues = JSON.parse(issuesOutput);
} catch (e) {
// Clean extra quotes/newlines
const cleaned = issuesOutput.replace(/^\s*['"]?/, '').replace(/['"]?\s*$/, '');
try {
issues = JSON.parse(cleaned);
} catch (err) {
console.error('Failed to parse issues output:', err.message);
console.error('Raw issues output:', JSON.stringify(issuesOutput));
return;
}
}
if (!Array.isArray(issues) || issues.length === 0) {
console.log('No linked issues found');
return;
}
for (const issueNumber of issues) {
try {
// Fetch issue details
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parseInt(issueNumber, 10)
});
console.log(`Syncing metadata from Issue #${issueNumber} to PR #${prNumber}`);
// --- Sync Labels safely using addLabels ---
const issueLabels = Array.isArray(issue.labels) ? issue.labels.map(l => l.name) : [];
if (issueLabels.length > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: issueLabels
});
console.log(`Labels added from issue: ${issueLabels.join(', ')}`);
}
// --- Sync Milestone ---
if (issue.milestone) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
milestone: issue.milestone.number
});
console.log(`Milestone synced: ${issue.milestone.title}`);
}
// --- 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}:\n- Labels: ${issueLabels.length > 0 ? issueLabels.join(', ') : 'None'}\n- Milestone: ${issue.milestone ? issue.milestone.title : 'None'}`
});
} catch (error) {
console.error(`Error syncing issue #${issueNumber} to PR #${prNumber}:`, error);
}
}