[FEAT] New APP_VERSION env var inferred from tag & refactor upgrade-command to integrate versioning (#10751)
# Introduction This PR contains a big test file and few snapshots Related to https://github.com/twentyhq/core-team-issues/issues/487 ## New env var `APP_VERSION` Now will be injected directly in a built docker image the twenty's built version. Inferred from the build git tag name. Which mean on main or other `not a tag version` built APP_VERSION will be `null` ## New upgrade-commander-runner Refactored the upgrade command to be more strict regarding: - Version management - Sync metadata command always run - Added failing workspaces aggregator + logs on cleanup From now on the `upgrade` command will compare the `WORKSPACE_VERSION` to the `APP_VERSION` in order to bypass any workspace version != than the upgrade version `fromVersion` ## Existing commands Note that the version validation will be done only when passing by the `upgrade` command. Which means that running the following command `upgrade:x.y-some-specific-command` won't result in workspace version mutation This is to enforce that all an upgrade commands + sync-metadata has been run on a workspace ## Will do in other PR but related ### New workspace New workspace will now be inserted with version equal to the APP_VERSION they've been created by ### Old workspace Will create a command that should be ran outside of any `upgrade-runner` extending command, the command will have to be ran on every workspace before making the next release upgrade This command iterates over any active and suspended workspace that has `version` to `NULL` in order to update it `APP_VERSION` -1 minor ### SENTRY_RELEASE - Either deprecate SENTRY_RELEASE in favor of `APP_VERSION` => What about main with null version ? or create a new env var that would be `APP_COMMIT_SHA` instead of SENTRY third party ref ### Update CD to inject APP_VERSION from branch name ### Update docs and release logs Adding documentation for `APP_VERSION` ## Related PRs: https://github.com/twentyhq/twenty-infra/pull/181
This commit is contained in:
@ -0,0 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`is-same-major-and-minor-version incomplete version1 1`] = `"Received invalid version: 1.0 1.1.0"`;
|
||||
|
||||
exports[`is-same-major-and-minor-version invalid version1 1`] = `"Received invalid version: invalid 1.1.0"`;
|
||||
|
||||
exports[`is-same-major-and-minor-version invalid version2 1`] = `"Received invalid version: 1.0.0 invalid"`;
|
||||
@ -0,0 +1,192 @@
|
||||
import { EachTestingContext } from 'twenty-shared';
|
||||
|
||||
import { compareVersionMajorAndMinor } from 'src/utils/version/compare-version-minor-and-major';
|
||||
|
||||
type IsSameVersionTestCase = EachTestingContext<{
|
||||
version1: string;
|
||||
version2: string;
|
||||
expected?: ReturnType<typeof compareVersionMajorAndMinor>;
|
||||
expectToThrow?: boolean;
|
||||
}>;
|
||||
describe('is-same-major-and-minor-version', () => {
|
||||
const beneathVersionTestCases: IsSameVersionTestCase[] = [
|
||||
{
|
||||
context: {
|
||||
version1: '1.0.0',
|
||||
version2: '1.1.0',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'different minor version',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '2.3.0',
|
||||
version2: '2.4.0',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'different minor version',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '0.1.0',
|
||||
version2: '0.2.0',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'different minor version with zero major',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '2.3.5',
|
||||
version2: '2.4.1',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'different minor and patch versions',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '1.0.0-alpha',
|
||||
version2: '1.1.0-beta',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'different minor version with different pre-release tags',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: 'v1.0.0',
|
||||
version2: 'v1.1.0',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'different minor version with v prefix',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '2.0.0',
|
||||
version2: '42.42.42',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'above version2',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '2.0.0',
|
||||
version2: 'v42.42.42',
|
||||
expected: 'lower',
|
||||
},
|
||||
title: 'above version2 with v-prefix',
|
||||
},
|
||||
];
|
||||
|
||||
const sameVersionTestCases: IsSameVersionTestCase[] = [
|
||||
{
|
||||
context: {
|
||||
version1: '1.1.0',
|
||||
version2: '1.1.0',
|
||||
expected: 'equal',
|
||||
},
|
||||
title: 'exact same version',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '1.1.0',
|
||||
version2: '1.1.42',
|
||||
expected: 'equal',
|
||||
},
|
||||
title: 'exact same major and minor but different patch version',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: 'v1.1.0',
|
||||
version2: 'v1.1.0',
|
||||
expected: 'equal',
|
||||
},
|
||||
title: 'exact same version with v prefix',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '1.1.0-alpha',
|
||||
version2: '1.1.0-alpha',
|
||||
expected: 'equal',
|
||||
},
|
||||
title: 'exact same version with same pre-release tag',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '0.0.1',
|
||||
version2: '0.0.1',
|
||||
expected: 'equal',
|
||||
},
|
||||
title: 'exact same version with all zeros',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: 'v1.1.0',
|
||||
version2: '1.1.0',
|
||||
expected: 'equal',
|
||||
},
|
||||
title: 'same version with different v-prefix',
|
||||
},
|
||||
];
|
||||
|
||||
const aboveVersionTestCases: IsSameVersionTestCase[] = [
|
||||
{
|
||||
context: {
|
||||
version1: 'v42.1.0',
|
||||
version2: '2.0.0',
|
||||
expected: 'higher',
|
||||
},
|
||||
title: 'above version',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '42.42.42',
|
||||
version2: '2.0.0',
|
||||
expected: 'higher',
|
||||
},
|
||||
title: 'above version with prefix',
|
||||
},
|
||||
];
|
||||
const invalidTestCases: IsSameVersionTestCase[] = [
|
||||
{
|
||||
context: {
|
||||
version1: 'invalid',
|
||||
version2: '1.1.0',
|
||||
expectToThrow: true,
|
||||
},
|
||||
title: 'invalid version1',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '1.0.0',
|
||||
version2: 'invalid',
|
||||
expectToThrow: true,
|
||||
},
|
||||
title: 'invalid version2',
|
||||
},
|
||||
{
|
||||
context: {
|
||||
version1: '1.0',
|
||||
version2: '1.1.0',
|
||||
expectToThrow: true,
|
||||
},
|
||||
title: 'incomplete version1',
|
||||
},
|
||||
];
|
||||
|
||||
test.each([
|
||||
...sameVersionTestCases,
|
||||
...invalidTestCases,
|
||||
...beneathVersionTestCases,
|
||||
...aboveVersionTestCases,
|
||||
])(
|
||||
'$title',
|
||||
({ context: { version1, version2, expected, expectToThrow = false } }) => {
|
||||
if (expectToThrow) {
|
||||
expect(() =>
|
||||
compareVersionMajorAndMinor(version1, version2),
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
} else {
|
||||
expect(compareVersionMajorAndMinor(version1, version2)).toBe(expected);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -0,0 +1,37 @@
|
||||
import * as semver from 'semver';
|
||||
|
||||
type CompareVersionMajorAndMinorReturnType = 'lower' | 'equal' | 'higher';
|
||||
export function compareVersionMajorAndMinor(
|
||||
rawVersion1: string,
|
||||
rawVersion2: string,
|
||||
): CompareVersionMajorAndMinorReturnType {
|
||||
const [version1, version2] = [rawVersion1, rawVersion2].map((version) =>
|
||||
semver.parse(version),
|
||||
);
|
||||
|
||||
if (version1 === null || version2 === null) {
|
||||
throw new Error(`Received invalid version: ${rawVersion1} ${rawVersion2}`);
|
||||
}
|
||||
|
||||
const v1WithoutPatch = `${version1.major}.${version1.minor}.0`;
|
||||
const v2WithoutPatch = `${version2.major}.${version2.minor}.0`;
|
||||
|
||||
const compareResult = semver.compare(v1WithoutPatch, v2WithoutPatch);
|
||||
|
||||
switch (compareResult) {
|
||||
case -1: {
|
||||
return 'lower';
|
||||
}
|
||||
case 0: {
|
||||
return 'equal';
|
||||
}
|
||||
case 1: {
|
||||
return 'higher';
|
||||
}
|
||||
default: {
|
||||
throw new Error(
|
||||
`Should never occur, encountered an unexpected value from semver.compare ${compareResult}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user