Fix server update message not handling mutli-digit version numbers (#29436)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
7b72a6582f
Коммит
3ed209a34d
@@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {fetchAndCompareVersion} from './updates';
|
||||
|
||||
import {ItemStatus} from '../dashboard.type';
|
||||
|
||||
jest.mock('mattermost-redux/client', () => ({
|
||||
Client4: {
|
||||
getBaseRoute: jest.fn(() => 'http://localhost/api/v4'),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('fetchAndCompareVersion', () => {
|
||||
beforeEach(() => {
|
||||
global.fetch = jest.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('should return major update available', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValue({
|
||||
json: jest.fn().mockResolvedValue({tag_name: 'v9.1.2', body: 'New major version available'}),
|
||||
});
|
||||
|
||||
const formatMessage = jest.fn(({defaultMessage}) => defaultMessage);
|
||||
const result = await fetchAndCompareVersion('5.6.0', formatMessage);
|
||||
|
||||
expect(result.type).toBe('Major');
|
||||
expect(result.description).toBe('New major version available');
|
||||
expect(result.status).toBe(ItemStatus.ERROR);
|
||||
});
|
||||
|
||||
it('should return major update available - single to double digit', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValue({
|
||||
json: jest.fn().mockResolvedValue({tag_name: 'v10.0.0', body: 'New major version available'}),
|
||||
});
|
||||
|
||||
const formatMessage = jest.fn(({defaultMessage}) => defaultMessage);
|
||||
const result = await fetchAndCompareVersion('9.1.0', formatMessage);
|
||||
|
||||
expect(result.type).toBe('Major');
|
||||
expect(result.description).toBe('New major version available');
|
||||
expect(result.status).toBe(ItemStatus.ERROR);
|
||||
});
|
||||
|
||||
it('should return minor update available', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValue({
|
||||
json: jest.fn().mockResolvedValue({tag_name: 'v9.2.0', body: 'New minor version available'}),
|
||||
});
|
||||
|
||||
const formatMessage = jest.fn(({defaultMessage}) => defaultMessage);
|
||||
const result = await fetchAndCompareVersion('9.1.0', formatMessage);
|
||||
|
||||
expect(result.type).toBe('Minor');
|
||||
expect(result.description).toBe('New minor version available');
|
||||
expect(result.status).toBe(ItemStatus.WARNING);
|
||||
});
|
||||
|
||||
it('should return minor update available - single to double digit', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValue({
|
||||
json: jest.fn().mockResolvedValue({tag_name: 'v9.11.0', body: 'New minor version available'}),
|
||||
});
|
||||
|
||||
const formatMessage = jest.fn(({defaultMessage}) => defaultMessage);
|
||||
const result = await fetchAndCompareVersion('9.5.0', formatMessage);
|
||||
|
||||
expect(result.type).toBe('Minor');
|
||||
expect(result.description).toBe('New minor version available');
|
||||
expect(result.status).toBe(ItemStatus.WARNING);
|
||||
});
|
||||
|
||||
it('should return patch update available', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValue({
|
||||
json: jest.fn().mockResolvedValue({tag_name: 'v9.1.1', body: 'New patch version available'}),
|
||||
});
|
||||
|
||||
const formatMessage = jest.fn(({defaultMessage}) => defaultMessage);
|
||||
const result = await fetchAndCompareVersion('9.1.0', formatMessage);
|
||||
|
||||
expect(result.type).toBe('Patch');
|
||||
expect(result.description).toBe('New patch version available');
|
||||
expect(result.status).toBe(ItemStatus.INFO);
|
||||
});
|
||||
|
||||
it('should return patch update available - single to double digit', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValue({
|
||||
json: jest.fn().mockResolvedValue({tag_name: 'v9.1.11', body: 'New patch version available'}),
|
||||
});
|
||||
|
||||
const formatMessage = jest.fn(({defaultMessage}) => defaultMessage);
|
||||
const result = await fetchAndCompareVersion('9.1.4', formatMessage);
|
||||
|
||||
expect(result.type).toBe('Patch');
|
||||
expect(result.description).toBe('New patch version available');
|
||||
expect(result.status).toBe(ItemStatus.INFO);
|
||||
});
|
||||
|
||||
it('should return no update available', async () => {
|
||||
(global.fetch as jest.Mock).mockResolvedValue({
|
||||
json: jest.fn().mockResolvedValue({tag_name: 'v9.1.0', body: 'No new version available'}),
|
||||
});
|
||||
|
||||
const formatMessage = jest.fn(({defaultMessage}) => defaultMessage);
|
||||
const result = await fetchAndCompareVersion('9.1.0', formatMessage);
|
||||
|
||||
expect(result.type).toBe('');
|
||||
expect(result.description).toBe('No new version available');
|
||||
expect(result.status).toBe(ItemStatus.OK);
|
||||
});
|
||||
});
|
||||
@@ -18,55 +18,7 @@ const testServerVersion = async (
|
||||
formatMessage: ReturnType<typeof useIntl>['formatMessage'],
|
||||
options: Options,
|
||||
) => {
|
||||
const fetchVersion = async (
|
||||
installedVersion: string,
|
||||
formatMessage: ReturnType<typeof useIntl>['formatMessage'],
|
||||
) => {
|
||||
const result = await fetch(`${Client4.getBaseRoute()}/latest_version`).then((result) => result.json());
|
||||
|
||||
if (result.tag_name) {
|
||||
const sanitizedVersion = result.tag_name.startsWith('v') ? result.tag_name.slice(1) : result.tag_name;
|
||||
const newVersionParts = sanitizedVersion.split('.');
|
||||
const installedVersionParts = installedVersion.split('.').slice(0, 3);
|
||||
|
||||
// quick general check if a newer version is available
|
||||
let type = '';
|
||||
let status: ItemStatus = ItemStatus.OK;
|
||||
|
||||
if (newVersionParts.join('') > installedVersionParts.join('')) {
|
||||
// get correct values to be inserted into the accordion item
|
||||
switch (true) {
|
||||
case newVersionParts[0] > installedVersionParts[0]:
|
||||
type = formatMessage({
|
||||
id: 'admin.reporting.workspace_optimization.updates.server_version.update_type.major',
|
||||
defaultMessage: 'Major',
|
||||
});
|
||||
status = ItemStatus.ERROR;
|
||||
break;
|
||||
case newVersionParts[1] > installedVersionParts[1]:
|
||||
type = formatMessage({
|
||||
id: 'admin.reporting.workspace_optimization.updates.server_version.update_type.minor',
|
||||
defaultMessage: 'Minor',
|
||||
});
|
||||
status = ItemStatus.WARNING;
|
||||
break;
|
||||
case newVersionParts[2] > installedVersionParts[2]:
|
||||
type = formatMessage({
|
||||
id: 'admin.reporting.workspace_optimization.updates.server_version.update_type.patch',
|
||||
defaultMessage: 'Patch',
|
||||
});
|
||||
status = ItemStatus.INFO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {type, description: result.body, status};
|
||||
}
|
||||
|
||||
return {type: '', description: '', status: ItemStatus.OK};
|
||||
};
|
||||
|
||||
const serverVersion = await fetchVersion(options.installedVersion, formatMessage);
|
||||
const serverVersion = await fetchAndCompareVersion(options.installedVersion, formatMessage);
|
||||
return {
|
||||
id: 'server_version',
|
||||
title: formatMessage({
|
||||
@@ -85,6 +37,54 @@ const testServerVersion = async (
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchAndCompareVersion = async (
|
||||
installedVersion: string,
|
||||
formatMessage: ReturnType<typeof useIntl>['formatMessage'],
|
||||
) => {
|
||||
const result = await fetch(`${Client4.getBaseRoute()}/latest_version`).then((result) => result.json());
|
||||
|
||||
if (result.tag_name) {
|
||||
const sanitizedVersion = result.tag_name.startsWith('v') ? result.tag_name.slice(1) : result.tag_name;
|
||||
const newVersionParts = sanitizedVersion.split('.');
|
||||
const installedVersionParts = installedVersion.split('.').slice(0, 3);
|
||||
|
||||
// quick general check if a newer version is available
|
||||
let type = '';
|
||||
let status: ItemStatus = ItemStatus.OK;
|
||||
|
||||
if (sanitizedVersion.localeCompare(installedVersion, undefined, {numeric: true, sensitivity: 'base'}) > 0) {
|
||||
// get correct values to be inserted into the accordion item
|
||||
switch (true) {
|
||||
case Number(newVersionParts[0]) > Number(installedVersionParts[0]):
|
||||
type = formatMessage({
|
||||
id: 'admin.reporting.workspace_optimization.updates.server_version.update_type.major',
|
||||
defaultMessage: 'Major',
|
||||
});
|
||||
status = ItemStatus.ERROR;
|
||||
break;
|
||||
case Number(newVersionParts[1]) > Number(installedVersionParts[1]):
|
||||
type = formatMessage({
|
||||
id: 'admin.reporting.workspace_optimization.updates.server_version.update_type.minor',
|
||||
defaultMessage: 'Minor',
|
||||
});
|
||||
status = ItemStatus.WARNING;
|
||||
break;
|
||||
case Number(newVersionParts[2]) > Number(installedVersionParts[2]):
|
||||
type = formatMessage({
|
||||
id: 'admin.reporting.workspace_optimization.updates.server_version.update_type.patch',
|
||||
defaultMessage: 'Patch',
|
||||
});
|
||||
status = ItemStatus.INFO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {type, description: result.body, status};
|
||||
}
|
||||
|
||||
return {type: '', description: '', status: ItemStatus.OK};
|
||||
};
|
||||
|
||||
export const runUpdateChecks = async (
|
||||
config: Partial<AdminConfig>,
|
||||
formatMessage: ReturnType<typeof useIntl>['formatMessage'],
|
||||
|
||||
Ссылка в новой задаче
Block a user