Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add "Thanks" section to release-please configuration #5276

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: add script to credit contributors in release notes 🎄
- 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 #5272 (ho ho ho)
TG199 committed Dec 28, 2024
commit 32b9a8d9e015df9b059c51899593988fac2e5e69
3 changes: 1 addition & 2 deletions .github/release-please/config.json
Original file line number Diff line number Diff line change
@@ -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": {
".": {}
37 changes: 35 additions & 2 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -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/*
@@ -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
@@ -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",
@@ -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",
128 changes: 128 additions & 0 deletions scripts/mention-contributors.mjs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Change request] As a design point, I don't think taking on the burden of a full script is ideal. Assuming release-please doesn't have contribution thanks as a core feature, I think the next best thing would be a plugin. Which is a thing that can be made: https://github.com/googleapis/release-please/blob/3bae6137f939a4db2df1d32436453d1ac2a41e9f/docs/manifest-releaser.md#plugin-usage

googleapis/release-please#2221 tracks them adding more docs and also links to some information + existing plugins.

Is that an approach you think could work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Giving this a try!

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();