Bläddra i källkod

fix: trim release notes to recent versions

paoloanzn 2 månader sedan
förälder
incheckning
4d728a1b19

+ 19 - 9
src/commands/release-notes/release-notes.ts

@@ -3,8 +3,10 @@ import {
   CHANGELOG_URL,
   fetchAndStoreChangelog,
   getAllReleaseNotes,
+  getRecentReleaseNoteGroups,
   getStoredChangelog,
 } from '../../utils/releaseNotes.js'
+import { getGlobalConfig } from '../../utils/config.js'
 
 function formatReleaseNotes(notes: Array<[string, string[]]>): string {
   return notes
@@ -18,7 +20,7 @@ function formatReleaseNotes(notes: Array<[string, string[]]>): string {
 
 export async function call(): Promise<LocalCommandResult> {
   // Try to fetch the latest changelog with a 500ms timeout
-  let freshNotes: Array<[string, string[]]> = []
+  let changelog = ''
 
   try {
     const timeoutPromise = new Promise<void>((_, reject) => {
@@ -26,20 +28,28 @@ export async function call(): Promise<LocalCommandResult> {
     })
 
     await Promise.race([fetchAndStoreChangelog(), timeoutPromise])
-    freshNotes = getAllReleaseNotes(await getStoredChangelog())
+    changelog = await getStoredChangelog()
   } catch {
     // Either fetch failed or timed out - just use cached notes
   }
 
-  // If we have fresh notes from the quick fetch, use those
-  if (freshNotes.length > 0) {
-    return { type: 'text', value: formatReleaseNotes(freshNotes) }
+  if (!changelog) {
+    changelog = await getStoredChangelog()
   }
 
-  // Otherwise check cached notes
-  const cachedNotes = getAllReleaseNotes(await getStoredChangelog())
-  if (cachedNotes.length > 0) {
-    return { type: 'text', value: formatReleaseNotes(cachedNotes) }
+  const recentNotes = getRecentReleaseNoteGroups(
+    MACRO.VERSION,
+    getGlobalConfig().lastReleaseNotesSeen,
+    changelog,
+    3,
+  )
+  if (recentNotes.length > 0) {
+    return { type: 'text', value: formatReleaseNotes(recentNotes) }
+  }
+
+  const latestNotes = getAllReleaseNotes(changelog).slice(-3).reverse()
+  if (latestNotes.length > 0) {
+    return { type: 'text', value: formatReleaseNotes(latestNotes) }
   }
 
   // Nothing available, show link

+ 1 - 1
src/components/LogoV2/LogoV2.tsx

@@ -74,7 +74,7 @@ export function LogoV2() {
   const config = getGlobalConfig();
   let changelog;
   try {
-    changelog = getRecentReleaseNotesSync(3);
+    changelog = getRecentReleaseNotesSync(3, MACRO.VERSION, config.lastReleaseNotesSeen);
   } catch {
     changelog = [];
   }

+ 13 - 24
src/utils/logoV2Utils.ts

@@ -9,7 +9,10 @@ import {
   truncateToWidth,
   truncateToWidthNoEllipsis,
 } from './format.js'
-import { getStoredChangelogFromMemory, parseChangelog } from './releaseNotes.js'
+import {
+  getRecentReleaseNotes,
+  getStoredChangelogFromMemory,
+} from './releaseNotes.js'
 import { gt } from './semver.js'
 import { loadMessageLogs } from './sessionStorage.js'
 import { getInitialSettings } from './settings/settings.js'
@@ -309,7 +312,11 @@ export function formatModelAndBilling(
  * For ants, uses commits bundled at build time
  * For external users, uses public changelog
  */
-export function getRecentReleaseNotesSync(maxItems: number): string[] {
+export function getRecentReleaseNotesSync(
+  maxItems: number,
+  currentVersion: string = MACRO.VERSION,
+  lastSeenVersion?: string | null,
+): string[] {
   // For ants, use bundled changelog
   if (process.env.USER_TYPE === 'ant') {
     const changelog = MACRO.VERSION_CHANGELOG
@@ -325,26 +332,8 @@ export function getRecentReleaseNotesSync(maxItems: number): string[] {
     return []
   }
 
-  let parsed
-  try {
-    parsed = parseChangelog(changelog)
-  } catch {
-    return []
-  }
-
-  // Get notes from recent versions
-  const allNotes: string[] = []
-  const versions = Object.keys(parsed)
-    .sort((a, b) => (gt(a, b) ? -1 : 1))
-    .slice(0, 3) // Look at top 3 recent versions
-
-  for (const version of versions) {
-    const notes = parsed[version]
-    if (notes) {
-      allNotes.push(...notes)
-    }
-  }
-
-  // Return raw notes without filtering or premature truncation
-  return allNotes.slice(0, maxItems)
+  return getRecentReleaseNotes(currentVersion, lastSeenVersion, changelog).slice(
+    0,
+    maxItems,
+  )
 }

+ 40 - 15
src/utils/releaseNotes.ts

@@ -209,34 +209,59 @@ export function getRecentReleaseNotes(
   previousVersion: string | null | undefined,
   changelogContent: string = getStoredChangelogFromMemory(),
 ): string[] {
+  try {
+    return getRecentReleaseNoteGroups(
+      currentVersion,
+      previousVersion,
+      changelogContent,
+    )
+      .flatMap(([, notes]) => notes)
+      .filter(Boolean)
+      .slice(0, MAX_RELEASE_NOTES_SHOWN)
+  } catch (error) {
+    logError(toError(error))
+    return []
+  }
+  return []
+}
+
+export function getRecentReleaseNoteGroups(
+  currentVersion: string,
+  previousVersion: string | null | undefined,
+  changelogContent: string = getStoredChangelogFromMemory(),
+  maxVersions: number = Number.POSITIVE_INFINITY,
+): Array<[string, string[]]> {
   try {
     const releaseNotes = parseChangelog(changelogContent)
 
-    // Strip SHA from both versions to compare only the base versions
+    // Strip SHA/build metadata from both versions to compare only the base semver.
     const baseCurrentVersion = coerce(currentVersion)
     const basePreviousVersion = previousVersion ? coerce(previousVersion) : null
 
+    if (!baseCurrentVersion) {
+      return []
+    }
+
     if (
-      !basePreviousVersion ||
-      (baseCurrentVersion &&
-        gt(baseCurrentVersion.version, basePreviousVersion.version))
+      basePreviousVersion &&
+      !gt(baseCurrentVersion.version, basePreviousVersion.version)
     ) {
-      // Get all versions that are newer than the last seen version
-      return Object.entries(releaseNotes)
-        .filter(
-          ([version]) =>
-            !basePreviousVersion || gt(version, basePreviousVersion.version),
-        )
-        .sort(([versionA], [versionB]) => (gt(versionA, versionB) ? -1 : 1)) // Sort newest first
-        .flatMap(([_, notes]) => notes)
-        .filter(Boolean)
-        .slice(0, MAX_RELEASE_NOTES_SHOWN)
+      return []
     }
+
+    return Object.entries(releaseNotes)
+      .filter(
+        ([version]) =>
+          !basePreviousVersion || gt(version, basePreviousVersion.version),
+      )
+      .sort(([versionA], [versionB]) => (gt(versionA, versionB) ? -1 : 1))
+      .slice(0, maxVersions)
+      .map(([version, notes]) => [version, notes.filter(Boolean)] as [string, string[]])
+      .filter(([, notes]) => notes.length > 0)
   } catch (error) {
     logError(toError(error))
     return []
   }
-  return []
 }
 
 /**