feat: derive mobile build number from semver (#30569)
This commit is contained in:
1 parent
9273a4ca2a
commit
cf17dcbfee
5 files changed
+104
-41
No files matched your search
@@ -1,11 +1,16 @@
|
||||
import semver from 'semver';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import {
|
||||
resolveArchivedVersions,
|
||||
ArchivedVersion,
|
||||
getMobileBuild,
|
||||
getNewVersion,
|
||||
ReleaseError,
|
||||
} from './release';
|
||||
|
||||
const mobileBuild = (version: string) =>
|
||||
getMobileBuild(semver.parse(version) as semver.SemVer);
|
||||
|
||||
const archived = (label: string): ArchivedVersion => ({
|
||||
label,
|
||||
url: `https://docs.${label}.archive.immich.app`,
|
||||
@@ -137,3 +142,56 @@ describe(resolveArchivedVersions.name, () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe(getMobileBuild.name, () => {
|
||||
it('should encode the version', () => {
|
||||
expect(mobileBuild('3.1.0')).toBe(3_010_099);
|
||||
expect(mobileBuild('3.1.4')).toBe(3_010_499);
|
||||
expect(mobileBuild('3.2.0-rc.0')).toBe(3_020_000);
|
||||
expect(mobileBuild('3.2.0-rc.3')).toBe(3_020_003);
|
||||
});
|
||||
|
||||
it('should be above the last hand-maintained build number', () => {
|
||||
expect(mobileBuild('3.1.0')).toBeGreaterThan(3057);
|
||||
});
|
||||
|
||||
it('should stay under the play store limit', () => {
|
||||
expect(mobileBuild('99.99.99')).toBeLessThan(2_100_000_000);
|
||||
});
|
||||
|
||||
it('should increase across a release cycle', () => {
|
||||
const versions = [
|
||||
'3.1.0',
|
||||
'3.1.1',
|
||||
'3.2.0-rc.0',
|
||||
'3.2.0-rc.1',
|
||||
'3.2.0',
|
||||
'3.2.1',
|
||||
'3.3.0-rc.0',
|
||||
'4.0.0-rc.0',
|
||||
'4.0.0',
|
||||
];
|
||||
|
||||
const builds = versions.map((version) => mobileBuild(version));
|
||||
expect(builds).toEqual([...builds].sort((a, b) => a - b));
|
||||
expect(new Set(builds).size).toBe(builds.length);
|
||||
});
|
||||
|
||||
it('should rank a release above its own candidates', () => {
|
||||
expect(mobileBuild('3.2.0')).toBeGreaterThan(mobileBuild('3.2.0-rc.98'));
|
||||
});
|
||||
|
||||
it('should rank a patch on an older line below the newer line', () => {
|
||||
expect(mobileBuild('3.1.5')).toBeLessThan(mobileBuild('3.2.0'));
|
||||
});
|
||||
|
||||
it('should refuse versions it cannot encode', () => {
|
||||
expect(() => mobileBuild('100.0.0')).toThrow('Cannot derive');
|
||||
expect(() => mobileBuild('3.100.0')).toThrow('Cannot derive');
|
||||
expect(() => mobileBuild('3.1.100')).toThrow('Cannot derive');
|
||||
expect(() => mobileBuild('3.1.0-rc.99')).toThrow('Cannot derive');
|
||||
expect(() => mobileBuild('3.1.0-beta')).toThrow('Cannot derive');
|
||||
expect(() => mobileBuild('3.1.0-rc.-1')).toThrow('Cannot derive');
|
||||
expect(() => mobileBuild('3.1.0-rc.x')).toThrow('Cannot derive');
|
||||
});
|
||||
});
|
||||
@@ -35,7 +35,7 @@ const Files = {
|
||||
},
|
||||
};
|
||||
|
||||
export const handleRelease = ({ type, mobile }: ReleaseOptions) => {
|
||||
export const handleRelease = ({ type }: ReleaseOptions) => {
|
||||
const versionRaw = getVersion();
|
||||
const newVersionRaw = getNewVersion(versionRaw, type);
|
||||
const newVersion = semver.parse(normalize(newVersionRaw));
|
||||
@@ -43,8 +43,7 @@ export const handleRelease = ({ type, mobile }: ReleaseOptions) => {
|
||||
throw new ReleaseInputError();
|
||||
}
|
||||
const newVersionNoRc = `${newVersion.major}.${newVersion.minor}.${newVersion.patch}`;
|
||||
const mobileBuild = getMobileBuild();
|
||||
const newMobileBuild = mobile ? mobileBuild + 1 : mobileBuild;
|
||||
const newMobileBuild = getMobileBuild(newVersion);
|
||||
|
||||
// pump versions everywhere
|
||||
|
||||
@@ -189,14 +188,32 @@ export const getNewVersion = (versionRaw: string, type: string) => {
|
||||
return newVersionRaw;
|
||||
};
|
||||
|
||||
const getMobileBuild = () => {
|
||||
const pubspec = new TextFile(Files.Mobile.Pubspec).read();
|
||||
const match = pubspec.match(/^version: .*\+(\d+)$/m);
|
||||
if (!match) {
|
||||
throw new Error('Could not find mobile build number in pubspec.yaml');
|
||||
const RADIX = 100;
|
||||
const STABLE = RADIX - 1;
|
||||
|
||||
export const getMobileBuild = (version: SemVer) => {
|
||||
const { major, minor, patch, prerelease } = version;
|
||||
const candidate = prerelease[1];
|
||||
const digit = typeof candidate === 'number' ? candidate : STABLE;
|
||||
|
||||
const valid =
|
||||
major < RADIX &&
|
||||
minor < RADIX &&
|
||||
patch < RADIX &&
|
||||
(prerelease.length === 0 || digit < STABLE);
|
||||
|
||||
if (!valid) {
|
||||
throw new Error(
|
||||
`Cannot derive a mobile build number from ${version.format()}`,
|
||||
);
|
||||
}
|
||||
|
||||
return Number(match[1]);
|
||||
return (
|
||||
major * Math.pow(RADIX, 3) +
|
||||
minor * Math.pow(RADIX, 2) +
|
||||
patch * RADIX +
|
||||
digit
|
||||
);
|
||||
};
|
||||
|
||||
const pump = (path: string, pattern: RegExp, replacement: string) => {
|
||||
|
||||
Reference in new issue
Block a user