name: Changelog Comment on: pull_request_target: types: [opened, reopened] workflow_dispatch: inputs: pr_number: description: 'PR number to post the changelog comment on (for testing)' required: true type: number jobs: comment: name: Post changelog comment runs-on: ubuntu-latest steps: - name: Post or update changelog comment uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 with: github-token: ${{ secrets.CROWDIN_GH_TOKEN }} script: | const marker = ''; const mergedMarker = ''; const sections = ['### Added', '', '### Changed', '', '### Deprecated', '', '### Removed', '', '### Fixed', '', '### Security'].join('\n'); const productBlock = (name) => `
\n${name}\n\n${sections}\n\n
`; const template = [ marker, '## Pull request changelog', '', '', '', productBlock('App'), '', productBlock('Website'), '', productBlock('Hosting'), ].join('\n'); // Resolve PR number from event or workflow_dispatch input const prNumber = context.payload.pull_request?.number ?? parseInt('${{ github.event.inputs.pr_number }}', 10); if (!prNumber || isNaN(prNumber)) { core.setFailed('Could not determine PR number'); return; } // Get PR details (need base ref for child PR detection) const { data: pr } = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber, }); // Check if bot comment already exists const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, }); const existingComment = comments.find(c => c.body.includes(marker)); if (existingComment) { core.info('Changelog comment already exists, skipping'); return; } // Post the template comment await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, body: template, }); core.info(`Posted changelog comment on PR #${prNumber}`); // Detect child PR: check if this PR's base branch is another open PR's head branch const baseRef = pr.base.ref; if (baseRef === 'main' || baseRef === 'prod') { return; } // Look for a parent PR whose head branch matches our base branch const { data: candidatePRs } = await github.rest.pulls.list({ owner: context.repo.owner, repo: context.repo.repo, state: 'open', head: `${context.repo.owner}:${baseRef}`, }); if (candidatePRs.length === 0) { return; } const parentPR = candidatePRs[0]; core.info(`Detected parent PR #${parentPR.number} for child PR #${prNumber}`); // Add admonition to child PR's changelog comment const { data: childComments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, }); const childChangelogComment = childComments.find(c => c.body.includes(marker)); if (childChangelogComment && !childChangelogComment.body.includes(mergedMarker)) { await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: childChangelogComment.id, body: `${mergedMarker}\n> [!NOTE]\n> This changelog has been merged into the changelog for #${parentPR.number}\n\n${childChangelogComment.body}`, }); }