@@ -302,6 +302,145 @@ describe('releases/github', () => {
302302 } )
303303 expect ( tag ) . toBeNull ( )
304304 } )
305+
306+ it ( 'should sort by published_at and return most recent release' , async ( ) => {
307+ // Mock releases with same prefix but different published_at times.
308+ const releasesOutOfOrder = [
309+ {
310+ assets : [ { name : 'node-darwin-arm64' } ] ,
311+ published_at : '2026-01-12T10:00:00Z' ,
312+ tag_name : 'node-smol-20260112-d8601d1' ,
313+ } ,
314+ {
315+ assets : [ { name : 'node-darwin-arm64' } ] ,
316+ published_at : '2026-01-12T15:30:00Z' , // Most recent
317+ tag_name : 'node-smol-20260112-9ec3865' ,
318+ } ,
319+ {
320+ assets : [ { name : 'node-darwin-arm64' } ] ,
321+ published_at : '2026-01-12T08:00:00Z' ,
322+ tag_name : 'node-smol-20260112-abc1234' ,
323+ } ,
324+ ]
325+
326+ vi . mocked ( httpRequest ) . mockResolvedValue (
327+ createMockHttpResponse (
328+ Buffer . from ( JSON . stringify ( releasesOutOfOrder ) ) ,
329+ true ,
330+ 200 ,
331+ ) ,
332+ )
333+
334+ const tag = await getLatestRelease ( 'node-smol-' , SOCKET_BTM_REPO , {
335+ quiet : true ,
336+ } )
337+
338+ // Should return the release with the latest published_at time.
339+ expect ( tag ) . toBe ( 'node-smol-20260112-9ec3865' )
340+ } )
341+
342+ it ( 'should handle multiple releases on same day with different times' , async ( ) => {
343+ // Simulate scenario where GitHub API returns releases in arbitrary order.
344+ const sameDay = [
345+ {
346+ assets : [ { name : 'yoga-sync-abc.mjs' } ] ,
347+ published_at : '2026-01-12T09:15:22Z' ,
348+ tag_name : 'yoga-layout-20260112-first' ,
349+ } ,
350+ {
351+ assets : [ { name : 'yoga-sync-xyz.mjs' } ] ,
352+ published_at : '2026-01-12T14:45:10Z' , // Latest
353+ tag_name : 'yoga-layout-20260112-latest' ,
354+ } ,
355+ {
356+ assets : [ { name : 'yoga-sync-def.mjs' } ] ,
357+ published_at : '2026-01-12T11:30:00Z' ,
358+ tag_name : 'yoga-layout-20260112-middle' ,
359+ } ,
360+ ]
361+
362+ vi . mocked ( httpRequest ) . mockResolvedValue (
363+ createMockHttpResponse ( Buffer . from ( JSON . stringify ( sameDay ) ) , true , 200 ) ,
364+ )
365+
366+ const tag = await getLatestRelease ( 'yoga-layout-' , SOCKET_BTM_REPO , {
367+ quiet : true ,
368+ } )
369+
370+ expect ( tag ) . toBe ( 'yoga-layout-20260112-latest' )
371+ } )
372+
373+ it ( 'should sort by published_at even when API returns newest first' , async ( ) => {
374+ // Test that we don't rely on API ordering.
375+ const releasesNewestFirst = [
376+ {
377+ assets : [ { name : 'models-data.tar.gz' } ] ,
378+ published_at : '2026-01-15T12:00:00Z' , // Newest
379+ tag_name : 'models-20260115-newest' ,
380+ } ,
381+ {
382+ assets : [ { name : 'models-data.tar.gz' } ] ,
383+ published_at : '2026-01-14T12:00:00Z' ,
384+ tag_name : 'models-20260114-older' ,
385+ } ,
386+ {
387+ assets : [ { name : 'models-data.tar.gz' } ] ,
388+ published_at : '2026-01-13T12:00:00Z' ,
389+ tag_name : 'models-20260113-oldest' ,
390+ } ,
391+ ]
392+
393+ vi . mocked ( httpRequest ) . mockResolvedValue (
394+ createMockHttpResponse (
395+ Buffer . from ( JSON . stringify ( releasesNewestFirst ) ) ,
396+ true ,
397+ 200 ,
398+ ) ,
399+ )
400+
401+ const tag = await getLatestRelease ( 'models-' , SOCKET_BTM_REPO , {
402+ quiet : true ,
403+ } )
404+
405+ expect ( tag ) . toBe ( 'models-20260115-newest' )
406+ } )
407+
408+ it ( 'should sort by published_at with asset pattern filtering' , async ( ) => {
409+ // Multiple releases matching prefix, but only some have matching assets.
410+ const releasesWithAssets = [
411+ {
412+ assets : [ { name : 'node-linux-x64' } ] , // No matching asset
413+ published_at : '2026-01-12T16:00:00Z' ,
414+ tag_name : 'node-smol-20260112-no-match' ,
415+ } ,
416+ {
417+ assets : [ { name : 'node-darwin-arm64' } ] , // Matching asset, oldest
418+ published_at : '2026-01-12T10:00:00Z' ,
419+ tag_name : 'node-smol-20260112-older' ,
420+ } ,
421+ {
422+ assets : [ { name : 'node-darwin-arm64' } ] , // Matching asset, newest
423+ published_at : '2026-01-12T14:00:00Z' ,
424+ tag_name : 'node-smol-20260112-newer' ,
425+ } ,
426+ ]
427+
428+ vi . mocked ( httpRequest ) . mockResolvedValue (
429+ createMockHttpResponse (
430+ Buffer . from ( JSON . stringify ( releasesWithAssets ) ) ,
431+ true ,
432+ 200 ,
433+ ) ,
434+ )
435+
436+ const tag = await getLatestRelease ( 'node-smol-' , SOCKET_BTM_REPO , {
437+ assetPattern : 'node-darwin-*' ,
438+ quiet : true ,
439+ } )
440+
441+ // Should return the newest release that has the matching asset.
442+ expect ( tag ) . toBe ( 'node-smol-20260112-newer' )
443+ } )
305444 } )
306445
307446 describe ( 'getReleaseAssetUrl' , ( ) => {
0 commit comments