diff --git a/solo/src/core/dependency_manager.mjs b/solo/src/core/dependency_manager.mjs index 834a0aabf..43019a936 100644 --- a/solo/src/core/dependency_manager.mjs +++ b/solo/src/core/dependency_manager.mjs @@ -15,10 +15,15 @@ * */ import { FullstackTestingError } from './errors.mjs' +import { constants } from './index.mjs' import * as core from './index.mjs' +import * as helpers from './helpers.mjs' import { ShellRunner } from './shell_runner.mjs' export class DependencyManager extends ShellRunner { + static depVersions = new Map() + .set(constants.HELM, 'v3.14.0') + constructor (logger) { super(logger) @@ -27,23 +32,20 @@ export class DependencyManager extends ShellRunner { .set(core.constants.HELM, () => this.checkHelm()) } - async runCheck (cmdString) { - try { - await this.run(cmdString) - } catch (e) { - this.logger.error(e) - return false - } - - return true - } - /** * Check if 'helm' CLI program is installed or not * @returns {Promise} */ async checkHelm () { - return this.runCheck(`${core.constants.HELM} version`) + try { + const output = await this.run(`${core.constants.HELM} version --short`) + const parts = output[0].split('+') + return helpers.compareVersion(DependencyManager.depVersions.get(constants.HELM), parts[0]) >= 0 + } catch (e) { + this.logger.error(`failed to check helm dependency:${e.message}`, e) + } + + return false } /** diff --git a/solo/src/core/helpers.mjs b/solo/src/core/helpers.mjs index 78c5ec480..085a3d3ec 100644 --- a/solo/src/core/helpers.mjs +++ b/solo/src/core/helpers.mjs @@ -67,19 +67,19 @@ export function packageVersion () { } /** - * Split the release version into its major, minor and patch number - * @param releaseTag platform release version + * Split semantic version into its major, minor and patch number + * @param semver release version * @return {{patch: number, major: number, minor: number}} */ -export function parseReleaseTag (releaseTag) { - if (!releaseTag || releaseTag[0] !== 'v') { - throw new FullstackTestingError(`invalid release tag. Expected 'v..', found '${releaseTag}'`) +export function parseSemver (semver) { + if (!semver || semver[0] !== 'v') { + throw new FullstackTestingError(`invalid release tag. Expected 'v..', found '${semver}'`) } - releaseTag = releaseTag.replace('v', '') // remove first 'v' - const parts = releaseTag.split('-')[0].split('.') // just take the major.minor.patch part of the version + const version = semver.replace('v', '') // remove first 'v' + const parts = version.split('-')[0].split('.') // just take the major.minor.patch part of the version if (parts.length < 3) { - throw new FullstackTestingError('releaseTag must have the format MAJOR.MINOR.PATCH') + throw new FullstackTestingError(`version '${semver}' must have the format MAJOR.MINOR.PATCH`) } return { @@ -89,13 +89,37 @@ export function parseReleaseTag (releaseTag) { } } +/** + * Compare two version + * + * It returns 1, 0, -1 depending on the following three cases: + * - candidate > target: 1 + * - candidate == target: 0 + * - candidate < target: -1 + * + * @param target target version + * @param candidate candidate version + * @return {number} + */ +export function compareVersion (target, candidate) { + if (target === candidate) return 0 + + const v1 = parseSemver(target) + const v2 = parseSemver(candidate) + if (v2.major >= v1.major && v2.minor >= v1.minor && v2.patch >= v1.patch) { + return 1 + } + + return -1 +} + /** * Return the required root image for a platform version * @param releaseTag platform version * @return {string} */ export function getRootImageRepository (releaseTag) { - const releaseVersion = parseReleaseTag(releaseTag) + const releaseVersion = parseSemver(releaseTag) if (releaseVersion.minor < 46) { return 'hashgraph/full-stack-testing/ubi8-init-java17' } diff --git a/solo/src/core/platform_installer.mjs b/solo/src/core/platform_installer.mjs index faa0485ef..6460c5524 100644 --- a/solo/src/core/platform_installer.mjs +++ b/solo/src/core/platform_installer.mjs @@ -316,7 +316,7 @@ export class PlatformInstaller { const appName = constants.HEDERA_APP_NAME const nodeStakeAmount = constants.HEDERA_NODE_DEFAULT_STAKE_AMOUNT - const releaseVersion = helpers.parseReleaseTag(releaseTag) + const releaseVersion = helpers.parseSemver(releaseTag) try { const configLines = [] diff --git a/solo/test/unit/core/helpers.test.mjs b/solo/test/unit/core/helpers.test.mjs index 076b29a17..2d820900a 100644 --- a/solo/test/unit/core/helpers.test.mjs +++ b/solo/test/unit/core/helpers.test.mjs @@ -23,22 +23,47 @@ describe('Helpers', () => { ['v0.42.5', { major: 0, minor: 42, patch: 5 }], ['v0.42.5-alpha.0', { major: 0, minor: 42, patch: 5 }] ])('should parse release tag into major, minor and patch numbers', (input, expected) => { - const result = helpers.parseReleaseTag(input) + const result = helpers.parseSemver(input) expect(result).toEqual(expected) }) it.each([ ['', new FullstackTestingError('invalid release tag. Expected \'v..\', found \'\'')], ['0.42.5', new FullstackTestingError('invalid release tag. Expected \'v..\', found \'0.42.5\'')], - ['v0.42', new FullstackTestingError('releaseTag must have the format MAJOR.MINOR.PATCH')], - ['v0.42', new FullstackTestingError('releaseTag must have the format MAJOR.MINOR.PATCH')], - ['v0.NEW', new FullstackTestingError('releaseTag must have the format MAJOR.MINOR.PATCH')] + ['v0.42', new FullstackTestingError("version 'v0.42' must have the format MAJOR.MINOR.PATCH")], + ['v0.NEW', new FullstackTestingError("version 'v0.NEW' must have the format MAJOR.MINOR.PATCH")] ])('should throw error in parsing release tag', (input, expectedError) => { expect.assertions(1) try { - helpers.parseReleaseTag(input) // Error(new FullstackTestingError('releaseTag must have the format MAJOR.MINOR.PATCH')) + helpers.parseSemver(input) // Error(new FullstackTestingError('releaseTag must have the format MAJOR.MINOR.PATCH')) } catch (e) { expect(e).toEqual(expectedError) } }) + + describe('compareVersion', () => { + it('should succeed with same version', () => { + expect(helpers.compareVersion('v3.14.0', 'v3.14.0')).toBe(0) + }) + + it('should succeed with patch higher than target', () => { + expect(helpers.compareVersion('v3.14.0', 'v3.14.1')).toBe(1) + }) + + it('should succeed with minor version higher than target', () => { + expect(helpers.compareVersion('v3.14.0', 'v3.15.0')).toBe(1) + }) + + it('should succeed with major version higher than target', () => { + expect(helpers.compareVersion('v3.14.0', 'v4.14.0')).toBe(1) + }) + + it('should fail with major version lower than target', () => { + expect(helpers.compareVersion('v3.14.0', 'v2.14.0')).toBe(-1) + }) + + it('should fail with minor version lower than target', () => { + expect(helpers.compareVersion('v3.14.0', 'v3.11.0')).toBe(-1) + }) + }) })