Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5860105

Browse files
committedMar 17, 2025··
Build: Backport changelog generation from jQuery
1 parent 5c0edde commit 5860105

File tree

5 files changed

+183
-6
lines changed

5 files changed

+183
-6
lines changed
 

‎.release-it.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ module.exports = {
55
hooks: {
66
"before:init": "bash ./build/release/pre-release.sh",
77
"after:version:bump":
8-
"sed -i 's/main\\/AUTHORS.txt/${version}\\/AUTHORS.txt/' package.json",
8+
"sed -i 's/main\\/AUTHORS.txt/${version}\\/AUTHORS.txt/' package.json",
99
"after:bump": "cross-env VERSION=${version} npm run build",
10-
"before:git:release": "git add -f dist/",
10+
"before:git:release": "git add -f dist/ changelog.md",
1111
"after:release": "echo 'Run the following to complete the release:' && " +
12-
"echo './build/release/post-release.sh $\{version}'"
12+
"echo './build/release/post-release.sh $\{version}'"
1313
},
1414
git: {
15+
16+
// Use the node script directly to avoid an npm script
17+
// command log entry in the GH release notes
18+
changelog: "node build/release/changelog.mjs ${from} ${to}",
1519
commitMessage: "Release: ${version}",
1620
getLatestTagFromAllRefs: true,
1721
pushRepo: "git@github.com:jquery/jquery-mousewheel.git",

‎CHANGELOG.md ‎LEGACY_CHANGELOG.md

File renamed without changes.

‎build/release/changelog.mjs

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { writeFile } from "node:fs/promises";
2+
import { argv } from "node:process";
3+
import { exec as nodeExec } from "node:child_process";
4+
import util from "node:util";
5+
6+
const exec = util.promisify( nodeExec );
7+
8+
const rbeforeHash = /.#$/;
9+
const rendsWithHash = /#$/;
10+
const rcherry = / \(cherry picked from commit [^)]+\)/;
11+
const rcommit = /Fix(?:e[sd])? ((?:[a-zA-Z0-9_-]{1,39}\/[a-zA-Z0-9_-]{1,100}#)|#|gh-)(\d+)/g;
12+
const rcomponent = /^([^ :]+):\s*([^\n]+)/;
13+
const rnewline = /\r?\n/;
14+
15+
const prevVersion = argv[ 2 ];
16+
const nextVersion = argv[ 3 ];
17+
const blogUrl = process.env.BLOG_URL;
18+
19+
if ( !prevVersion || !nextVersion ) {
20+
throw new Error( "Usage: `node changelog.js PREV_VERSION NEXT_VERSION`" );
21+
}
22+
23+
function ticketUrl( ticketId ) {
24+
return `https://github.com/jquery/jquery-mousewheel/issues/${ ticketId }`;
25+
}
26+
27+
function getTicketsForCommit( commit ) {
28+
const tickets = [];
29+
30+
commit.replace( rcommit, function( _match, refType, ticketId ) {
31+
const ticket = {
32+
url: ticketUrl( ticketId ),
33+
label: "#" + ticketId
34+
};
35+
36+
// If the refType has anything before the #, assume it's a GitHub ref
37+
if ( rbeforeHash.test( refType ) ) {
38+
39+
// console.log( refType );
40+
refType = refType.replace( rendsWithHash, "" );
41+
ticket.url = `https://github.com/${ refType }/issues/${ ticketId }`;
42+
ticket.label = refType + ticket.label;
43+
}
44+
45+
tickets.push( ticket );
46+
} );
47+
48+
return tickets;
49+
}
50+
51+
async function getCommits() {
52+
const format =
53+
"__COMMIT__%n%s (__TICKETREF__[%h](https://github.com/jquery/jquery-mousewheel/commit/%H))%n%b";
54+
const { stdout } = await exec(
55+
`git log --format="${ format }" ${ prevVersion }..${ nextVersion }`
56+
);
57+
const commits = stdout.split( "__COMMIT__" ).slice( 1 );
58+
59+
return removeReverts( commits.map( parseCommit ).sort( sortCommits ) );
60+
}
61+
62+
function parseCommit( commit ) {
63+
const tickets = getTicketsForCommit( commit )
64+
.map( ( ticket ) => {
65+
return `[${ ticket.label }](${ ticket.url })`;
66+
} )
67+
.join( ", " );
68+
69+
// Drop the commit message body
70+
let message = `${ commit.trim().split( rnewline )[ 0 ] }`;
71+
72+
// Add any ticket references
73+
message = message.replace( "__TICKETREF__", tickets ? `${ tickets }, ` : "" );
74+
75+
// Remove cherry-pick references
76+
message = message.replace( rcherry, "" );
77+
78+
return message;
79+
}
80+
81+
function sortCommits( a, b ) {
82+
const aComponent = rcomponent.exec( a );
83+
const bComponent = rcomponent.exec( b );
84+
85+
if ( aComponent && bComponent ) {
86+
if ( aComponent[ 1 ] < bComponent[ 1 ] ) {
87+
return -1;
88+
}
89+
if ( aComponent[ 1 ] > bComponent[ 1 ] ) {
90+
return 1;
91+
}
92+
return 0;
93+
}
94+
95+
if ( a < b ) {
96+
return -1;
97+
}
98+
if ( a > b ) {
99+
return 1;
100+
}
101+
return 0;
102+
}
103+
104+
/**
105+
* Remove all revert commits and the commit it is reverting
106+
*/
107+
function removeReverts( commits ) {
108+
const remove = [];
109+
110+
commits.forEach( function( commit ) {
111+
const match = /\*\s*Revert "([^"]*)"/.exec( commit );
112+
113+
// Ignore double reverts
114+
if ( match && !/^Revert "([^"]*)"/.test( match[ 0 ] ) ) {
115+
remove.push( commit, match[ 0 ] );
116+
}
117+
} );
118+
119+
remove.forEach( function( message ) {
120+
const index = commits.findIndex( ( commit ) => commit.includes( message ) );
121+
if ( index > -1 ) {
122+
123+
// console.log( "Removing", commits[ index ] );
124+
commits.splice( index, 1 );
125+
}
126+
} );
127+
128+
return commits;
129+
}
130+
131+
function addHeaders( commits ) {
132+
const components = {};
133+
let markdown = "";
134+
135+
commits.forEach( function( commit ) {
136+
const match = rcomponent.exec( commit );
137+
if ( match ) {
138+
let component = match[ 1 ];
139+
if ( !/^[A-Z]/.test( component ) ) {
140+
component =
141+
component.slice( 0, 1 ).toUpperCase() +
142+
component.slice( 1 ).toLowerCase();
143+
}
144+
if ( !components[ component.toLowerCase() ] ) {
145+
markdown += "\n## " + component + "\n\n";
146+
components[ component.toLowerCase() ] = true;
147+
}
148+
markdown += `- ${ match[ 2 ] }\n`;
149+
} else {
150+
markdown += `- ${ commit }\n`;
151+
}
152+
} );
153+
154+
return markdown;
155+
}
156+
157+
async function generate() {
158+
const commits = await getCommits();
159+
160+
let changelog = "# Changelog\n";
161+
if ( blogUrl ) {
162+
changelog += `\n${ blogUrl }\n`;
163+
}
164+
changelog += addHeaders( commits );
165+
166+
// Write markdown to changelog.md
167+
await writeFile( "changelog.md", changelog );
168+
169+
// Log regular changelog for release-it
170+
console.log( changelog );
171+
172+
return changelog;
173+
}
174+
175+
generate();

‎build/release/pre-release.sh

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
set -euo pipefail
44

5-
read -p "Press enter if you updated CHANGELOG.md; abort otherwise"
6-
75
# Install dependencies
86
npm ci
97

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"browser"
2727
],
2828
"files": [
29-
"CHANGELOG.md",
29+
"changelog.md",
3030
"dist/jquery.mousewheel.js",
3131
"dist/jquery.mousewheel.min.js",
3232
"README.md",

0 commit comments

Comments
 (0)
Please sign in to comment.