mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-04-03 15:26:16 +02:00
fix(Updates): avoid issues with stale cache when checking latest version
This commit is contained in:
parent
76ac713406
commit
a49322b63b
|
|
@ -324,10 +324,12 @@ export class SystemService {
|
||||||
throw new Error('Invalid response from GitHub API')
|
throw new Error('Invalid response from GitHub API')
|
||||||
}
|
}
|
||||||
|
|
||||||
const latestVersion = response.data.tag_name.replace(/^v/, '') // Remove leading 'v' if present
|
const latestVersion = response.data.tag_name.replace(/^v/, '').trim() // Remove leading 'v' and whitespace
|
||||||
logger.info(`Current version: ${currentVersion}, Latest version: ${latestVersion}`)
|
logger.info(`Current version: ${currentVersion}, Latest version: ${latestVersion}`)
|
||||||
|
|
||||||
const updateAvailable = process.env.NODE_ENV === 'development' ? false : latestVersion !== currentVersion
|
const updateAvailable = process.env.NODE_ENV === 'development'
|
||||||
|
? false
|
||||||
|
: this.isNewerVersion(latestVersion, currentVersion.trim())
|
||||||
|
|
||||||
// Cache the results in KVStore for frontend checks
|
// Cache the results in KVStore for frontend checks
|
||||||
await KVStore.setValue('system.updateAvailable', updateAvailable.toString())
|
await KVStore.setValue('system.updateAvailable', updateAvailable.toString())
|
||||||
|
|
@ -463,4 +465,27 @@ export class SystemService {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two semantic version strings to determine if the first is newer than the second.
|
||||||
|
* @param version1 - The version to check (e.g., "1.25.0")
|
||||||
|
* @param version2 - The current version (e.g., "1.24.0")
|
||||||
|
* @returns true if version1 is newer than version2
|
||||||
|
*/
|
||||||
|
private isNewerVersion(version1: string, version2: string): boolean {
|
||||||
|
const v1Parts = version1.split('.').map((part) => parseInt(part, 10))
|
||||||
|
const v2Parts = version2.split('.').map((part) => parseInt(part, 10))
|
||||||
|
|
||||||
|
const maxLength = Math.max(v1Parts.length, v2Parts.length)
|
||||||
|
|
||||||
|
for (let i = 0; i < maxLength; i++) {
|
||||||
|
const v1Part = v1Parts[i] || 0
|
||||||
|
const v2Part = v2Parts[i] || 0
|
||||||
|
|
||||||
|
if (v1Part > v2Part) return true
|
||||||
|
if (v1Part < v2Part) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false // Versions are equal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ function ContentUpdatesSection() {
|
||||||
addNotification({ type: 'success', message: `Started ${succeeded} update(s)` })
|
addNotification({ type: 'success', message: `Started ${succeeded} update(s)` })
|
||||||
}
|
}
|
||||||
if (failed > 0) {
|
if (failed > 0) {
|
||||||
addNotification({ type: 'warning', message: `${failed} update(s) could not be started` })
|
addNotification({ type: 'error', message: `${failed} update(s) could not be started` })
|
||||||
}
|
}
|
||||||
// Remove successful updates from the list
|
// Remove successful updates from the list
|
||||||
const successIds = new Set(result.results.filter((r) => r.success).map((r) => r.resource_id))
|
const successIds = new Set(result.results.filter((r) => r.success).map((r) => r.resource_id))
|
||||||
|
|
@ -230,6 +230,7 @@ export default function SystemUpdatePage(props: {
|
||||||
const [showLogs, setShowLogs] = useState(false)
|
const [showLogs, setShowLogs] = useState(false)
|
||||||
const [logs, setLogs] = useState<string>('')
|
const [logs, setLogs] = useState<string>('')
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
|
const [versionInfo, setVersionInfo] = useState(props.system)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isUpdating) return
|
if (!isUpdating) return
|
||||||
|
|
@ -311,6 +312,34 @@ export default function SystemUpdatePage(props: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const checkVersionMutation = useMutation({
|
||||||
|
mutationKey: ['checkLatestVersion'],
|
||||||
|
mutationFn: () => api.checkLatestVersion(true),
|
||||||
|
onSuccess: (data) => {
|
||||||
|
if (data) {
|
||||||
|
setVersionInfo({
|
||||||
|
updateAvailable: data.updateAvailable,
|
||||||
|
latestVersion: data.latestVersion,
|
||||||
|
currentVersion: data.currentVersion,
|
||||||
|
})
|
||||||
|
if (data.updateAvailable) {
|
||||||
|
addNotification({
|
||||||
|
type: 'success',
|
||||||
|
message: `Update available: ${data.latestVersion}`,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addNotification({ type: 'success', message: 'System is up to date' })
|
||||||
|
}
|
||||||
|
setError(null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: (error: any) => {
|
||||||
|
const errorMessage = error?.message || 'Failed to check for updates'
|
||||||
|
setError(errorMessage)
|
||||||
|
addNotification({ type: 'error', message: errorMessage })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const getProgressBarColor = () => {
|
const getProgressBarColor = () => {
|
||||||
if (updateStatus?.stage === 'error') return 'bg-desert-red'
|
if (updateStatus?.stage === 'error') return 'bg-desert-red'
|
||||||
if (updateStatus?.stage === 'complete') return 'bg-desert-olive'
|
if (updateStatus?.stage === 'complete') return 'bg-desert-olive'
|
||||||
|
|
@ -415,10 +444,10 @@ export default function SystemUpdatePage(props: {
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p className="text-sm text-desert-stone mb-1">Current Version</p>
|
<p className="text-sm text-desert-stone mb-1">Current Version</p>
|
||||||
<p className="text-xl font-bold text-desert-green">
|
<p className="text-xl font-bold text-desert-green">
|
||||||
{props.system.currentVersion}
|
{versionInfo.currentVersion}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{props.system.updateAvailable && (
|
{versionInfo.updateAvailable && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<svg
|
<svg
|
||||||
|
|
@ -438,7 +467,7 @@ export default function SystemUpdatePage(props: {
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<p className="text-sm text-desert-stone mb-1">Latest Version</p>
|
<p className="text-sm text-desert-stone mb-1">Latest Version</p>
|
||||||
<p className="text-xl font-bold text-desert-olive">
|
<p className="text-xl font-bold text-desert-olive">
|
||||||
{props.system.latestVersion}
|
{versionInfo.latestVersion}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
@ -464,15 +493,16 @@ export default function SystemUpdatePage(props: {
|
||||||
size="lg"
|
size="lg"
|
||||||
icon="IconDownload"
|
icon="IconDownload"
|
||||||
onClick={handleStartUpdate}
|
onClick={handleStartUpdate}
|
||||||
disabled={!props.system.updateAvailable}
|
disabled={!versionInfo.updateAvailable}
|
||||||
>
|
>
|
||||||
{props.system.updateAvailable ? 'Start Update' : 'No Update Available'}
|
{versionInfo.updateAvailable ? 'Start Update' : 'No Update Available'}
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
<StyledButton
|
<StyledButton
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="lg"
|
size="lg"
|
||||||
icon="IconRefresh"
|
icon="IconRefresh"
|
||||||
onClick={() => window.location.reload()}
|
onClick={() => checkVersionMutation.mutate()}
|
||||||
|
loading={checkVersionMutation.isPending}
|
||||||
>
|
>
|
||||||
Check Again
|
Check Again
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user