mirror of
https://github.com/immich-app/immich.git
synced 2026-05-29 02:52:32 -04:00
feat: release candidate support
This commit is contained in:
+19
-3
@@ -16,6 +16,7 @@ class ServerVersionResponseDto {
|
||||
required this.major,
|
||||
required this.minor,
|
||||
required this.patch_,
|
||||
required this.prerelease,
|
||||
});
|
||||
|
||||
/// Major version number
|
||||
@@ -36,27 +37,40 @@ class ServerVersionResponseDto {
|
||||
/// Maximum value: 9007199254740991
|
||||
int patch_;
|
||||
|
||||
/// Pre-release version number
|
||||
///
|
||||
/// Minimum value: -9007199254740991
|
||||
/// Maximum value: 9007199254740991
|
||||
int? prerelease;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is ServerVersionResponseDto &&
|
||||
other.major == major &&
|
||||
other.minor == minor &&
|
||||
other.patch_ == patch_;
|
||||
other.patch_ == patch_ &&
|
||||
other.prerelease == prerelease;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(major.hashCode) +
|
||||
(minor.hashCode) +
|
||||
(patch_.hashCode);
|
||||
(patch_.hashCode) +
|
||||
(prerelease == null ? 0 : prerelease!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'ServerVersionResponseDto[major=$major, minor=$minor, patch_=$patch_]';
|
||||
String toString() => 'ServerVersionResponseDto[major=$major, minor=$minor, patch_=$patch_, prerelease=$prerelease]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'major'] = this.major;
|
||||
json[r'minor'] = this.minor;
|
||||
json[r'patch'] = this.patch_;
|
||||
if (this.prerelease != null) {
|
||||
json[r'prerelease'] = this.prerelease;
|
||||
} else {
|
||||
// json[r'prerelease'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -72,6 +86,7 @@ class ServerVersionResponseDto {
|
||||
major: mapValueOfType<int>(json, r'major')!,
|
||||
minor: mapValueOfType<int>(json, r'minor')!,
|
||||
patch_: mapValueOfType<int>(json, r'patch')!,
|
||||
prerelease: mapValueOfType<int>(json, r'prerelease'),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -122,6 +137,7 @@ class ServerVersionResponseDto {
|
||||
'major',
|
||||
'minor',
|
||||
'patch',
|
||||
'prerelease',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -21483,12 +21483,26 @@
|
||||
"maximum": 9007199254740991,
|
||||
"minimum": -9007199254740991,
|
||||
"type": "integer"
|
||||
},
|
||||
"prerelease": {
|
||||
"description": "Pre-release version number",
|
||||
"maximum": 9007199254740991,
|
||||
"minimum": -9007199254740991,
|
||||
"nullable": true,
|
||||
"type": "integer",
|
||||
"x-immich-history": [
|
||||
{
|
||||
"version": "v3.0.0",
|
||||
"state": "Added"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"major",
|
||||
"minor",
|
||||
"patch"
|
||||
"patch",
|
||||
"prerelease"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
||||
@@ -2074,6 +2074,8 @@ export type ServerVersionResponseDto = {
|
||||
minor: number;
|
||||
/** Patch version number */
|
||||
patch: number;
|
||||
/** Pre-release version number */
|
||||
prerelease: number | null;
|
||||
};
|
||||
export type VersionCheckStateResponseDto = {
|
||||
/** Last check timestamp */
|
||||
|
||||
Generated
+27
-20
@@ -571,8 +571,8 @@ importers:
|
||||
specifier: ^1.6.3
|
||||
version: 1.6.4
|
||||
semver:
|
||||
specifier: ^7.6.2
|
||||
version: 7.8.0
|
||||
specifier: ^7.8.1
|
||||
version: 7.8.1
|
||||
sharp:
|
||||
specifier: ^0.34.5
|
||||
version: 0.34.5
|
||||
@@ -11243,6 +11243,11 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
semver@7.8.1:
|
||||
resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
send@0.19.2:
|
||||
resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -16300,7 +16305,7 @@ snapshots:
|
||||
nopt: 5.0.0
|
||||
npmlog: 5.0.1
|
||||
rimraf: 3.0.2
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
tar: 6.2.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
@@ -17757,7 +17762,7 @@ snapshots:
|
||||
'@testing-library/dom@10.4.1':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.29.0
|
||||
'@babel/runtime': 7.29.2
|
||||
'@babel/runtime': 7.29.7
|
||||
'@types/aria-query': 5.0.4
|
||||
aria-query: 5.3.0
|
||||
dom-accessibility-api: 0.5.16
|
||||
@@ -18461,7 +18466,7 @@ snapshots:
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
debug: 4.4.3
|
||||
minimatch: 10.2.5
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
tinyglobby: 0.2.16
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
@@ -19561,7 +19566,7 @@ snapshots:
|
||||
dot-prop: 10.1.0
|
||||
env-paths: 3.0.0
|
||||
json-schema-typed: 8.0.2
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
uint8array-extras: 1.5.0
|
||||
|
||||
config-chain@1.1.13:
|
||||
@@ -19733,7 +19738,7 @@ snapshots:
|
||||
postcss-modules-scope: 3.2.1(postcss@8.5.15)
|
||||
postcss-modules-values: 4.0.0(postcss@8.5.15)
|
||||
postcss-value-parser: 4.2.0
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
optionalDependencies:
|
||||
webpack: 5.107.0(postcss@8.5.15)
|
||||
|
||||
@@ -20601,7 +20606,7 @@ snapshots:
|
||||
find-up: 5.0.0
|
||||
globals: 15.15.0
|
||||
lodash.memoize: 4.1.2
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
|
||||
eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3):
|
||||
dependencies:
|
||||
@@ -20624,7 +20629,7 @@ snapshots:
|
||||
postcss: 8.5.15
|
||||
postcss-load-config: 3.1.4(postcss@8.5.15)
|
||||
postcss-safe-parser: 7.0.1(postcss@8.5.15)
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
svelte-eslint-parser: 1.6.1(svelte@5.55.8(@typescript-eslint/types@8.59.4))
|
||||
optionalDependencies:
|
||||
svelte: 5.55.8(@typescript-eslint/types@8.59.4)
|
||||
@@ -21102,7 +21107,7 @@ snapshots:
|
||||
minimatch: 3.1.5
|
||||
node-abort-controller: 3.1.1
|
||||
schema-utils: 3.3.0
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
tapable: 2.3.3
|
||||
typescript: 5.9.3
|
||||
webpack: 5.106.0(@swc/core@1.15.33(@swc/helpers@0.5.22))(esbuild@0.28.0)(lightningcss@1.32.0)
|
||||
@@ -21538,7 +21543,7 @@ snapshots:
|
||||
|
||||
history@4.10.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
'@babel/runtime': 7.29.7
|
||||
loose-envify: 1.4.0
|
||||
resolve-pathname: 3.0.0
|
||||
tiny-invariant: 1.3.3
|
||||
@@ -22126,7 +22131,7 @@ snapshots:
|
||||
lodash.isstring: 4.0.1
|
||||
lodash.once: 4.1.1
|
||||
ms: 2.1.3
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
|
||||
just-compare@2.3.0: {}
|
||||
|
||||
@@ -22412,7 +22417,7 @@ snapshots:
|
||||
|
||||
make-dir@4.0.0:
|
||||
dependencies:
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
|
||||
maplibre-gl@5.24.0:
|
||||
dependencies:
|
||||
@@ -23247,7 +23252,7 @@ snapshots:
|
||||
|
||||
node-abi@3.92.0:
|
||||
dependencies:
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
optional: true
|
||||
|
||||
node-abort-controller@3.1.1: {}
|
||||
@@ -23288,7 +23293,7 @@ snapshots:
|
||||
graceful-fs: 4.2.11
|
||||
nopt: 9.0.0
|
||||
proc-log: 6.1.0
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
tar: 7.5.15
|
||||
tinyglobby: 0.2.16
|
||||
undici: 6.25.0
|
||||
@@ -23526,7 +23531,7 @@ snapshots:
|
||||
got: 12.6.1
|
||||
registry-auth-token: 5.1.1
|
||||
registry-url: 6.0.1
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
|
||||
package-manager-detector@1.6.0: {}
|
||||
|
||||
@@ -23914,7 +23919,7 @@ snapshots:
|
||||
cosmiconfig: 8.3.6(typescript@6.0.3)
|
||||
jiti: 1.21.7
|
||||
postcss: 8.5.15
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
webpack: 5.107.0(postcss@8.5.15)
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
@@ -24969,12 +24974,14 @@ snapshots:
|
||||
|
||||
semver-diff@4.0.0:
|
||||
dependencies:
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
|
||||
semver@6.3.1: {}
|
||||
|
||||
semver@7.8.0: {}
|
||||
|
||||
semver@7.8.1: {}
|
||||
|
||||
send@0.19.2:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
@@ -25509,7 +25516,7 @@ snapshots:
|
||||
postcss: 8.5.15
|
||||
postcss-scss: 4.0.9(postcss@8.5.15)
|
||||
postcss-selector-parser: 7.1.1
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
optionalDependencies:
|
||||
svelte: 5.55.8(@typescript-eslint/types@8.59.4)
|
||||
|
||||
@@ -26217,7 +26224,7 @@ snapshots:
|
||||
is-yarn-global: 0.4.1
|
||||
latest-version: 7.0.0
|
||||
pupa: 3.3.0
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
semver-diff: 4.0.0
|
||||
xdg-basedir: 5.1.0
|
||||
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@
|
||||
"reflect-metadata": "^0.2.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"semver": "^7.6.2",
|
||||
"semver": "^7.8.1",
|
||||
"sharp": "^0.34.5",
|
||||
"sirv": "^3.0.0",
|
||||
"socket.io": "^4.8.1",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createZodDto } from 'nestjs-zod';
|
||||
import type { SemVer } from 'semver';
|
||||
import { HistoryBuilder } from 'src/decorators';
|
||||
import { isoDatetimeToDate } from 'src/validation';
|
||||
import z from 'zod';
|
||||
|
||||
@@ -61,6 +62,7 @@ const ServerVersionResponseSchema = z
|
||||
major: z.int().describe('Major version number'),
|
||||
minor: z.int().describe('Minor version number'),
|
||||
patch: z.int().describe('Patch version number'),
|
||||
prerelease: z.int().nullable().meta(HistoryBuilder.v3().getExtensions()).describe('Pre-release version number'),
|
||||
})
|
||||
.meta({ id: 'ServerVersionResponseDto' });
|
||||
|
||||
@@ -147,7 +149,12 @@ export class ServerStorageResponseDto extends createZodDto(ServerStorageResponse
|
||||
|
||||
export class ServerVersionResponseDto extends createZodDto(ServerVersionResponseSchema) {
|
||||
static fromSemVer(value: SemVer): z.infer<typeof ServerVersionResponseSchema> {
|
||||
return { major: value.major, minor: value.minor, patch: value.patch };
|
||||
return {
|
||||
major: value.major,
|
||||
minor: value.minor,
|
||||
patch: value.patch,
|
||||
prerelease: (value.prerelease[1] as number) ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,17 @@ describe(VersionService.name, () => {
|
||||
mocks.cron.update.mockResolvedValue();
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
vitest.mock(import('src/constants.js'), async () => ({
|
||||
...(await vitest.importActual<typeof import('src/constants.js')>('src/constants.js')),
|
||||
serverVersion: new SemVer('v3.0.0'),
|
||||
}));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
vitest.unmock(import('src/constants.js'));
|
||||
});
|
||||
|
||||
it('should work', () => {
|
||||
expect(sut).toBeDefined();
|
||||
});
|
||||
@@ -66,9 +77,10 @@ describe(VersionService.name, () => {
|
||||
describe('getVersion', () => {
|
||||
it('should respond the server version', () => {
|
||||
expect(sut.getVersion()).toEqual({
|
||||
major: serverVersion.major,
|
||||
minor: serverVersion.minor,
|
||||
patch: serverVersion.patch,
|
||||
major: 3,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -131,6 +143,16 @@ describe(VersionService.name, () => {
|
||||
expect(mocks.websocket.clientBroadcast).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not notify if the version is a release candidate and we are on a stable version', async () => {
|
||||
mocks.serverInfo.getLatestRelease.mockResolvedValue(mockVersionResponse('v3.0.1-rc.1'));
|
||||
await expect(sut.handleVersionCheck()).resolves.toEqual(JobStatus.Success);
|
||||
expect(mocks.systemMetadata.set).toHaveBeenCalledWith(SystemMetadataKey.VersionCheckState, {
|
||||
checkedAt: expect.any(String),
|
||||
releaseVersion: 'v3.0.1-rc.1',
|
||||
});
|
||||
expect(mocks.websocket.clientBroadcast).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle a version check error', async () => {
|
||||
mocks.serverInfo.getLatestRelease.mockRejectedValue(new Error('Version service is down'));
|
||||
await expect(sut.handleVersionCheck()).resolves.toEqual(JobStatus.Failed);
|
||||
@@ -169,21 +191,36 @@ describe(VersionService.name, () => {
|
||||
describe('onWebsocketConnection', () => {
|
||||
it('should send on_server_version client event', async () => {
|
||||
await sut.onWebsocketConnection({ userId: '42' });
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledWith('on_server_version', '42', expect.any(SemVer));
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledWith('on_server_version', '42', {
|
||||
major: 3,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
});
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should also send a new release notification', async () => {
|
||||
mocks.systemMetadata.get.mockResolvedValue({ checkedAt: '2024-01-01', releaseVersion: 'v1.42.0' });
|
||||
await sut.onWebsocketConnection({ userId: '42' });
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledWith('on_server_version', '42', expect.any(SemVer));
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledWith('on_server_version', '42', {
|
||||
major: 3,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
});
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledWith('on_new_release', '42', expect.any(Object));
|
||||
});
|
||||
|
||||
it('should not send a release notification when the version check is disabled', async () => {
|
||||
mocks.systemMetadata.get.mockResolvedValueOnce({ newVersionCheck: { enabled: false } });
|
||||
await sut.onWebsocketConnection({ userId: '42' });
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledWith('on_server_version', '42', expect.any(SemVer));
|
||||
expect(mocks.websocket.clientSend).toHaveBeenCalledWith('on_server_version', '42', {
|
||||
major: 3,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
});
|
||||
expect(mocks.websocket.clientSend).not.toHaveBeenCalledWith('on_new_release', '42', expect.any(Object));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,7 +12,8 @@ import { handlePromiseError } from 'src/utils/misc';
|
||||
|
||||
const asNotification = ({ checkedAt, releaseVersion }: VersionCheckMetadata): ReleaseNotification => {
|
||||
return {
|
||||
isAvailable: semver.gt(releaseVersion, serverVersion),
|
||||
// can't use gt because it's broken for release candidates F https://github.com/npm/node-semver/issues/483
|
||||
isAvailable: semver.intersects(`>${serverVersion}`, releaseVersion.toString()),
|
||||
checkedAt,
|
||||
serverVersion: ServerVersionResponseDto.fromSemVer(serverVersion),
|
||||
releaseVersion: ServerVersionResponseDto.fromSemVer(new SemVer(releaseVersion)),
|
||||
@@ -103,7 +104,8 @@ export class VersionService extends BaseService {
|
||||
|
||||
await this.systemMetadataRepository.set(SystemMetadataKey.VersionCheckState, metadata);
|
||||
|
||||
if (semver.gt(releaseVersion, serverVersion)) {
|
||||
// can't use gt because it's broken for release candidates F https://github.com/npm/node-semver/issues/483
|
||||
if (semver.intersects(`>${serverVersion}`, releaseVersion.toString())) {
|
||||
this.logger.log(`Found ${releaseVersion}, released at ${new Date(publishedAt).toLocaleString()}`);
|
||||
this.websocketRepository.clientBroadcast('on_new_release', asNotification(metadata));
|
||||
}
|
||||
@@ -117,7 +119,11 @@ export class VersionService extends BaseService {
|
||||
|
||||
@OnEvent({ name: 'WebsocketConnect' })
|
||||
async onWebsocketConnection({ userId }: ArgOf<'WebsocketConnect'>) {
|
||||
this.websocketRepository.clientSend('on_server_version', userId, serverVersion);
|
||||
this.websocketRepository.clientSend(
|
||||
'on_server_version',
|
||||
userId,
|
||||
ServerVersionResponseDto.fromSemVer(serverVersion),
|
||||
);
|
||||
|
||||
const { newVersionCheck } = await this.getConfig({ withCache: true });
|
||||
if (!newVersionCheck.enabled) {
|
||||
|
||||
@@ -35,9 +35,7 @@
|
||||
userInteraction.versions = versions;
|
||||
});
|
||||
let isMain = $derived(info?.sourceRef === 'main' && info.repository === 'immich-app/immich');
|
||||
let version = $derived(
|
||||
$serverVersion ? `v${$serverVersion.major}.${$serverVersion.minor}.${$serverVersion.patch}` : null,
|
||||
);
|
||||
let version = $derived($serverVersion ? semverToName($serverVersion) : null);
|
||||
|
||||
const getReleaseInfo = (release?: ReleaseEvent) => {
|
||||
if (!release || !release?.isAvailable || !authManager.user.isAdmin) {
|
||||
|
||||
@@ -164,23 +164,63 @@ describe('utils', () => {
|
||||
|
||||
describe(getReleaseType.name, () => {
|
||||
it('should return "major" for major version changes', () => {
|
||||
expect(getReleaseType({ major: 1, minor: 0, patch: 0 }, { major: 2, minor: 0, patch: 0 })).toBe('major');
|
||||
expect(getReleaseType({ major: 1, minor: 0, patch: 0 }, { major: 3, minor: 2, patch: 1 })).toBe('major');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
{ major: 2, minor: 0, patch: 0, prerelease: null },
|
||||
),
|
||||
).toBe('major');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
{ major: 3, minor: 2, patch: 1, prerelease: null },
|
||||
),
|
||||
).toBe('major');
|
||||
});
|
||||
|
||||
it('should return "minor" for minor version changes', () => {
|
||||
expect(getReleaseType({ major: 1, minor: 0, patch: 0 }, { major: 1, minor: 1, patch: 0 })).toBe('minor');
|
||||
expect(getReleaseType({ major: 1, minor: 0, patch: 0 }, { major: 1, minor: 2, patch: 1 })).toBe('minor');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
{ major: 1, minor: 1, patch: 0, prerelease: null },
|
||||
),
|
||||
).toBe('minor');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
{ major: 1, minor: 2, patch: 1, prerelease: null },
|
||||
),
|
||||
).toBe('minor');
|
||||
});
|
||||
|
||||
it('should return "patch" for patch version changes', () => {
|
||||
expect(getReleaseType({ major: 1, minor: 0, patch: 0 }, { major: 1, minor: 0, patch: 1 })).toBe('patch');
|
||||
expect(getReleaseType({ major: 1, minor: 0, patch: 0 }, { major: 1, minor: 0, patch: 5 })).toBe('patch');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
{ major: 1, minor: 0, patch: 1, prerelease: null },
|
||||
),
|
||||
).toBe('patch');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
{ major: 1, minor: 0, patch: 5, prerelease: null },
|
||||
),
|
||||
).toBe('patch');
|
||||
});
|
||||
|
||||
it('should return "none" for matching versions', () => {
|
||||
expect(getReleaseType({ major: 1, minor: 0, patch: 0 }, { major: 1, minor: 0, patch: 0 })).toBe('none');
|
||||
expect(getReleaseType({ major: 1, minor: 2, patch: 3 }, { major: 1, minor: 2, patch: 3 })).toBe('none');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
{ major: 1, minor: 0, patch: 0, prerelease: null },
|
||||
),
|
||||
).toBe('none');
|
||||
expect(
|
||||
getReleaseType(
|
||||
{ major: 1, minor: 2, patch: 3, prerelease: null },
|
||||
{ major: 1, minor: 2, patch: 3, prerelease: null },
|
||||
),
|
||||
).toBe('none');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -430,7 +430,8 @@ export const getReleaseType = (
|
||||
return 'none';
|
||||
};
|
||||
|
||||
export const semverToName = ({ major, minor, patch }: ServerVersionResponseDto) => `v${major}.${minor}.${patch}`;
|
||||
export const semverToName = ({ major, minor, patch, prerelease }: ServerVersionResponseDto) =>
|
||||
`v${major}.${minor}.${patch}${prerelease ? `-rc.${prerelease}` : ''}`;
|
||||
|
||||
export const withoutIcons = (actions: ActionItem[]): ActionItem[] =>
|
||||
actions.map((action) => ({ ...action, icon: undefined }));
|
||||
|
||||
Reference in New Issue
Block a user