Skip to content

Commit 37259ea

Browse files
authored
feat(ci): add comment on pr workflow (#663)
1 parent a477740 commit 37259ea

1 file changed

Lines changed: 179 additions & 1 deletion

File tree

.github/workflows/deploy.yml

Lines changed: 179 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ jobs:
8080

8181
outputs:
8282
published: ${{ steps.check-changes.outputs.has_changes }}
83+
package_versions: ${{ steps.increment.outputs.package_versions }}
8384

8485
steps:
8586
- name: Checkout Project
@@ -126,10 +127,15 @@ jobs:
126127
echo "npmAuthToken: ${{ env.token }}" >> ~/.yarnrc.yml
127128
128129
- name: Sync and Increment Package Versions
130+
id: increment
129131
if: steps.check-changes.outputs.has_changes == 'true'
130132
run: |
131133
yarn package-tools sync --tag ${GITHUB_REF##*/}
132-
yarn package-tools increment --packages ${{ needs.analyze-changes.outputs.node-recursive }} --tag ${GITHUB_REF##*/}
134+
OUTPUT=$(yarn package-tools increment --packages ${{ needs.analyze-changes.outputs.node-recursive }} --tag ${GITHUB_REF##*/})
135+
echo "$OUTPUT"
136+
echo "package_versions<<EOF" >> $GITHUB_OUTPUT
137+
echo "$OUTPUT" >> $GITHUB_OUTPUT
138+
echo "EOF" >> $GITHUB_OUTPUT
133139
- name: Build Changed Packages
134140
if: steps.check-changes.outputs.has_changes == 'true'
135141
run: yarn run build:prod
@@ -348,3 +354,175 @@ jobs:
348354
echo "=========================================="
349355
echo "Tagging complete!"
350356
echo "=========================================="
357+
358+
comment-on-pr:
359+
name: Comment on Released PRs
360+
needs: [publish-npm, publish-tag]
361+
runs-on: ubuntu-latest
362+
363+
steps:
364+
- name: Get PR Number
365+
id: get-pr
366+
uses: actions/github-script@v7
367+
with:
368+
script: |
369+
const deploySha = context.sha;
370+
const owner = context.repo.owner;
371+
const repo = context.repo.repo;
372+
373+
try {
374+
const prs = await github.rest.repos.listPullRequestsAssociatedWithCommit({
375+
owner, repo, commit_sha: deploySha
376+
});
377+
const mergedPR = prs.data.find(pr => pr.merged_at);
378+
if (mergedPR) {
379+
core.setOutput('pr_number', String(mergedPR.number));
380+
return;
381+
}
382+
} catch (error) {
383+
console.log(`Failed to discover PR from commit: ${error.message}`);
384+
}
385+
core.setOutput('pr_number', '');
386+
387+
- name: Post Release Comment on PR
388+
if: steps.get-pr.outputs.pr_number != ''
389+
uses: actions/github-script@v7
390+
with:
391+
script: |
392+
const prNumber = parseInt('${{ steps.get-pr.outputs.pr_number }}');
393+
394+
const raw = `${{ needs.publish-npm.outputs.package_versions }}`;
395+
const packageVersions = {};
396+
for (const line of raw.split('\n')) {
397+
const match = line.match(/^(.+?)\s+=>\s+(.+)$/);
398+
if (match) packageVersions[match[1].trim()] = match[2].trim();
399+
}
400+
const packageEntries = Object.entries(packageVersions);
401+
402+
const owner = context.repo.owner;
403+
const repo = context.repo.repo;
404+
const repoUrl = `https://github.com/${owner}/${repo}`;
405+
const hasPackages = packageEntries.length > 0;
406+
407+
const taggablePackages = {
408+
'@webex/widgets': 'webex-widgets',
409+
'@webex/cc-widgets': 'webex-cc-widgets'
410+
};
411+
412+
const aggregators = ['@webex/cc-widgets', '@webex/widgets'];
413+
414+
let commentBody;
415+
416+
if (hasPackages) {
417+
const primaryPackage = aggregators.find(p => packageVersions[p])
418+
|| packageEntries[0][0];
419+
const primaryVersion = packageVersions[primaryPackage];
420+
const stableVersion = primaryVersion
421+
.replace(/-next\..*/, '')
422+
.replace(/-[a-z]*\..*/, '');
423+
424+
let cname = 'widgets.webex.com';
425+
try {
426+
const cnameFile = await github.rest.repos.getContent({ owner, repo, path: 'docs/CNAME' });
427+
const encoded = cnameFile.data.content;
428+
if (typeof encoded === 'string') {
429+
cname = Buffer.from(encoded, 'base64').toString().trim();
430+
}
431+
} catch (e) {
432+
console.log(`Could not read docs/CNAME, using default changelog host: ${e.message}`);
433+
}
434+
435+
const changelogUrl = new URL(`https://${cname}/changelog/`);
436+
if (stableVersion) {
437+
changelogUrl.searchParams.set('stable_version', stableVersion);
438+
}
439+
changelogUrl.searchParams.set('package', primaryPackage);
440+
changelogUrl.searchParams.set('version', primaryVersion);
441+
442+
const tagLinkParts = Object.entries(taggablePackages)
443+
.filter(([pkg]) => packageVersions[pkg])
444+
.map(([pkg, prefix]) => {
445+
const tag = `${prefix}-v${packageVersions[pkg]}`;
446+
return `[\`${tag}\`](${repoUrl}/releases/tag/${tag})`;
447+
});
448+
const releaseLine = tagLinkParts.length
449+
? `| **Released in:** ${tagLinkParts.join(', ')} |`
450+
: '';
451+
452+
const rows = packageEntries
453+
.sort(([a], [b]) => {
454+
if (a === '@webex/cc-widgets') return -1;
455+
if (b === '@webex/cc-widgets') return 1;
456+
if (a === '@webex/widgets') return -1;
457+
if (b === '@webex/widgets') return 1;
458+
return a.localeCompare(b);
459+
})
460+
.map(([pkg, ver]) => `| \`${pkg}\` | \`${ver}\` |`)
461+
.join('\n');
462+
463+
const packagesTable = [
464+
'',
465+
'| Packages Updated | Version |',
466+
'|---------|---------|',
467+
rows,
468+
''
469+
].join('\n');
470+
471+
commentBody = [
472+
'| :tada: Your changes are now available! |',
473+
'|---|',
474+
releaseLine,
475+
`| :book: **[View full changelog →](${changelogUrl})** |`,
476+
packagesTable,
477+
'Thank you for your contribution!',
478+
'',
479+
`_:robot: This is an automated message. For queries, please contact [support](https://developer.webex.com/support)._`
480+
].filter(Boolean).join('\n');
481+
} else {
482+
commentBody = [
483+
':white_check_mark: **Your changes have been merged!**',
484+
'',
485+
'Thank you for your contribution!',
486+
'',
487+
`_:robot: This is an automated message. For queries, please contact [support](https://developer.webex.com/support)._`
488+
].join('\n');
489+
}
490+
491+
try {
492+
const pr = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
493+
if (!pr.data.merged_at) return;
494+
495+
const comments = await github.paginate(github.rest.issues.listComments, {
496+
owner, repo,
497+
issue_number: prNumber,
498+
per_page: 100
499+
});
500+
501+
const detailedComment = comments.find(comment =>
502+
comment.user.type === 'Bot' &&
503+
comment.body.includes('Your changes are now available')
504+
);
505+
const mergedComment = comments.find(comment =>
506+
comment.user.type === 'Bot' &&
507+
comment.body.includes('Your changes have been merged')
508+
);
509+
510+
if (detailedComment) return;
511+
if (!hasPackages && mergedComment) return;
512+
513+
if (mergedComment && hasPackages) {
514+
await github.rest.issues.updateComment({
515+
owner, repo,
516+
comment_id: mergedComment.id,
517+
body: commentBody
518+
});
519+
} else {
520+
await github.rest.issues.createComment({
521+
owner, repo,
522+
issue_number: prNumber,
523+
body: commentBody
524+
});
525+
}
526+
} catch (error) {
527+
core.warning(`Failed to comment on PR #${prNumber}: ${error.message}`);
528+
}

0 commit comments

Comments
 (0)