@@ -252,7 +252,12 @@ async function collectAssets(artifactRoot) {
252252 const filePath = normalisedPath ;
253253 const artifactDir = path . relative ( artifactRoot , path . dirname ( filePath ) ) ;
254254 if ( isAutoUpdateSupportFile ( fileName ) ) {
255- updateSupportFiles . push ( { filePath, artifactDir } ) ;
255+ updateSupportFiles . push ( {
256+ filePath,
257+ artifactDir,
258+ assetName : path . basename ( filePath ) ,
259+ upload : true ,
260+ } ) ;
256261 continue ;
257262 }
258263
@@ -275,6 +280,7 @@ async function collectAssets(artifactRoot) {
275280 format : detectFormat ( fileName ) ,
276281 sha512,
277282 size,
283+ assetName : fileName ,
278284 } ) ;
279285 }
280286 }
@@ -296,6 +302,74 @@ async function collectAssets(artifactRoot) {
296302 return { releaseAssets, updateSupportFiles } ;
297303}
298304
305+ function normaliseWindowsChannelName ( arch ) {
306+ if ( ! arch ) {
307+ return null ;
308+ }
309+ const normalised = arch . toLowerCase ( ) ;
310+ if ( [ 'x64' , 'ia32' , 'arm64' ] . includes ( normalised ) ) {
311+ return `win32-${ normalised } ` ;
312+ }
313+ return `win32-${ normalised . replace ( / [ ^ a - z 0 - 9 ] + / gi, '-' ) } ` ;
314+ }
315+
316+ async function prepareMetadataUploads ( { releaseAssets, updateSupportFiles } ) {
317+ if ( updateSupportFiles . length === 0 ) {
318+ return ;
319+ }
320+
321+ const releaseAssetsByDir = new Map ( ) ;
322+ for ( const asset of releaseAssets ) {
323+ if ( ! releaseAssetsByDir . has ( asset . artifactDir ) ) {
324+ releaseAssetsByDir . set ( asset . artifactDir , { assets : [ ] , arch : asset . arch } ) ;
325+ }
326+ const entry = releaseAssetsByDir . get ( asset . artifactDir ) ;
327+ entry . assets . push ( asset ) ;
328+ if ( ! entry . arch && asset . arch ) {
329+ entry . arch = asset . arch ;
330+ }
331+ }
332+
333+ const windowsMetadata = updateSupportFiles . filter ( ( file ) => {
334+ const name = path . basename ( file . filePath ) . toLowerCase ( ) ;
335+ return name === 'latest.yml' && file . artifactDir . startsWith ( 'docforge-windows-' ) ;
336+ } ) ;
337+
338+ if ( windowsMetadata . length === 0 ) {
339+ return ;
340+ }
341+
342+ const canonical =
343+ windowsMetadata . find ( ( file ) => {
344+ const info = releaseAssetsByDir . get ( file . artifactDir ) ;
345+ return info ?. arch === 'x64' ;
346+ } ) ?? windowsMetadata [ 0 ] ;
347+
348+ for ( const file of windowsMetadata ) {
349+ const info = releaseAssetsByDir . get ( file . artifactDir ) ;
350+ const channelName = normaliseWindowsChannelName ( info ?. arch ?? 'windows' ) ;
351+ if ( ! channelName ) {
352+ continue ;
353+ }
354+ const aliasName = `${ channelName } .yml` ;
355+ const aliasPath = path . join ( path . dirname ( file . filePath ) , aliasName ) ;
356+ await fs . copyFile ( file . filePath , aliasPath ) ;
357+ updateSupportFiles . push ( {
358+ filePath : aliasPath ,
359+ artifactDir : file . artifactDir ,
360+ assetName : aliasName ,
361+ upload : true ,
362+ } ) ;
363+
364+ file . assetName = path . basename ( file . filePath ) ;
365+ if ( file === canonical ) {
366+ file . upload = true ;
367+ } else {
368+ file . upload = false ;
369+ }
370+ }
371+ }
372+
299373async function updateMetadataFiles ( metadataFiles , releaseAssets ) {
300374 if ( metadataFiles . length === 0 ) {
301375 return ;
@@ -550,9 +624,26 @@ async function main() {
550624 const releaseNotes = sections . join ( '\n' ) . replace ( / \n { 3 , } / g, '\n\n' ) ;
551625 await fs . writeFile ( outputPath , `${ releaseNotes } \n` , 'utf8' ) ;
552626
627+ await prepareMetadataUploads ( { releaseAssets, updateSupportFiles } ) ;
628+ updateSupportFiles . sort ( ( a , b ) => a . filePath . localeCompare ( b . filePath ) ) ;
629+
553630 const manifestEntries = [
554- ...releaseAssets . map ( ( asset ) => path . relative ( process . cwd ( ) , asset . filePath ) ) ,
555- ...updateSupportFiles . map ( ( file ) => path . relative ( process . cwd ( ) , file . filePath ) ) ,
631+ ...releaseAssets . map ( ( asset ) => {
632+ const relative = path . relative ( process . cwd ( ) , asset . filePath ) ;
633+ if ( asset . assetName && path . basename ( asset . filePath ) !== asset . assetName ) {
634+ return `${ relative } #${ asset . assetName } ` ;
635+ }
636+ return relative ;
637+ } ) ,
638+ ...updateSupportFiles
639+ . filter ( ( file ) => file . upload !== false )
640+ . map ( ( file ) => {
641+ const relative = path . relative ( process . cwd ( ) , file . filePath ) ;
642+ if ( file . assetName && path . basename ( file . filePath ) !== file . assetName ) {
643+ return `${ relative } #${ file . assetName } ` ;
644+ }
645+ return relative ;
646+ } ) ,
556647 ] ;
557648 const manifest = manifestEntries . join ( '\n' ) ;
558649 await fs . writeFile ( filesOutputPath , `${ manifest } \n` , 'utf8' ) ;
0 commit comments