[pull] latest from ag-grid:latest #1287
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Expand JIRA Links in PR descriptions | |
| on: | |
| pull_request: | |
| types: [ opened, edited ] | |
| permissions: | |
| contents: read | |
| # Serialise runs per PR so overlapping edits can't race the duplicate-comment | |
| # check (check-then-act): later edits wait for the in-flight run to post its | |
| # sentinel comment, then see it and skip. Do not cancel in progress, or a | |
| # cancelled run might skip posting while its replacement also skips. | |
| concurrency: | |
| group: gh-comment-hook-${{ github.event.pull_request.number }} | |
| cancel-in-progress: false | |
| jobs: | |
| expand-jira-links: | |
| if: github.repository == 'ag-grid/ag-grid' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| issues: write | |
| steps: | |
| - name: Checkout repository | |
| if: github.event.action == 'opened' || github.event.action == 'edited' | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| sparse-checkout: | |
| 'scripts/ci/_utils.mjs' | |
| - name: Replace mention with jira link | |
| id: notify-start | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| continue-on-error: true | |
| env: | |
| PR_BODY: ${{ github.event.pull_request.body }} | |
| PR_ID: ${{ github.event.pull_request.number }} | |
| PR_URL: ${{ github.event.pull_request.html_url }} | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} | |
| EVENT_ACTION: ${{ github.event.action }} | |
| JIRA_API_AUTH: ${{ secrets.JIRA_API_AUTH }} | |
| JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| with: | |
| result-encoding: string | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const old_body = process.env.PR_BODY || ''; | |
| const issue_number = process.env.PR_ID; | |
| const pr_url = process.env.PR_URL; | |
| const pr_title = process.env.PR_TITLE; | |
| const eventAction = process.env.EVENT_ACTION; | |
| const headRef = process.env.PR_HEAD_REF || ''; | |
| // Expand bare JIRA ticket mentions (#AG-XXXX) into markdown links | |
| const body = old_body.replace(/#((AG|RTI)-\d{3,})/g, `[$1](https://ag-grid.atlassian.net/browse/$1)`); | |
| if (body !== old_body) { | |
| await github.rest.issues.update({ owner, repo, issue_number, body }); | |
| } | |
| // Post a Jira comment when the PR is opened, or when a JIRA reference is added | |
| // later via an edit (e.g. auto-generated revert PRs, where the ticket is added | |
| // after opening). The per-PR sentinel dedup below prevents duplicate comments. | |
| if (eventAction !== 'opened' && eventAction !== 'edited') return; | |
| if (!process.env.JIRA_API_AUTH) return; | |
| // AI Workflow Delivery PRs post their own JIRA comment once the run is | |
| // actually ready for review, so skip the generic mention comment here. | |
| if (headRef.startsWith('ghabot-ag-')) { | |
| console.log(`Skipping JIRA mention comment for AI workflow PR (branch ${headRef}).`); | |
| return; | |
| } | |
| const { addJiraComment, getJiraIssueComments } = | |
| require('./scripts/ci/_utils.mjs'); | |
| // Collect all JIRA tickets referenced in the PR body (using the possibly-updated body) | |
| const ticketRegex = /(AG|RTI)-\d{3,}/gi; | |
| const tickets = [...new Set([...(body || old_body).matchAll(ticketRegex)].map(m => m[0].toUpperCase()))]; | |
| if (!tickets.length) return; | |
| const prLink = `https://github.com/${owner}/${repo}/pull/${issue_number}`; | |
| // Sentinel string embedded in the comment so we can detect it later and avoid duplicates | |
| const sentinel = `gh-pr-mention:pr=${issue_number}`; | |
| const paragraph = (content) => ({ type: 'paragraph', content: Array.isArray(content) ? content : [content] }); | |
| const txt = (text) => ({ text, type: 'text' }); | |
| const link = (text, url) => ({ type: 'text', text, marks: [{ type: 'link', attrs: { href: url, title: text } }] }); | |
| await Promise.all(tickets.map(async (ticket) => { | |
| // Deduplicate: check whether we already posted a comment for this PR on this ticket | |
| const existing = await getJiraIssueComments(ticket); | |
| const alreadyPosted = existing?.some(c => { | |
| // Comments stored as ADF; fall back to plain text check on stringified body | |
| const raw = JSON.stringify(c.body || ''); | |
| return raw.includes(sentinel); | |
| }); | |
| if (alreadyPosted) { | |
| console.log(`Skipping ${ticket} — already has a comment for PR #${issue_number}`); | |
| return; | |
| } | |
| const adf = { | |
| type: 'doc', | |
| version: 1, | |
| content: [ | |
| paragraph([ | |
| txt(`This issue was mentioned in `), | |
| link(`PR #${issue_number}`, prLink), | |
| pr_title ? txt(` — ${pr_title}`) : txt(''), | |
| txt(' by '), | |
| link('CI workflow', process.env.JOB_URL || '#'), | |
| txt(`.\n${sentinel}`), | |
| ]), | |
| ], | |
| }; | |
| await addJiraComment(ticket, adf); | |
| })); |