From dd0d11d68fea2231fff41744162388fa5eacff16 Mon Sep 17 00:00:00 2001 From: Sergio Zharinov <zharinov@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:01:15 +0400 Subject: [PATCH] feat(ruby): Switch to @renovate/ruby-semver library (#5116) --- lib/versioning/ruby/index.spec.ts | 9 +++ lib/versioning/ruby/index.ts | 2 +- lib/versioning/ruby/range.ts | 19 +++-- lib/versioning/ruby/strategies/bump.ts | 2 +- lib/versioning/ruby/strategies/replace.ts | 2 +- lib/versioning/ruby/version.ts | 99 +++++++++++++++-------- package.json | 2 +- yarn.lock | 12 ++- 8 files changed, 91 insertions(+), 56 deletions(-) diff --git a/lib/versioning/ruby/index.spec.ts b/lib/versioning/ruby/index.spec.ts index 5cbe03cc43..3b18a1554e 100644 --- a/lib/versioning/ruby/index.spec.ts +++ b/lib/versioning/ruby/index.spec.ts @@ -278,6 +278,15 @@ describe('semverRuby', () => { false ); }); + + it('returns null for garbage version input', () => { + expect(semverRuby.isLessThanRange('asdf', '> 1.2.2, ~> 2.0.0')).toBe( + null + ); + expect( + semverRuby.isLessThanRange(null as string, '> 1.2.2, ~> 2.0.0') + ).toBe(null); + }); }); describe('.isValid', () => { diff --git a/lib/versioning/ruby/index.ts b/lib/versioning/ruby/index.ts index 334e27b46d..500270fd4e 100644 --- a/lib/versioning/ruby/index.ts +++ b/lib/versioning/ruby/index.ts @@ -5,7 +5,7 @@ import { satisfies, maxSatisfying, minSatisfying, -} from '@snyk/ruby-semver'; +} from '@renovatebot/ruby-semver'; import { VersioningApi, NewValueConfig } from '../common'; import { logger } from '../../logger'; import { parse as parseVersion } from './version'; diff --git a/lib/versioning/ruby/range.ts b/lib/versioning/ruby/range.ts index be31b163aa..fd0f46e26b 100644 --- a/lib/versioning/ruby/range.ts +++ b/lib/versioning/ruby/range.ts @@ -1,5 +1,5 @@ -import { create } from '@snyk/ruby-semver/lib/ruby/gem-version'; -import { parse as _parse } from '@snyk/ruby-semver/lib/ruby/gem-requirement'; +import { create, Version } from '@renovatebot/ruby-semver/dist/ruby/version'; +import { parse as _parse } from '@renovatebot/ruby-semver/dist/ruby/requirement'; import { logger } from '../../logger'; import { EQUAL, NOT_EQUAL, GT, LT, GTE, LTE, PGTE } from './operator'; @@ -27,15 +27,14 @@ const parse = (range: string): Range => { }; }; -interface GemVersion { - release(): GemVersion; - compare(ver: GemVersion): number; - bump(): GemVersion; -} -type GemRequirement = [string, GemVersion]; +type GemRequirement = [string, Version]; -const ltr = (version: string, range: string): boolean => { - const gemVersion: GemVersion = create(version); +const ltr = (version: string, range: string): boolean | null => { + const gemVersion = create(version); + if (!gemVersion) { + logger.warn(`Invalid ruby version '${version}'`); + return null; + } const requirements: GemRequirement[] = range.split(',').map(_parse); const results = requirements.map(([operator, ver]) => { diff --git a/lib/versioning/ruby/strategies/bump.ts b/lib/versioning/ruby/strategies/bump.ts index acbac49726..a66d6ffe36 100644 --- a/lib/versioning/ruby/strategies/bump.ts +++ b/lib/versioning/ruby/strategies/bump.ts @@ -1,4 +1,4 @@ -import { gte, lte } from '@snyk/ruby-semver'; +import { gte, lte } from '@renovatebot/ruby-semver'; import { logger } from '../../../logger'; import { EQUAL, NOT_EQUAL, GT, LT, GTE, LTE, PGTE } from '../operator'; import { floor, increment, decrement } from '../version'; diff --git a/lib/versioning/ruby/strategies/replace.ts b/lib/versioning/ruby/strategies/replace.ts index 632e32ba3b..4ff52e7562 100644 --- a/lib/versioning/ruby/strategies/replace.ts +++ b/lib/versioning/ruby/strategies/replace.ts @@ -1,4 +1,4 @@ -import { satisfies } from '@snyk/ruby-semver'; +import { satisfies } from '@renovatebot/ruby-semver'; import bump from './bump'; import { logger } from '../../../logger'; diff --git a/lib/versioning/ruby/version.ts b/lib/versioning/ruby/version.ts index a6914561f5..7059b5b922 100644 --- a/lib/versioning/ruby/version.ts +++ b/lib/versioning/ruby/version.ts @@ -1,12 +1,24 @@ import last from 'lodash/last'; -import { create } from '@snyk/ruby-semver/lib/ruby/gem-version'; -import { diff, major, minor, patch, prerelease } from '@snyk/ruby-semver'; +import { + create, + SegmentElement, +} from '@renovatebot/ruby-semver/dist/ruby/version'; +import { eq, major, minor, patch, prerelease } from '@renovatebot/ruby-semver'; interface RubyVersion { major: number; minor: number; patch: number; - prerelease: string[]; + prerelease: string[] | null; +} + +function releaseSegments(version: string): SegmentElement[] { + const v = create(version); + if (v) { + return v.release().getSegments(); + } + /* istanbul ignore next */ + return []; } const parse = (version: string): RubyVersion => ({ @@ -19,13 +31,14 @@ const parse = (version: string): RubyVersion => ({ const adapt = (left: string, right: string): string => left.split('.').slice(0, right.split('.').length).join('.'); -const floor = (version: string): string => - [...create(version).release().getSegments().slice(0, -1), 0].join('.'); +const floor = (version: string): string => { + return [...releaseSegments(version).slice(0, -1), 0].join('.'); +}; // istanbul ignore next const incrementLastSegment = (version: string): string => { - const segments = create(version).release().getSegments(); - const nextLast = parseInt(last(segments), 10) + 1; + const segments = releaseSegments(version); + const nextLast = parseInt(last(segments) as string, 10) + 1; return [...segments.slice(0, -1), nextLast].join('.'); }; @@ -48,24 +61,29 @@ const incrementPatch = (ptch: number, pre: string[]): number => // istanbul ignore next const increment = (from: string, to: string): string => { - const { major: maj, minor: min, patch: ptch, prerelease: pre } = parse(from); + const parsed = parse(from); + const { major: maj, prerelease: pre } = parsed; + let { minor: min, patch: ptch } = parsed; + min = min || 0; + ptch = ptch || 0; let nextVersion: string; - switch (diff(from, adapt(to, from))) { - case 'major': - nextVersion = [incrementMajor(maj, min, ptch, pre || []), 0, 0].join('.'); - break; - case 'minor': - nextVersion = [maj, incrementMinor(min, ptch, pre || []), 0].join('.'); - break; - case 'patch': - nextVersion = [maj, min, incrementPatch(ptch, pre || [])].join('.'); - break; - case 'prerelease': - nextVersion = [maj, min, ptch].join('.'); - break; - default: - return incrementLastSegment(from); + const adapted = adapt(to, from); + if (eq(from, adapted)) { + return incrementLastSegment(from); + } + + const isStable = (x: string): boolean => /^[0-9.-/]+$/.test(x); + if (major(from) !== major(adapted)) { + nextVersion = [incrementMajor(maj, min, ptch, pre || []), 0, 0].join('.'); + } else if (minor(from) !== minor(adapted)) { + nextVersion = [maj, incrementMinor(min, ptch, pre || []), 0].join('.'); + } else if (patch(from) !== patch(adapted)) { + nextVersion = [maj, min, incrementPatch(ptch, pre || [])].join('.'); + } else if (isStable(from) && isStable(adapted)) { + nextVersion = [maj, min, incrementPatch(ptch, pre || [])].join('.'); + } else { + nextVersion = [maj, min, ptch].join('.'); } return increment(nextVersion, to); @@ -73,20 +91,31 @@ const increment = (from: string, to: string): string => { // istanbul ignore next const decrement = (version: string): string => { - const segments = create(version).release().getSegments(); + const segments = releaseSegments(version); const nextSegments = segments .reverse() - .reduce((accumulator: number[], segment: number, index: number) => { - if (index === 0) { - return [segment - 1]; - } - - if (accumulator[index - 1] === -1) { - return [...accumulator.slice(0, index - 1), 0, segment - 1]; - } - - return [...accumulator, segment]; - }, []); + .reduce( + ( + accumulator: number[], + segment: SegmentElement, + index: number + ): number[] => { + if (index === 0) { + return [(segment as number) - 1]; + } + + if (accumulator[index - 1] === -1) { + return [ + ...accumulator.slice(0, index - 1), + 0, + (segment as number) - 1, + ]; + } + + return [...accumulator, segment as number]; + }, + [] + ); return nextSegments.reverse().join('.'); }; diff --git a/package.json b/package.json index c3c5935396..7f5c367ead 100644 --- a/package.json +++ b/package.json @@ -110,8 +110,8 @@ }, "dependencies": { "@renovate/pep440": "0.4.1", + "@renovatebot/ruby-semver": "0.1.3", "@sindresorhus/is": "2.1.0", - "@snyk/ruby-semver": "2.1.0", "@yarnpkg/lockfile": "1.1.0", "aws-sdk": "2.656.0", "azure-devops-node-api": "10.1.1", diff --git a/yarn.lock b/yarn.lock index 86bcd18db4..bf6d70bfdf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1163,6 +1163,11 @@ dependencies: xregexp "4.2.0" +"@renovatebot/ruby-semver@0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@renovatebot/ruby-semver/-/ruby-semver-0.1.3.tgz#dfa43139d5a465dddec9e0e712d9d359bf7ea167" + integrity sha512-tGd5CMTCrFrmJhGxIhLP2Imv5bkzfZQY/6gfV+T6TOhMfca9hRBA7hj/xAexSDLAFN5QmEjGPK0SFusVUPPHIw== + "@semantic-release/commit-analyzer@^8.0.0": version "8.0.1" resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-8.0.1.tgz#5d2a37cd5a3312da0e3ac05b1ca348bf60b90bca" @@ -1296,13 +1301,6 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== -"@snyk/ruby-semver@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@snyk/ruby-semver/-/ruby-semver-2.1.0.tgz#d76cc02fc20860c224da2646fe9cc1bb0b0d1d15" - integrity sha512-u8ez8kWyqge+N+FxRDx/uPBmcHzY7BMfODvzEVeoTOeoD0CHPymEaVlkEKA8ZHtxzXjUzPIl2I8f2siZEzLjYg== - dependencies: - lodash "^4.17.14" - "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" -- GitLab