From 51acfafc0d8070904d84465854548ca3f3aceee3 Mon Sep 17 00:00:00 2001 From: sheikhlimon Date: Mon, 20 Oct 2025 23:07:40 +0600 Subject: [PATCH 1/6] test pr sync --- .github/workflows/autolabel-pr-issue.yml | 38 ++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/.github/workflows/autolabel-pr-issue.yml b/.github/workflows/autolabel-pr-issue.yml index 2effb31f..c0f7a302 100644 --- a/.github/workflows/autolabel-pr-issue.yml +++ b/.github/workflows/autolabel-pr-issue.yml @@ -18,6 +18,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 + # Extract linked issue(s) - name: Extract linked issue(s) from PR id: extract-issues uses: actions/github-script@v7 @@ -43,19 +44,33 @@ jobs: } } - return JSON.stringify({ issues: Array.from(issueNumbers), pr: prNumber }); + // Return valid JSON + return { issues: Array.from(issueNumbers), pr: prNumber }; + # Sync metadata safely - name: Sync Issue Metadata to PR uses: actions/github-script@v7 + env: + RESULT_JSON: ${{ steps.extract-issues.outputs.result }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const data = JSON.parse('${{ steps.extract-issues.outputs.result }}'); + const core = require('@actions/core'); + + // Safely parse the previous step’s JSON + let data; + try { + data = JSON.parse(process.env.RESULT_JSON); + } catch (err) { + core.setFailed(`Invalid JSON from extract-issues: ${err.message}`); + return; + } + const prNumber = data.pr; const issueNumbers = data.issues || []; - if (issueNumbers.length === 0) { - console.log("No linked issues found"); + if (!issueNumbers.length) { + console.log("No linked issues found."); return; } @@ -99,14 +114,13 @@ jobs: console.log(`Milestone synced: ${issue.milestone.title}`); } - // --- Sync Projects (GitHub Projects v2) --- - if(issue.project_cards_url) { - // Fetch project cards of issue + // --- Sync Projects (optional, GitHub Projects v2 is different API) --- + if (issue.project_cards_url) { 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 || []) { + column_id: issue.project_cards_url.split('/').pop() + }).catch(() => ({ data: [] })); + + for (const card of cardsResponse.data || []) { await github.rest.projects.createCard({ column_id: card.column_id, content_id: prNumber, @@ -116,7 +130,7 @@ jobs: } } - // --- Optionally: Add a comment on PR --- + // --- Optional: Add a comment on PR --- await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, From 9d1a79b7bdca471ede9f53e6e12b27e790c62f97 Mon Sep 17 00:00:00 2001 From: sheikhlimon Date: Mon, 20 Oct 2025 23:28:54 +0600 Subject: [PATCH 2/6] non-whitespace character --- .github/workflows/autolabel-pr-issue.yml | 37 +++++++----------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/.github/workflows/autolabel-pr-issue.yml b/.github/workflows/autolabel-pr-issue.yml index c0f7a302..04391673 100644 --- a/.github/workflows/autolabel-pr-issue.yml +++ b/.github/workflows/autolabel-pr-issue.yml @@ -18,18 +18,19 @@ jobs: - name: Checkout uses: actions/checkout@v4 - # Extract linked issue(s) - - name: Extract linked issue(s) from PR + # Step 1: Extract linked issue(s) from PR + - name: Extract linked issue(s) id: extract-issues uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | + const core = require('@actions/core'); + const prNumber = context.payload.pull_request.number; 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 @@ -44,10 +45,10 @@ jobs: } } - // Return valid JSON - return { issues: Array.from(issueNumbers), pr: prNumber }; + // ✅ Set output safely as JSON string + core.setOutput('result', JSON.stringify({ issues: Array.from(issueNumbers), pr: prNumber })); - # Sync metadata safely + # Step 2: Sync metadata to PR - name: Sync Issue Metadata to PR uses: actions/github-script@v7 env: @@ -57,12 +58,13 @@ jobs: script: | const core = require('@actions/core'); - // Safely parse the previous step’s JSON + // Safely parse JSON let data; try { data = JSON.parse(process.env.RESULT_JSON); + if (typeof data === 'string') data = JSON.parse(data); } catch (err) { - core.setFailed(`Invalid JSON from extract-issues: ${err.message}`); + core.setFailed(`Failed to parse JSON: ${err.message}\nRaw: ${process.env.RESULT_JSON}`); return; } @@ -70,13 +72,12 @@ jobs: const issueNumbers = data.issues || []; if (!issueNumbers.length) { - console.log("No linked issues found."); + console.log("No linked issues found"); return; } for (const issueNumber of issueNumbers) { try { - // Fetch issue const { data: issue } = await github.rest.issues.get({ owner: context.repo.owner, repo: context.repo.repo, @@ -114,22 +115,6 @@ jobs: console.log(`Milestone synced: ${issue.milestone.title}`); } - // --- Sync Projects (optional, GitHub Projects v2 is different API) --- - if (issue.project_cards_url) { - const cardsResponse = await github.rest.projects.listCards({ - column_id: issue.project_cards_url.split('/').pop() - }).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}`); - } - } - // --- Optional: Add a comment on PR --- await github.rest.issues.createComment({ owner: context.repo.owner, From 456fe4df6ce76965cc4f2618dc2ebf7e03264c9f Mon Sep 17 00:00:00 2001 From: sheikhlimon Date: Mon, 20 Oct 2025 23:31:41 +0600 Subject: [PATCH 3/6] test v3 --- .github/workflows/autolabel-pr-issue.yml | 87 ++++++++++++------------ 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/.github/workflows/autolabel-pr-issue.yml b/.github/workflows/autolabel-pr-issue.yml index 04391673..a5f9ae70 100644 --- a/.github/workflows/autolabel-pr-issue.yml +++ b/.github/workflows/autolabel-pr-issue.yml @@ -18,7 +18,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - # Step 1: Extract linked issue(s) from PR + # Step 1: Extract linked issues - name: Extract linked issue(s) id: extract-issues uses: actions/github-script@v7 @@ -45,10 +45,9 @@ jobs: } } - // ✅ Set output safely as JSON string core.setOutput('result', JSON.stringify({ issues: Array.from(issueNumbers), pr: prNumber })); - # Step 2: Sync metadata to PR + # Step 2: Sync metadata - name: Sync Issue Metadata to PR uses: actions/github-script@v7 env: @@ -58,7 +57,7 @@ jobs: script: | const core = require('@actions/core'); - // Safely parse JSON + // Parse JSON safely let data; try { data = JSON.parse(process.env.RESULT_JSON); @@ -72,58 +71,60 @@ jobs: const issueNumbers = data.issues || []; if (!issueNumbers.length) { - console.log("No linked issues found"); + console.log("No linked issues found."); return; } for (const issueNumber of issueNumbers) { + let issue; try { - const { data: issue } = await github.rest.issues.get({ + const res = await github.rest.issues.get({ owner: context.repo.owner, repo: context.repo.repo, issue_number: parseInt(issueNumber) }); + issue = res.data; + } catch (err) { + console.warn(`Cannot access Issue #${issueNumber}, skipping sync.`); + continue; // skip to next issue + } - console.log(`Syncing metadata from Issue #${issueNumber} to PR #${prNumber}`); - - // --- Sync Labels --- - const issueLabels = issue.labels.map(l => l.name); - const { data: pr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: prNumber - }); - const currentPRLabels = pr.labels.map(l => l.name); - const combinedLabels = Array.from(new Set([...currentPRLabels, ...issueLabels])); - - await github.rest.issues.addLabels({ + console.log(`Syncing metadata from Issue #${issueNumber} to PR #${prNumber}`); + + // --- Sync Labels --- + const issueLabels = issue.labels.map(l => l.name); + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber + }); + 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(', ')}`); + + // --- Sync Milestone --- + if (issue.milestone) { + await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, - labels: combinedLabels + milestone: issue.milestone.number }); - console.log(`Labels applied: ${combinedLabels.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}`); - } - - // --- Optional: Add a 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'}` - }); - - } catch (error) { - console.error(`Error syncing issue #${issueNumber} to PR #${prNumber}:`, error.message); + console.log(`Milestone synced: ${issue.milestone.title}`); } + + // --- Add a 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'}` + }); } From 978e101728b64394e3bba14aa291800d5dcd786b Mon Sep 17 00:00:00 2001 From: sheikhlimon Date: Tue, 21 Oct 2025 00:00:05 +0600 Subject: [PATCH 4/6] update sync workflow --- .github/workflows/autolabel-pr-issue.yml | 114 ++++++++++------------- 1 file changed, 51 insertions(+), 63 deletions(-) diff --git a/.github/workflows/autolabel-pr-issue.yml b/.github/workflows/autolabel-pr-issue.yml index a5f9ae70..dc5e3c12 100644 --- a/.github/workflows/autolabel-pr-issue.yml +++ b/.github/workflows/autolabel-pr-issue.yml @@ -18,8 +18,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - # Step 1: Extract linked issues - - name: Extract linked issue(s) + - name: Extract linked issue(s) from PR id: extract-issues uses: actions/github-script@v7 with: @@ -31,6 +30,7 @@ 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 @@ -45,86 +45,74 @@ jobs: } } - core.setOutput('result', JSON.stringify({ issues: Array.from(issueNumbers), pr: prNumber })); + // Use core.setOutput instead of return + core.setOutput('issues', JSON.stringify(Array.from(issueNumbers))); + core.setOutput('pr', prNumber.toString()); - # Step 2: Sync metadata - name: Sync Issue Metadata to PR + if: steps.extract-issues.outputs.issues != '[]' uses: actions/github-script@v7 - env: - RESULT_JSON: ${{ steps.extract-issues.outputs.result }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const core = require('@actions/core'); + const issueNumbers = JSON.parse('${{ steps.extract-issues.outputs.issues }}'); + const prNumber = parseInt('${{ steps.extract-issues.outputs.pr }}'); - // Parse JSON safely - let data; - try { - data = JSON.parse(process.env.RESULT_JSON); - if (typeof data === 'string') data = JSON.parse(data); - } catch (err) { - core.setFailed(`Failed to parse JSON: ${err.message}\nRaw: ${process.env.RESULT_JSON}`); - return; - } - - const prNumber = data.pr; - const issueNumbers = data.issues || []; - - if (!issueNumbers.length) { - console.log("No linked issues found."); + if (issueNumbers.length === 0) { + console.log("No linked issues found"); return; } for (const issueNumber of issueNumbers) { - let issue; try { - const res = await github.rest.issues.get({ + // Fetch issue + const { data: issue } = await github.rest.issues.get({ owner: context.repo.owner, repo: context.repo.repo, issue_number: parseInt(issueNumber) }); - issue = res.data; - } catch (err) { - console.warn(`Cannot access Issue #${issueNumber}, skipping sync.`); - continue; // skip to next issue - } - - console.log(`Syncing metadata from Issue #${issueNumber} to PR #${prNumber}`); - - // --- Sync Labels --- - const issueLabels = issue.labels.map(l => l.name); - const { data: pr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: prNumber - }); - 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(', ')}`); - - // --- Sync Milestone --- - if (issue.milestone) { - await github.rest.issues.update({ + + console.log(`Syncing metadata from Issue #${issueNumber} to PR #${prNumber}`); + + // --- Sync Labels --- + const issueLabels = issue.labels.map(l => l.name); + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber + }); + const currentPRLabels = pr.labels.map(l => l.name); + const combinedLabels = Array.from(new Set([...currentPRLabels, ...issueLabels])); + + 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) { + 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 a comment on PR --- + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, - milestone: issue.milestone.number + body: `✅ Synchronized metadata from Issue #${issueNumber}:\n- Labels: ${issueLabels.length > 0 ? issueLabels.join(', ') : 'None'}\n- Milestone: ${issue.milestone ? issue.milestone.title : 'None'}` }); - console.log(`Milestone synced: ${issue.milestone.title}`); + } catch (error) { + console.error(`Error syncing issue #${issueNumber} to PR #${prNumber}:`, error.message); } - - // --- Add a 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'}` - }); } From c38b841b73d9dec2c2206f11cc384e9c0706d280 Mon Sep 17 00:00:00 2001 From: sheikhlimon Date: Tue, 21 Oct 2025 00:03:24 +0600 Subject: [PATCH 5/6] test for pull request --- .github/workflows/autolabel-pr-issue.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/autolabel-pr-issue.yml b/.github/workflows/autolabel-pr-issue.yml index dc5e3c12..d718d6e0 100644 --- a/.github/workflows/autolabel-pr-issue.yml +++ b/.github/workflows/autolabel-pr-issue.yml @@ -1,7 +1,7 @@ name: Sync Issue Metadata to PR on: - pull_request_target: + pull_request: # Changed from pull_request_target for testing types: [opened, edited, synchronize, reopened] permissions: @@ -25,26 +25,26 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const core = require('@actions/core'); - + const prNumber = context.payload.pull_request.number; 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 ]; - + const issueNumbers = new Set(); const text = prTitle + ' ' + prBody; - + for (const pattern of patterns) { for (const match of text.matchAll(pattern)) { issueNumbers.add(match[1]); } } - + // Use core.setOutput instead of return core.setOutput('issues', JSON.stringify(Array.from(issueNumbers))); core.setOutput('pr', prNumber.toString()); @@ -57,12 +57,12 @@ jobs: script: | const issueNumbers = JSON.parse('${{ steps.extract-issues.outputs.issues }}'); const prNumber = parseInt('${{ steps.extract-issues.outputs.pr }}'); - + if (issueNumbers.length === 0) { console.log("No linked issues found"); return; } - + for (const issueNumber of issueNumbers) { try { // Fetch issue From 5160334277e3644ecd8a5db2385fdcd8b8ceaec6 Mon Sep 17 00:00:00 2001 From: sheikhlimon Date: Tue, 21 Oct 2025 00:05:15 +0600 Subject: [PATCH 6/6] core available globally --- .github/workflows/autolabel-pr-issue.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/autolabel-pr-issue.yml b/.github/workflows/autolabel-pr-issue.yml index d718d6e0..5205bd22 100644 --- a/.github/workflows/autolabel-pr-issue.yml +++ b/.github/workflows/autolabel-pr-issue.yml @@ -24,8 +24,6 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const core = require('@actions/core'); - const prNumber = context.payload.pull_request.number; const prTitle = context.payload.pull_request.title || ''; const prBody = context.payload.pull_request.body || '';