fix(updates): compare prerelease versions correctly (#1220)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
This commit is contained in:
committed by
GitHub
co-authored by
Isaac Sanchez
parent
eb3f0e7f72
commit
0cfa37932e
@@ -655,16 +655,35 @@ export async function getLatestVersion() {
|
|||||||
/**
|
/**
|
||||||
* Compare semver-like version strings.
|
* Compare semver-like version strings.
|
||||||
*/
|
*/
|
||||||
|
function parseVersionForComparison(value) {
|
||||||
|
const normalized = String(value || '').replace(/^v/, '').split('+')[0];
|
||||||
|
const prereleaseIndex = normalized.indexOf('-');
|
||||||
|
const core = prereleaseIndex >= 0 ? normalized.slice(0, prereleaseIndex) : normalized;
|
||||||
|
const parts = core.split('.').map((part) => {
|
||||||
|
const parsed = Number.parseInt(part || '0', 10);
|
||||||
|
return Number.isFinite(parsed) ? parsed : 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
parts,
|
||||||
|
prerelease: prereleaseIndex >= 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function compareVersions(left, right) {
|
function compareVersions(left, right) {
|
||||||
const a = String(left || '').replace(/^v/, '').split('.').map((part) => Number.parseInt(part || '0', 10));
|
const a = parseVersionForComparison(left);
|
||||||
const b = String(right || '').replace(/^v/, '').split('.').map((part) => Number.parseInt(part || '0', 10));
|
const b = parseVersionForComparison(right);
|
||||||
const length = Math.max(a.length, b.length);
|
const length = Math.max(a.parts.length, b.parts.length);
|
||||||
|
|
||||||
for (let index = 0; index < length; index += 1) {
|
for (let index = 0; index < length; index += 1) {
|
||||||
const diff = (a[index] || 0) - (b[index] || 0);
|
const diff = (a.parts[index] || 0) - (b.parts[index] || 0);
|
||||||
if (diff !== 0) return diff;
|
if (diff !== 0) return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (a.prerelease !== b.prerelease) {
|
||||||
|
return a.prerelease ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,14 +34,16 @@ function createFetchMock() {
|
|||||||
|
|
||||||
describe('checkForUpdates', () => {
|
describe('checkForUpdates', () => {
|
||||||
let fetchMock;
|
let fetchMock;
|
||||||
|
let originalFetch;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fetchMock = createFetchMock();
|
fetchMock = createFetchMock();
|
||||||
vi.stubGlobal('fetch', fetchMock);
|
originalFetch = globalThis.fetch;
|
||||||
|
globalThis.fetch = fetchMock;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vi.unstubAllGlobals();
|
globalThis.fetch = originalFetch;
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Scenario: API says update available, npm confirms ---
|
// --- Scenario: API says update available, npm confirms ---
|
||||||
@@ -98,6 +100,21 @@ describe('checkForUpdates', () => {
|
|||||||
expect(result.available).toBe(false);
|
expect(result.available).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns available=false when npm only has a prerelease of the current version', async () => {
|
||||||
|
fetchMock
|
||||||
|
.when('api.openchamber.dev', Promise.reject(new Error('Network error')))
|
||||||
|
.when('registry.npmjs.org', {
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({
|
||||||
|
'dist-tags': { latest: '1.10.0-beta.1' },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await checkForUpdates({ currentVersion: '1.10.0' });
|
||||||
|
|
||||||
|
expect(result.available).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it('does not cross-check desktop update claims against npm', async () => {
|
it('does not cross-check desktop update claims against npm', async () => {
|
||||||
fetchMock
|
fetchMock
|
||||||
.when('api.openchamber.dev', {
|
.when('api.openchamber.dev', {
|
||||||
|
|||||||
Reference in New Issue
Block a user