diff --git a/lib/modules/versioning/distro.spec.ts b/lib/modules/versioning/distro.spec.ts index d0dd67db08eab6aa48c943daa80019b0759fa900..d451437ab41027b61f42b7e383164c30942f6060 100644 --- a/lib/modules/versioning/distro.spec.ts +++ b/lib/modules/versioning/distro.spec.ts @@ -1,8 +1,14 @@ +import { DateTime, Settings } from 'luxon'; import { DistroInfo } from './distro'; describe('modules/versioning/distro', () => { const di = new DistroInfo('data/ubuntu-distro-info.json'); + beforeAll(() => { + const dt = DateTime.fromISO('2021-03-20'); + jest.spyOn(Settings, 'now').mockReturnValue(dt.valueOf()); + }); + it.each` version | expected ${'jammy'} | ${true} @@ -73,68 +79,77 @@ describe('modules/versioning/distro', () => { it.each` version | expected + ${'eoan'} | ${true} ${'focal'} | ${false} - ${'groovy'} | ${true} - ${'hirsute'} | ${true} + ${'groovy'} | ${false} + ${'hirsute'} | ${false} ${'impish'} | ${false} ${'jammy'} | ${false} + ${'19.10'} | ${true} ${'20.04'} | ${false} - ${'20.10'} | ${true} - ${'21.04'} | ${true} + ${'20.10'} | ${false} + ${'21.04'} | ${false} ${'21.10'} | ${false} ${'22.04'} | ${false} `('isEolLts("$version") === $expected', ({ version, expected }) => { expect(di.isEolLts(version)).toBe(expected); }); - it('retrieves most recent release schedule with version', () => { - expect(di.getNLatest(0)).toEqual({ - codename: 'Jammy Jellyfish', - created: '2021-10-14', - eol: '2027-04-21', - eol_esm: '2032-04-21', - eol_server: '2027-04-21', - release: '2022-04-21', - series: 'jammy', - version: '22.04', + it.each` + version | expected + ${'focal'} | ${true} + ${'groovy'} | ${true} + ${'hirsute'} | ${false} + ${'impish'} | ${false} + ${'jammy'} | ${false} + ${'20.04'} | ${true} + ${'20.10'} | ${true} + ${'21.04'} | ${false} + ${'21.10'} | ${false} + ${'22.04'} | ${false} + ${'24.04'} | ${false} + `('isReleased("$version") === $expected', ({ version, expected }) => { + expect(di.isReleased(version)).toBe(expected); + }); + + it('retrieves schedule of the previous previous release', () => { + expect(di.getNLatest(2)).toMatchObject({ + series: 'eoan', + version: '19.10', }); }); - it('sends an out of bound argument', () => { - expect(di.getNLatest(-1)).toBeNull(); + it('retrieves schedule of the previous release', () => { + expect(di.getNLatest(1)).toMatchObject({ + series: 'focal', + version: '20.04', + }); }); - it('sends a float as an argument', () => { - expect(di.getNLatest(0.1)).toEqual({ - codename: 'Jammy Jellyfish', - created: '2021-10-14', - eol: '2027-04-21', - eol_esm: '2032-04-21', - eol_server: '2027-04-21', - release: '2022-04-21', - series: 'jammy', - version: '22.04', + it('retrieves schedule of the most recent release', () => { + expect(di.getNLatest(0)).toMatchObject({ + series: 'groovy', + version: '20.10', }); }); - it('retrieves before most recent release schedule with version', () => { - expect(di.getNLatest(1)).toEqual({ - codename: 'Impish Indri', - series: 'impish', - created: '2021-04-22', - release: '2021-10-14', - eol: '2022-07-14', - version: '21.10', + it('sends a float as an argument', () => { + expect(di.getNLatest(0.1)).toMatchObject({ + series: 'groovy', + version: '20.10', }); }); + it('sends an out of bound argument', () => { + expect(di.getNLatest(-1)).toBeNull(); + }); + + it('sends another out of bound argument', () => { + expect(di.getNLatest(100)).toBeNull(); + }); + it('retrieves focal release schedule', () => { - expect(di.getSchedule('20.04')).toEqual({ - codename: 'Focal Fossa', - created: '2019-10-17', - eol: '2025-04-23', - eol_esm: '2030-04-23', - eol_server: '2025-04-23', + expect(di.getSchedule('20.04')).toMatchObject({ release: '2020-04-23', series: 'focal', }); diff --git a/lib/modules/versioning/distro.ts b/lib/modules/versioning/distro.ts index eba5d8af9682dd141017d9a9c5346b78daa6a6cf..7d52f6f3aa5586fcfe625213bec598d71c9d2ecd 100644 --- a/lib/modules/versioning/distro.ts +++ b/lib/modules/versioning/distro.ts @@ -19,6 +19,9 @@ export type DistroInfoRecord = Record<string, DistroSchedule>; export type DistroInfoRecordWithVersion = { version: string } & DistroSchedule; +// Days to delay new releases +const delay = 1; + export class DistroInfo { private readonly _codenameToVersion = new Map< string, @@ -127,8 +130,8 @@ export class DistroInfo { } if (end) { - const now = DateTime.now(); - const eol = DateTime.fromISO(end); + const now = DateTime.now().toUTC(); + const eol = DateTime.fromISO(end, { zone: 'utc' }); return eol < now; } @@ -136,6 +139,25 @@ export class DistroInfo { return true; } + /** + * Check if a given version has been released + * @param input A codename/semVer + * @returns false if unreleased or has no schedule, true otherwise + */ + public isReleased(input: string): boolean { + const ver = this.getVersionByCodename(input); + const schedule = this.getSchedule(ver); + + if (!schedule) { + return false; + } + + const now = DateTime.now().minus({ day: delay }).toUTC(); + const release = DateTime.fromISO(schedule.release, { zone: 'utc' }); + + return release < now; + } + /** * Get distro info for the release that has N other newer releases. * Example: n=0 corresponds to the latest available release, n=1 the release before, etc. @@ -145,12 +167,25 @@ export class DistroInfo { */ public getNLatest(n: number): DistroInfoRecordWithVersion | null { const len = this._sortedInfo.length - 1; - const i = len - Math.floor(n); + let idx = -1; + + if (n < 0) { + return null; + } + + for (let i = len; i >= 0; i--) { + if (this.isReleased(this._sortedInfo[i].version)) { + // 'i' holds the latest released version index + // compensate for the requested 'n' + idx = i - Math.floor(n); + break; + } + } - if (len >= i && i >= 0) { - return this._sortedInfo[i]; + if (idx > len || idx < 0) { + return null; } - return null; + return this._sortedInfo[idx]; } } diff --git a/lib/modules/versioning/ubuntu/index.spec.ts b/lib/modules/versioning/ubuntu/index.spec.ts index 0287985b11943387520a430110b9a91910f17d70..0c8233e644c914aa5d6fc064b62e5377371c0086 100644 --- a/lib/modules/versioning/ubuntu/index.spec.ts +++ b/lib/modules/versioning/ubuntu/index.spec.ts @@ -155,17 +155,6 @@ describe('modules/versioning/ubuntu/index', () => { ${'20.04'} | ${true} ${'20.10'} | ${false} ${'22.04'} | ${false} - ${'42.01'} | ${false} - ${'42.02'} | ${false} - ${'42.03'} | ${false} - ${'42.04'} | ${true} - ${'42.05'} | ${false} - ${'42.06'} | ${false} - ${'42.07'} | ${false} - ${'42.08'} | ${false} - ${'42.09'} | ${false} - ${'42.10'} | ${false} - ${'42.11'} | ${false} ${'2020.04'} | ${false} ${'warty'} | ${false} ${'hoary'} | ${false} diff --git a/lib/modules/versioning/ubuntu/index.ts b/lib/modules/versioning/ubuntu/index.ts index b49f5ad230f69fe6304cf323832eb640e63979ba..304488dbba56ec298f91b771ebaffec3f377b8f6 100644 --- a/lib/modules/versioning/ubuntu/index.ts +++ b/lib/modules/versioning/ubuntu/index.ts @@ -1,4 +1,3 @@ -import { DateTime } from 'luxon'; import { regEx } from '../../../util/regex'; import { DistroInfo } from '../distro'; import type { NewValueConfig, VersioningApi } from '../types'; @@ -43,12 +42,9 @@ function isStable(version: string): boolean { return false; } - const schedule = di.getSchedule(ver); - if ( - schedule && - DateTime.fromISO(schedule.release).toUTC() > - DateTime.now().minus({ days: 1 }).toUTC() - ) { + const match = ver.match(regEx(/^\d+.\d+/)); + + if (!di.isReleased(match ? match[0] : ver)) { return false; }