mirror of
https://github.com/freecodexyz/free-code.git
synced 2026-10-19 01:31:25 -05:00
fix: trim release notes to recent versions
This commit is contained in:
1 parent
71bf5f24a0
commit
4d728a1b19
4 files changed
+80
-56
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
@@ -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,
|
||||
)
|
||||
}
|
||||
+47
-22
@@ -210,28 +210,14 @@ export function getRecentReleaseNotes(
|
||||
changelogContent: string = getStoredChangelogFromMemory(),
|
||||
): string[] {
|
||||
try {
|
||||
const releaseNotes = parseChangelog(changelogContent)
|
||||
|
||||
// Strip SHA from both versions to compare only the base versions
|
||||
const baseCurrentVersion = coerce(currentVersion)
|
||||
const basePreviousVersion = previousVersion ? coerce(previousVersion) : null
|
||||
|
||||
if (
|
||||
!basePreviousVersion ||
|
||||
(baseCurrentVersion &&
|
||||
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 getRecentReleaseNoteGroups(
|
||||
currentVersion,
|
||||
previousVersion,
|
||||
changelogContent,
|
||||
)
|
||||
.flatMap(([, notes]) => notes)
|
||||
.filter(Boolean)
|
||||
.slice(0, MAX_RELEASE_NOTES_SHOWN)
|
||||
} catch (error) {
|
||||
logError(toError(error))
|
||||
return []
|
||||
@@ -239,6 +225,45 @@ export function getRecentReleaseNotes(
|
||||
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/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 &&
|
||||
!gt(baseCurrentVersion.version, basePreviousVersion.version)
|
||||
) {
|
||||
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 []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all release notes as an array of [version, notes] arrays.
|
||||
* Versions are sorted with oldest first.
|
||||
|
||||
Reference in new issue
Block a user