Skip to content

Commit

Permalink
feat: add script to credit contributors in release notes 🎄
Browse files Browse the repository at this point in the history
- Fetches contributor details for merged PRs using GitHub's API.
- Enhances auto-generated release notes by tagging contributors.
- Prepares for integration into the release workflow.

A special holiday update to spread cheer and gratitude this Christmas season! 🎅🎁

Resolves mochajs#5272 (ho ho ho)
  • Loading branch information
TG199 committed Dec 28, 2024
1 parent ffa019f commit 32b9a8d
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 4 deletions.
3 changes: 1 addition & 2 deletions .github/release-please/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
{ "type": "refactor", "section": "🧹 Chores", "hidden": false },
{ "type": "test", "section": "🧹 Chores", "hidden": false },
{ "type": "build", "section": "🤖 Automation", "hidden": false },
{ "type": "ci", "section": "🤖 Automation", "hidden": true },
{ "type": "thanks", "section": "🙏 Thank you", "hidden": false }
{ "type": "ci", "section": "🤖 Automation", "hidden": true }
],
"packages": {
".": {}
Expand Down
37 changes: 35 additions & 2 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,51 @@ jobs:
config-file: .github/release-please/config.json
manifest-file: .github/release-please/manifest.json

acknowledge_contributors:
name: Acknowledge Contributors
runs-on: ubuntu-latest
needs: release_please
if: needs.release_please.outputs.releaseCreated
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
show-progress: false

- uses: actions/setup-node@v4
with:
node-version: lts/*

- name: Install dependencies
run: npm install octokit

- name: Add contributors to release notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: node scripts/mention-contributors.mjs

- name: Commit updated changelog
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add CHANGELOG.md
git commit -m "docs: update release notes with contributors" || exit 0
git push
npm_publish:
name: Publish to npm
runs-on: ubuntu-latest
environment: npm
needs: release_please
needs: [release_please, acknowledge_contributors]
if: needs.release_please.outputs.releaseCreated
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
with:
show-progress: false

- uses: actions/setup-node@v4
with:
node-version: lts/*
Expand All @@ -46,4 +79,4 @@ jobs:

- run: npm publish --provenance --access public --tag=next
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
"version": "run-p version:* && git add -A ./AUTHORS ./CHANGELOG.md"
},
"dependencies": {
"@octokit/rest": "^21.0.2",
"ansi-colors": "^4.1.3",
"browser-stdout": "^1.3.1",
"chokidar": "^3.5.3",
Expand All @@ -107,6 +108,7 @@
"log-symbols": "^4.1.0",
"minimatch": "^5.1.6",
"ms": "^2.1.3",
"octokit": "^4.0.2",
"serialize-javascript": "^6.0.2",
"strip-json-comments": "^3.1.1",
"supports-color": "^8.1.1",
Expand Down
128 changes: 128 additions & 0 deletions scripts/mention-contributors.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
'use strict';

import { Octokit } from "octokit";
import fs from "node:fs";
import { date } from "zod";
import { console } from "node:inspector";

const token = process.env.GITHUB_TOKEN || "";
const owner = "mochajs";
const repo = "mocha";

const octokit = new Octokit({ auth: token});

async function getLastReleaseDate() {
try {
const { data: releases } = await octokit.request('GET /repos/{owner}/{repo}/releases', {
owner,
repo,
per_page: 2
});

if (releases.length > 1) {
return new Date(releases[1].published_at);
}

return new Date(Date.now() - (30 * 24 * 60 * 60 * 1000));
} catch (error) {
console.error("Error fetching releases:", error);
return new Date(Date.now() - (30 * 24 * 60 * 60 * 1000));
}
}

async function getContributorFullName(username) {
try {
const { data } = await octokit.request('GET /users/{username}', {
username: username
});
return data.name || username;
} catch (error) {
console.error(`Error fetching user info for ${username}:`, error);
return username;
}
}

async function getContributors() {
try {
const lastReleaseDate = await getLastReleaseDate();
const contributors = new Map();
let page = 1;
const per_page = 100;

while (true) {
const { data } = await octokit.request('GET /repos/{owner}/{repo}/pulls', {
owner,
repo,
state: "closed",
sort: "updated",
direction: "desc",
per_page,
page
});

if (data.length === 0) break;

for (const pr of data) {
if (new Date(pr.merged_at) <= lastReleaseDate) {
break;
}

if (pr.merged_at && !pr.user.login.includes('[bot]')) {
if (!contributors.has(pr.user.login)) {
const fullName = await getContributorFullName(pr.user.login);
contributors.set(pr.user.login, fullName);
}
}
}

if (data[data.length - 1].merged_at && new Date(data[data.length - 1].merged_at) <= lastReleaseDate){
break;
}
page++;
}
return contributors;
} catch (error) {
console.error("Error fetching contributors:", error);
return new Map();
}
}

async function appendThankYouSection() {
try {
const changelogPath = "CHANGELOG.md";
const contributors = await getContributors();

if (contributors.size === 0) {
return;
}
let thankYouSection = "\n## ❤️ Thank You\n\n";
for (const [username, fullName] of contributors) {
thankYouSection += `* ${fullName} @${username}\n`;
}
thankYouSection += "\n";

const existingContent = fs.readFileSync(changelogPath, "utf-8");

const lines = existingContent.split("\n");

const firstVersionIndex = lines.findIndex(line => line.startsWith("#"));
if (firstVersionIndex === -1){
return;
}

const nextVersionIndex = lines.slice(firstVersionIndex + 1)
.findIndex(line => line.startsWith("#"));

const insertPosition = nextVersionIndex !== -1
? firstVersionIndex + nextVersionIndex + 1: lines.length;

lines.splice(insertPosition, 0, thankYouSection);

fs.writeFileSync(changelogPath, lines.join("\n"), "utf-8");
console.log("Thank you section added to changelog!")

} catch (error) {
console.error("Error updating CHANGELOG.md:", error);
}
}
appendThankYouSection();

0 comments on commit 32b9a8d

Please sign in to comment.