@@ -19,6 +19,19 @@ function run(cmd: string, opts?: { cwd?: string; stdio?: "pipe" | "inherit" }) {
1919 return result ?. trim ( ) ?? "" ;
2020}
2121
22+ function tryRun ( cmd : string , opts ?: { cwd ?: string ; stdio ?: "pipe" | "inherit" } ) : { ok : boolean ; output : string } {
23+ try {
24+ return { ok : true , output : run ( cmd , opts ) } ;
25+ } catch {
26+ return { ok : false , output : "" } ;
27+ }
28+ }
29+
30+ function isPublished ( name : string , version : string ) : boolean {
31+ const { ok } = tryRun ( `npm view ${ name } @${ version } version` ) ;
32+ return ok ;
33+ }
34+
2235function fatal ( msg : string ) : never {
2336 console . error ( `\x1b[31mError:\x1b[0m ${ msg } ` ) ;
2437 process . exit ( 1 ) ;
@@ -162,27 +175,54 @@ async function main() {
162175 for ( const pkg of packages ) {
163176 run ( `git add ${ join ( pkg , "package.json" ) } ` ) ;
164177 }
165- run ( `git commit -m "release: v${ version } "` ) ;
166- run ( "git push origin main" ) ;
178+ const staged = run ( "git diff --cached --name-only" ) ;
179+ if ( staged ) {
180+ run ( `git commit -m "release: v${ version } "` ) ;
181+ run ( "git push origin main" ) ;
182+ } else {
183+ console . log ( " No version changes to commit, skipping." ) ;
184+ }
167185
168186 // Git tag & GitHub release
169187 console . log ( `\n\x1b[1mCreating git tag v${ version } ...\x1b[0m` ) ;
170- run ( `git tag v${ version } ` ) ;
171- run ( `git push origin v${ version } ` ) ;
188+ const tagExists = tryRun ( `git rev-parse v${ version } ` ) . ok ;
189+ if ( tagExists ) {
190+ console . log ( ` Tag v${ version } already exists, skipping.` ) ;
191+ } else {
192+ run ( `git tag v${ version } ` ) ;
193+ run ( `git push origin v${ version } ` ) ;
194+ }
172195
173196 const prerelease = tag === "rc" ? "--prerelease" : "" ;
174- console . log ( "\n\x1b[1mCreating GitHub release...\x1b[0m" ) ;
175- run (
176- `gh release create v${ version } --title "v${ version } " --generate-notes ${ prerelease } ` . trim ( ) ,
177- { stdio : "inherit" } ,
178- ) ;
197+ const releaseExists = tryRun ( `gh release view v${ version } ` ) . ok ;
198+ if ( releaseExists ) {
199+ console . log ( ` GitHub release v${ version } already exists, skipping.` ) ;
200+ } else {
201+ console . log ( "\n\x1b[1mCreating GitHub release...\x1b[0m" ) ;
202+ run (
203+ `gh release create v${ version } --title "v${ version } " --generate-notes ${ prerelease } ` . trim ( ) ,
204+ { stdio : "inherit" } ,
205+ ) ;
206+ }
179207
180208 // Publish
181209 console . log ( `\n\x1b[1mPublishing to npm (tag: ${ tag } )...\x1b[0m` ) ;
210+ const failures : string [ ] = [ ] ;
182211 for ( const pkg of packages ) {
183212 const name = JSON . parse ( readFileSync ( join ( pkg , "package.json" ) , "utf-8" ) ) . name ;
213+ if ( isPublished ( name , version ) ) {
214+ console . log ( ` \x1b[33m⏭ ${ name } @${ version } already published, skipping.\x1b[0m` ) ;
215+ continue ;
216+ }
184217 console . log ( ` Publishing ${ name } ...` ) ;
185- run ( `pnpm publish --access public --tag ${ tag } --no-git-checks` , { cwd : pkg , stdio : "inherit" } ) ;
218+ const { ok } = tryRun ( `pnpm publish --access public --tag ${ tag } --no-git-checks` , { cwd : pkg , stdio : "inherit" } ) ;
219+ if ( ! ok ) {
220+ failures . push ( name ) ;
221+ }
222+ }
223+
224+ if ( failures . length > 0 ) {
225+ fatal ( `Failed to publish: ${ failures . join ( ", " ) } ` ) ;
186226 }
187227
188228 console . log ( `\n\x1b[32m✓ Released v${ version } \x1b[0m` ) ;
0 commit comments