1+ #!/usr/bin/env node
2+
3+ import { execSync } from 'child_process' ;
4+ import fs from 'fs' ;
5+ import path from 'path' ;
6+
7+ const packageJson = JSON . parse ( fs . readFileSync ( 'package.json' , 'utf8' ) ) ;
8+ const currentVersion = packageJson . version ;
9+
10+ console . log ( `🚀 Starting release process for v${ currentVersion } ` ) ;
11+
12+ function run ( command ) {
13+ console . log ( `> ${ command } ` ) ;
14+ try {
15+ return execSync ( command , { stdio : 'inherit' , encoding : 'utf8' } ) ;
16+ } catch ( error ) {
17+ console . error ( `❌ Command failed: ${ command } ` ) ;
18+ process . exit ( 1 ) ;
19+ }
20+ }
21+
22+ function extractChangelogForVersion ( version ) {
23+ if ( ! fs . existsSync ( 'CHANGELOG.md' ) ) {
24+ return `Release v${ version } ` ;
25+ }
26+
27+ const changelog = fs . readFileSync ( 'CHANGELOG.md' , 'utf8' ) ;
28+ const lines = changelog . split ( '\n' ) ;
29+ const startIndex = lines . findIndex ( line =>
30+ line . includes ( `[${ version } ]` ) && line . startsWith ( '## ' )
31+ ) ;
32+
33+ if ( startIndex === - 1 ) {
34+ return `Release v${ version } ` ;
35+ }
36+
37+ const endIndex = lines . findIndex ( ( line , index ) =>
38+ index > startIndex && line . startsWith ( '## [' )
39+ ) ;
40+
41+ const versionLines = lines . slice (
42+ startIndex + 1 ,
43+ endIndex === - 1 ? undefined : endIndex
44+ ) ;
45+
46+ return versionLines . join ( '\n' ) . trim ( ) ;
47+ }
48+
49+ async function createRelease ( ) {
50+ // 1. Build and test
51+ console . log ( '\n📦 Building and testing...' ) ;
52+ run ( 'npm run build' ) ;
53+ run ( 'npm test' ) ;
54+
55+ // 2. Create git tag
56+ console . log ( '\n🏷️ Creating git tag...' ) ;
57+ run ( `git tag -a v${ currentVersion } -m "Release v${ currentVersion } "` ) ;
58+
59+ // 3. Push to GitHub
60+ console . log ( '\n⬆️ Pushing to GitHub...' ) ;
61+ run ( 'git push origin main' ) ;
62+ run ( `git push origin v${ currentVersion } ` ) ;
63+
64+ // 4. Publish to NPM
65+ console . log ( '\n📤 Publishing to NPM...' ) ;
66+ run ( 'npm publish' ) ;
67+
68+ // 5. Create GitHub release (if gh CLI is available)
69+ console . log ( '\n🎉 Creating GitHub release...' ) ;
70+ try {
71+ const changelog = extractChangelogForVersion ( currentVersion ) ;
72+ const releaseTitle = `🚀 Release v${ currentVersion } ` ;
73+
74+ // Escape special characters in changelog
75+ const escapedChangelog = changelog . replace ( / ` / g, '\\`' ) . replace ( / \$ / g, '\\$' ) ;
76+
77+ run ( `gh release create v${ currentVersion } --title "${ releaseTitle } " --notes "${ escapedChangelog } "` ) ;
78+ console . log ( '✅ GitHub release created successfully!' ) ;
79+ } catch ( error ) {
80+ console . log ( '⚠️ GitHub CLI not available or not authenticated.' ) ;
81+ console . log ( 'Please create the release manually on GitHub.' ) ;
82+ console . log ( 'Release notes saved to RELEASE_NOTES_v' + currentVersion + '.md' ) ;
83+ }
84+
85+ console . log ( `\n🎉 Release v${ currentVersion } completed successfully!` ) ;
86+ console . log ( `📦 Package: https://www.npmjs.com/package/${ packageJson . name } ` ) ;
87+ console . log ( `🏷️ Tag: https://github.com/${ packageJson . repository . url . split ( '/' ) . slice ( - 2 ) . join ( '/' ) . replace ( '.git' , '' ) } /releases/tag/v${ currentVersion } ` ) ;
88+ }
89+
90+ // Run the release process
91+ createRelease ( ) . catch ( error => {
92+ console . error ( '❌ Release failed:' , error ) ;
93+ process . exit ( 1 ) ;
94+ } ) ;
0 commit comments