@@ -82,12 +82,12 @@ jobs:
8282 MINOR=$(echo $CURRENT_VERSION | cut -d. -f2)
8383 PATCH=$(echo $CURRENT_VERSION | cut -d. -f3 | cut -d- -f1)
8484
85- # Determine version bump based on commit messages
85+ # Standard semver: bump patch by default, minor for features, major for breaking
8686 if git log --format=%B -n 20 | grep -qi "BREAKING CHANGE\|!:"; then
8787 MAJOR=$((MAJOR + 1))
8888 MINOR=0
8989 PATCH=0
90- elif git log --format=%B -n 10 | grep -qi "^feat"; then
90+ elif git log --format=%B -n 10 | grep -qiE "^feat(\(|:) "; then
9191 MINOR=$((MINOR + 1))
9292 PATCH=0
9393 else
@@ -240,70 +240,116 @@ jobs:
240240
241241 // Get commits since last tag
242242 let commits;
243+ let lastTag = null;
243244 try {
244- const lastTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf8' }).trim();
245- commits = execSync(`git log ${lastTag}..HEAD --pretty=format:"%h % s"`, { encoding: 'utf8' });
245+ lastTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf8' }).trim();
246+ commits = execSync(`git log ${lastTag}..HEAD --pretty=format:"%s"`, { encoding: 'utf8' });
246247 } catch {
247- commits = execSync('git log --pretty=format:"%h % s" -n 20', { encoding: 'utf8' });
248+ commits = execSync('git log --pretty=format:"%s" -n 20', { encoding: 'utf8' });
248249 }
249250
250- const lines = commits.split('\n').filter(line => line.trim());
251+ const lines = commits.split('\n').filter(line => line.trim() && !line.includes('chore(release)'));
252+
253+ // Helper to humanize commit messages
254+ const humanize = (msg) => {
255+ return msg
256+ .replace(/^feat(\([^)]+\))?:\s*/i, '')
257+ .replace(/^fix(\([^)]+\))?:\s*/i, '')
258+ .replace(/^chore(\([^)]+\))?:\s*/i, '')
259+ .replace(/^docs(\([^)]+\))?:\s*/i, '')
260+ .replace(/^refactor(\([^)]+\))?:\s*/i, '')
261+ .replace(/^test(\([^)]+\))?:\s*/i, '')
262+ .replace(/^ci(\([^)]+\))?:\s*/i, '')
263+ .replace(/^perf(\([^)]+\))?:\s*/i, '')
264+ .trim();
265+ };
266+
267+ // Capitalize first letter
268+ const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
251269
252270 // Categorize commits
253271 const features = [];
254272 const fixes = [];
255- const chores = [];
273+ const improvements = [];
256274 const breaking = [];
257275
258- for (const line of lines) {
259- const [hash, ...msgParts] = line.split(' ' );
260- const msg = msgParts.join(' ') ;
276+ for (const msg of lines) {
277+ const clean = humanize(msg );
278+ if (!clean) continue ;
261279
262280 if (msg.includes('BREAKING CHANGE') || msg.includes('!:')) {
263- breaking.push(`- ${msg} (${hash})` );
264- } else if (msg.startsWith(' feat' )) {
265- features.push(`- ${msg.replace('feat:', '').replace('feat(', '(').trim()} (${hash})` );
266- } else if (msg.startsWith(' fix' )) {
267- fixes.push(`- ${msg.replace('fix:', '').replace('fix(', '(').trim()} (${hash})` );
268- } else if (! msg.startsWith(' chore(release)' )) {
269- chores .push(`- ${msg} (${hash})` );
281+ breaking.push(capitalize(clean) );
282+ } else if (msg.match(/^ feat(\(|:)/i )) {
283+ features.push(capitalize(clean) );
284+ } else if (msg.match(/^ fix(\(|:)/i )) {
285+ fixes.push(capitalize(clean) );
286+ } else if (msg.match(/^(refactor|perf| chore|docs|test|ci)(\(|:)/i )) {
287+ improvements .push(capitalize(clean) );
270288 }
271289 }
272290
273- // Build changelog
274- let changelog = '## 🚀 What\'s Changed\n\n ';
291+ // Build a friendly changelog
292+ let changelog = '';
275293
294+ // Intro
295+ if (lastTag) {
296+ changelog += `Hey there! We've been busy making Autohand better. Here's what's new since ${lastTag}:\n\n`;
297+ } else {
298+ changelog += `Hey there! Here's what's new in this release:\n\n`;
299+ }
300+
301+ // Breaking changes (serious tone)
276302 if (breaking.length > 0) {
277- changelog += '### ⚠️ BREAKING CHANGES\n' + breaking.join('\n') + '\n\n';
303+ changelog += '### Heads up! Breaking Changes\n\n';
304+ changelog += 'These changes might require updates to your setup:\n\n';
305+ breaking.forEach(item => { changelog += `- ${item}\n`; });
306+ changelog += '\n';
278307 }
279308
309+ // Features (excited tone)
280310 if (features.length > 0) {
281- changelog += '### ✨ Features\n' + features.join('\n') + '\n\n';
311+ changelog += '### New Stuff\n\n';
312+ features.forEach(item => { changelog += `- ${item}\n`; });
313+ changelog += '\n';
282314 }
283315
316+ // Fixes (helpful tone)
284317 if (fixes.length > 0) {
285- changelog += '### 🐛 Bug Fixes\n' + fixes.join('\n') + '\n\n';
318+ changelog += '### Bug Fixes\n\n';
319+ if (fixes.length === 1) {
320+ changelog += `We squashed a bug:\n\n`;
321+ } else {
322+ changelog += `We squashed ${fixes.length} bugs:\n\n`;
323+ }
324+ fixes.forEach(item => { changelog += `- ${item}\n`; });
325+ changelog += '\n';
326+ }
327+
328+ // Improvements (casual tone)
329+ if (improvements.length > 0 && improvements.length <= 8) {
330+ changelog += '### Under the Hood\n\n';
331+ changelog += 'Some housekeeping and improvements:\n\n';
332+ improvements.forEach(item => { changelog += `- ${item}\n`; });
333+ changelog += '\n';
286334 }
287335
288- if (chores.length > 0 && chores.length < 10) {
289- changelog += '### 🔧 Maintenance\n' + chores.join('\n') + '\n\n';
336+ // If nothing categorized, add a generic message
337+ if (features.length === 0 && fixes.length === 0 && improvements.length === 0 && breaking.length === 0) {
338+ changelog += 'Minor updates and improvements to keep things running smoothly.\n\n';
290339 }
291340
292- // Add installation instructions
341+ // Installation section
293342 const cb = '`' + '`' + '`';
294- changelog += '\n## 📦 Installation\n\n';
295- changelog += '### Recommended: Install Script\n';
343+ changelog += '---\n\n';
344+ changelog += '### Get it\n\n';
345+ changelog += '**Quickest way:**\n';
296346 changelog += cb + 'bash\ncurl -fsSL https://autohand.ai/install.sh | sh\n' + cb + '\n\n';
297- changelog += '### Or install a specific version\n';
298- changelog += cb + 'bash\nAUTOHAND_VERSION=' + version + ' curl -fsSL https://autohand.ai/install.sh | sh\n' + cb + '\n\n';
299- changelog += '### Via npm/bun\n';
300- changelog += cb + 'bash\nnpm install -g autohand-cli\n# or\nbun install -g autohand-cli\n' + cb + '\n\n';
301- changelog += '### Manual Download\n';
302- changelog += 'Download the appropriate binary for your system from the assets below.\n\n';
303- changelog += '## 📋 Available Binaries\n';
347+ changelog += '**Via npm or bun:**\n';
348+ changelog += cb + 'bash\nnpm install -g autohand-cli\n' + cb + '\n\n';
349+ changelog += '**Or grab a binary below** for your platform.\n\n';
304350 changelog += '| Platform | Architecture | Binary |\n';
305351 changelog += '|----------|--------------|--------|\n';
306- changelog += '| macOS | Apple Silicon (M1/M2/M3/M4) | `autohand-macos-arm64` |\n';
352+ changelog += '| macOS | Apple Silicon | `autohand-macos-arm64` |\n';
307353 changelog += '| macOS | Intel | `autohand-macos-x64` |\n';
308354 changelog += '| Linux | x64 | `autohand-linux-x64` |\n';
309355 changelog += '| Linux | ARM64 | `autohand-linux-arm64` |\n';
0 commit comments