@@ -44,7 +44,6 @@ export interface Releaser {
4444 prerelease : boolean | undefined ;
4545 target_commitish : string | undefined ;
4646 discussion_category_name : string | undefined ;
47- generate_release_notes : boolean | undefined ;
4847 } ) : Promise < { data : Release } > ;
4948
5049 updateRelease ( params : {
@@ -58,13 +57,21 @@ export interface Releaser {
5857 draft : boolean | undefined ;
5958 prerelease : boolean | undefined ;
6059 discussion_category_name : string | undefined ;
61- generate_release_notes : boolean | undefined ;
6260 } ) : Promise < { data : Release } > ;
6361
6462 allReleases ( params : {
6563 owner : string ;
6664 repo : string ;
6765 } ) : AsyncIterableIterator < { data : Release [ ] } > ;
66+
67+ getLatestTag ( params : {
68+ owner : string ;
69+ repo : string ;
70+ } ) : Promise < undefined | string > ;
71+
72+ generateReleaseBody (
73+ params : Parameters < GitHub [ "rest" ] [ "repos" ] [ "generateReleaseNotes" ] > [ 0 ]
74+ ) : Promise < string > ;
6875}
6976
7077export class GitHubReleaser implements Releaser {
@@ -91,9 +98,11 @@ export class GitHubReleaser implements Releaser {
9198 prerelease : boolean | undefined ;
9299 target_commitish : string | undefined ;
93100 discussion_category_name : string | undefined ;
94- generate_release_notes : boolean | undefined ;
95101 } ) : Promise < { data : Release } > {
96- return this . github . rest . repos . createRelease ( params ) ;
102+ return this . github . rest . repos . createRelease ( {
103+ ...params ,
104+ generate_release_notes : false ,
105+ } ) ;
97106 }
98107
99108 updateRelease ( params : {
@@ -107,9 +116,11 @@ export class GitHubReleaser implements Releaser {
107116 draft : boolean | undefined ;
108117 prerelease : boolean | undefined ;
109118 discussion_category_name : string | undefined ;
110- generate_release_notes : boolean | undefined ;
111119 } ) : Promise < { data : Release } > {
112- return this . github . rest . repos . updateRelease ( params ) ;
120+ return this . github . rest . repos . updateRelease ( {
121+ ...params ,
122+ generate_release_notes : false ,
123+ } ) ;
113124 }
114125
115126 allReleases ( params : {
@@ -121,6 +132,41 @@ export class GitHubReleaser implements Releaser {
121132 this . github . rest . repos . listReleases . endpoint . merge ( updatedParams )
122133 ) ;
123134 }
135+
136+ async getLatestTag ( params : {
137+ owner : string ;
138+ repo : string ;
139+ } ) : Promise < undefined | string > {
140+ try {
141+ const release = await this . github . rest . repos . getLatestRelease ( params ) ;
142+
143+ if ( ! release ?. data ) {
144+ return ;
145+ }
146+
147+ return release . data . tag_name ;
148+ } catch ( e ) {
149+ console . error ( e ) ;
150+
151+ return ;
152+ }
153+ }
154+
155+ async generateReleaseBody (
156+ params : Parameters < GitHub [ "rest" ] [ "repos" ] [ "generateReleaseNotes" ] > [ 0 ]
157+ ) : Promise < string > {
158+ try {
159+ const { data } = await this . github . rest . repos . generateReleaseNotes ( params ) ;
160+
161+ if ( ! data . body ) {
162+ throw new Error ( "No release body generated" ) ;
163+ }
164+
165+ return data . body ;
166+ } catch ( e ) {
167+ throw e ;
168+ }
169+ }
124170}
125171
126172export const asset = ( path : string ) : ReleaseAsset => {
@@ -196,8 +242,38 @@ export const release = async (
196242 ? config . github_ref . replace ( "refs/tags/" , "" )
197243 : "" ) ;
198244
245+ const previous_tag = config . input_previous_tag ;
199246 const discussion_category_name = config . input_discussion_category_name ;
200247 const generate_release_notes = config . input_generate_release_notes ;
248+
249+ const latestTag : string | undefined = ! previous_tag
250+ ? await releaser . getLatestTag ( {
251+ owner,
252+ repo,
253+ } )
254+ : undefined ;
255+
256+ if ( latestTag ) {
257+ console . log ( `Latest tag related to a release is ${ latestTag } ` ) ;
258+ }
259+
260+ const tag_name = tag ;
261+
262+ let body : string = generate_release_notes
263+ ? await releaser . generateReleaseBody ( {
264+ owner,
265+ repo,
266+ tag_name,
267+ previous_tag_name : previous_tag || latestTag ,
268+ } )
269+ : "" ;
270+
271+ if ( generate_release_notes && previous_tag || latestTag ) {
272+ console . log ( `Will generate release notes using ${ previous_tag || latestTag } as previous tag` ) ;
273+ }
274+
275+ body = body ? `${ body } \n` : "" ;
276+
201277 try {
202278 // you can't get a an existing draft by tag
203279 // so we must find one in the list of all releases
@@ -232,19 +308,20 @@ export const release = async (
232308 target_commitish = existingRelease . data . target_commitish ;
233309 }
234310
235- const tag_name = tag ;
236311 const name = config . input_name || existingRelease . data . name || tag ;
237312 // revisit: support a new body-concat-strategy input for accumulating
238313 // body parts as a release gets updated. some users will likely want this while
239314 // others won't previously this was duplicating content for most which
240315 // no one wants
241316 const workflowBody = releaseBody ( config ) || "" ;
242317 const existingReleaseBody = existingRelease . data . body || "" ;
243- let body : string ;
318+
244319 if ( config . input_append_body && workflowBody && existingReleaseBody ) {
245- body = existingReleaseBody + "\n" + workflowBody ;
320+ console . log ( '➕ Appending existing release body' ) ;
321+ body = body + existingReleaseBody + "\n" + workflowBody ;
246322 } else {
247- body = workflowBody || existingReleaseBody ;
323+ console . log ( `➕ Using ${ workflowBody ? 'workflow body' : 'existing release body' } ` ) ;
324+ body = body + ( workflowBody || existingReleaseBody ) ;
248325 }
249326
250327 const draft =
@@ -267,14 +344,19 @@ export const release = async (
267344 draft,
268345 prerelease,
269346 discussion_category_name,
270- generate_release_notes,
271347 } ) ;
272348 return release . data ;
273349 } catch ( error ) {
274350 if ( error . status === 404 ) {
275351 const tag_name = tag ;
276352 const name = config . input_name || tag ;
277- const body = releaseBody ( config ) ;
353+ const workflowBody = releaseBody ( config ) || "" ;
354+
355+ if ( config . input_append_body && workflowBody ) {
356+ console . log ( '➕ Appending existing release body' ) ;
357+ body = body + workflowBody ;
358+ }
359+
278360 const draft = config . input_draft ;
279361 const prerelease = config . input_prerelease ;
280362 const target_commitish = config . input_target_commitish ;
@@ -296,7 +378,6 @@ export const release = async (
296378 prerelease,
297379 target_commitish,
298380 discussion_category_name,
299- generate_release_notes,
300381 } ) ;
301382 return release . data ;
302383 } catch ( error ) {
0 commit comments