mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-10 14:06:30 +00:00
Merge e348689be6
into 1d2c1a35e3
This commit is contained in:
commit
fa3dd8448d
9 changed files with 322 additions and 2 deletions
56
data/lambda-node-js-schedule.json
Normal file
56
data/lambda-node-js-schedule.json
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"10": {
|
||||||
|
"cycle": "nodejs10.x",
|
||||||
|
"releaseLabel": "Node.js 10",
|
||||||
|
"releaseDate": "2019-05-15",
|
||||||
|
"eol": "2022-02-14",
|
||||||
|
"link": "https://aws.amazon.com/about-aws/whats-new/2019/05/aws_lambda_adds_support_for_node_js_v10/",
|
||||||
|
"lts": false,
|
||||||
|
"support": "2021-07-30"
|
||||||
|
},
|
||||||
|
"12": {
|
||||||
|
"cycle": "nodejs12.x",
|
||||||
|
"releaseLabel": "Node.js 12",
|
||||||
|
"releaseDate": "2019-11-18",
|
||||||
|
"eol": "2023-04-30",
|
||||||
|
"link": "https://aws.amazon.com/blogs/compute/node-js-12-x-runtime-now-available-in-aws-lambda/",
|
||||||
|
"lts": false,
|
||||||
|
"support": "2023-03-31"
|
||||||
|
},
|
||||||
|
"14": {
|
||||||
|
"cycle": "nodejs14.x",
|
||||||
|
"releaseLabel": "Node.js 14",
|
||||||
|
"releaseDate": "2021-02-03",
|
||||||
|
"eol": "2025-02-28",
|
||||||
|
"link": "https://aws.amazon.com/blogs/compute/node-js-14-x-runtime-now-available-in-aws-lambda/",
|
||||||
|
"lts": false,
|
||||||
|
"support": "2023-12-04"
|
||||||
|
},
|
||||||
|
"16": {
|
||||||
|
"cycle": "nodejs16.x",
|
||||||
|
"releaseLabel": "Node.js 16",
|
||||||
|
"releaseDate": "2022-05-12",
|
||||||
|
"eol": "2025-03-31",
|
||||||
|
"link": "https://aws.amazon.com/blogs/compute/node-js-16-x-runtime-now-available-in-aws-lambda/",
|
||||||
|
"lts": false,
|
||||||
|
"support": "2024-06-12"
|
||||||
|
},
|
||||||
|
"18": {
|
||||||
|
"cycle": "nodejs18.x",
|
||||||
|
"releaseLabel": "Node.js 18",
|
||||||
|
"releaseDate": "2022-11-18",
|
||||||
|
"eol": "2025-10-01",
|
||||||
|
"link": "https://aws.amazon.com/blogs/compute/node-js-18-x-runtime-now-available-in-aws-lambda/",
|
||||||
|
"lts": false,
|
||||||
|
"support": "2025-07-31"
|
||||||
|
},
|
||||||
|
"20": {
|
||||||
|
"cycle": "nodejs20.x",
|
||||||
|
"releaseLabel": "Node.js 20",
|
||||||
|
"releaseDate": "2023-11-15",
|
||||||
|
"eol": false,
|
||||||
|
"link": "https://aws.amazon.com/blogs/compute/node-js-20-x-runtime-now-available-in-aws-lambda/",
|
||||||
|
"lts": false,
|
||||||
|
"support": true
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import * as hermit from './hermit';
|
||||||
import * as hex from './hex';
|
import * as hex from './hex';
|
||||||
import * as ivy from './ivy';
|
import * as ivy from './ivy';
|
||||||
import * as kubernetesApi from './kubernetes-api';
|
import * as kubernetesApi from './kubernetes-api';
|
||||||
|
import * as lambdaNode from './lambda-node';
|
||||||
import * as loose from './loose';
|
import * as loose from './loose';
|
||||||
import * as maven from './maven';
|
import * as maven from './maven';
|
||||||
import * as nixpkgs from './nixpkgs';
|
import * as nixpkgs from './nixpkgs';
|
||||||
|
@ -65,6 +66,7 @@ api.set(hermit.id, hermit.api);
|
||||||
api.set(hex.id, hex.api);
|
api.set(hex.id, hex.api);
|
||||||
api.set(ivy.id, ivy.api);
|
api.set(ivy.id, ivy.api);
|
||||||
api.set(kubernetesApi.id, kubernetesApi.api);
|
api.set(kubernetesApi.id, kubernetesApi.api);
|
||||||
|
api.set(lambdaNode.id, lambdaNode.api);
|
||||||
api.set(loose.id, loose.api);
|
api.set(loose.id, loose.api);
|
||||||
api.set(maven.id, maven.api);
|
api.set(maven.id, maven.api);
|
||||||
api.set(nixpkgs.id, nixpkgs.api);
|
api.set(nixpkgs.id, nixpkgs.api);
|
||||||
|
|
118
lib/modules/versioning/lambda-node/index.spec.ts
Normal file
118
lib/modules/versioning/lambda-node/index.spec.ts
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
import { api as lambdaVer } from '.';
|
||||||
|
|
||||||
|
describe('modules/versioning/lambda-node/index', () => {
|
||||||
|
let dtLocal: any;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
dtLocal = DateTime.local;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
DateTime.local = dtLocal;
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
currentValue | rangeStrategy | currentVersion | newVersion | expected
|
||||||
|
${'1.0.0'} | ${'replace'} | ${'1.0.0'} | ${'v1.1.0'} | ${'1.1.0'}
|
||||||
|
${'~8.0.0'} | ${'replace'} | ${'8.0.2'} | ${'v8.2.0'} | ${'~8.2.0'}
|
||||||
|
${'erbium'} | ${'replace'} | ${'12.0.0'} | ${'v14.1.4'} | ${'fermium'}
|
||||||
|
${'Fermium'} | ${'replace'} | ${'14.0.0'} | ${'v16.1.6'} | ${'gallium'}
|
||||||
|
${'gallium'} | ${'pin'} | ${'16.1.6'} | ${'v16.1.6'} | ${'16.1.6'}
|
||||||
|
${'gallium'} | ${'bump'} | ${'16.0.0'} | ${'v16.1.6'} | ${'gallium'}
|
||||||
|
${'gallium'} | ${'auto'} | ${'16.1.6'} | ${'v16.1.6'} | ${'gallium'}
|
||||||
|
`(
|
||||||
|
'getNewValue($currentValue, $rangeStrategy, $currentVersion, $newVersion, $expected) === $expected',
|
||||||
|
({ currentValue, rangeStrategy, currentVersion, newVersion, expected }) => {
|
||||||
|
const res = lambdaVer.getNewValue({
|
||||||
|
currentValue,
|
||||||
|
rangeStrategy,
|
||||||
|
currentVersion,
|
||||||
|
newVersion,
|
||||||
|
});
|
||||||
|
expect(res).toBe(expected);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const t1 = DateTime.fromISO('2024-09-01');
|
||||||
|
const t2 = DateTime.fromISO('2024-03-01');
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
version | time | expected
|
||||||
|
${'v18.0.3'} | ${t1} | ${true}
|
||||||
|
${'v18.0.0'} | ${t1} | ${true}
|
||||||
|
${'18.0.0'} | ${t1} | ${true}
|
||||||
|
${'18.0.0a'} | ${t1} | ${false}
|
||||||
|
${'16.0.0'} | ${t2} | ${true}
|
||||||
|
${'16.0.0'} | ${t1} | ${false}
|
||||||
|
${'15.0.0'} | ${t1} | ${false}
|
||||||
|
${'14.9.0'} | ${t1} | ${false}
|
||||||
|
${'14.0.0'} | ${t1} | ${false}
|
||||||
|
${'12.0.3'} | ${t1} | ${false}
|
||||||
|
${'v12.0.3'} | ${t1} | ${false}
|
||||||
|
${'12.0.3a'} | ${t1} | ${false}
|
||||||
|
${'11.0.0'} | ${t1} | ${false}
|
||||||
|
${'10.0.0'} | ${t1} | ${false}
|
||||||
|
${'10.0.999'} | ${t1} | ${false}
|
||||||
|
${'10.1.0'} | ${t1} | ${false}
|
||||||
|
${'10.0.0a'} | ${t1} | ${false}
|
||||||
|
${'9.0.0'} | ${t1} | ${false}
|
||||||
|
`('isStable("$version") === $expected', ({ version, time, expected }) => {
|
||||||
|
DateTime.local = (...args: any[]) =>
|
||||||
|
args.length ? dtLocal.apply(DateTime, args) : time;
|
||||||
|
expect(lambdaVer.isStable(version as string)).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
version | expected
|
||||||
|
${'16.0.0'} | ${true}
|
||||||
|
${'erbium'} | ${true}
|
||||||
|
${'bogus'} | ${false}
|
||||||
|
${'^10.0.0'} | ${true}
|
||||||
|
${'10.x'} | ${true}
|
||||||
|
${'10.9.8.7'} | ${false}
|
||||||
|
`('isValid("$version") === $expected', ({ version, expected }) => {
|
||||||
|
expect(lambdaVer.isValid(version as string)).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
version | range | expected
|
||||||
|
${'16.0.0'} | ${'gallium'} | ${true}
|
||||||
|
${'16.0.0'} | ${'fermium'} | ${false}
|
||||||
|
`(
|
||||||
|
'matches("$version", "$range") === $expected',
|
||||||
|
({ version, range, expected }) => {
|
||||||
|
expect(lambdaVer.matches(version as string, range as string)).toBe(
|
||||||
|
expected,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
versions | range | expected
|
||||||
|
${['16.0.0']} | ${'gallium'} | ${'16.0.0'}
|
||||||
|
${['16.0.0', '14.0.0', '16.9.9']} | ${'gallium'} | ${'16.9.9'}
|
||||||
|
${['15.0.0', '14.0.0']} | ${'gallium'} | ${null}
|
||||||
|
`(
|
||||||
|
'getSatisfyingVersion("$versions", "$range") === $expected',
|
||||||
|
({ versions, range, expected }) => {
|
||||||
|
expect(
|
||||||
|
lambdaVer.getSatisfyingVersion(versions as string[], range as string),
|
||||||
|
).toBe(expected);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
versions | range | expected
|
||||||
|
${['16.0.0']} | ${'gallium'} | ${'16.0.0'}
|
||||||
|
${['16.0.0', '14.0.0', '16.9.9']} | ${'gallium'} | ${'16.0.0'}
|
||||||
|
${['15.0.0', '14.0.0']} | ${'gallium'} | ${null}
|
||||||
|
`(
|
||||||
|
'minSatisfyingVersion("$versions", "$range") === $expected',
|
||||||
|
({ versions, range, expected }) => {
|
||||||
|
expect(
|
||||||
|
lambdaVer.minSatisfyingVersion(versions as string[], range as string),
|
||||||
|
).toBe(expected);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
58
lib/modules/versioning/lambda-node/index.ts
Normal file
58
lib/modules/versioning/lambda-node/index.ts
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
import {
|
||||||
|
getNewValue,
|
||||||
|
getSatisfyingVersion,
|
||||||
|
isStable as isNodeStable,
|
||||||
|
isValid,
|
||||||
|
matches,
|
||||||
|
minSatisfyingVersion,
|
||||||
|
} from '../node';
|
||||||
|
import { findScheduleForCodename } from '../node/schedule';
|
||||||
|
import npm from '../npm';
|
||||||
|
import type { VersioningApi } from '../types';
|
||||||
|
import { findLambdaScheduleForVersion } from './schedule';
|
||||||
|
|
||||||
|
export const id = 'lambda-node';
|
||||||
|
export const displayName = 'Lambda Node.js Runtime';
|
||||||
|
export const urls = [];
|
||||||
|
export const supportsRanges = false;
|
||||||
|
|
||||||
|
function normalizeValue(value: string): string {
|
||||||
|
const schedule = findScheduleForCodename(value);
|
||||||
|
if (schedule) {
|
||||||
|
const major = schedule.version.replace('v', '');
|
||||||
|
return `^${major}`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isStable(version: string): boolean {
|
||||||
|
if (!isNodeStable(version)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const schedule = findLambdaScheduleForVersion(normalizeValue(version));
|
||||||
|
|
||||||
|
if (!schedule) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof schedule.support === 'string') {
|
||||||
|
return DateTime.local() < DateTime.fromISO(schedule.support);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const api: VersioningApi = {
|
||||||
|
...npm,
|
||||||
|
isStable,
|
||||||
|
getNewValue,
|
||||||
|
isValid,
|
||||||
|
matches,
|
||||||
|
getSatisfyingVersion,
|
||||||
|
minSatisfyingVersion,
|
||||||
|
allowUnstableMajorUpgrades: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default api;
|
12
lib/modules/versioning/lambda-node/readme.md
Normal file
12
lib/modules/versioning/lambda-node/readme.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Renovate's Lambda Node.js versioning is a wrapper around the existing Node.js Versioning module with the only difference being
|
||||||
|
that it lists versions not currently supported by AWS as being unstable. This is intended to be a drop-in replacement
|
||||||
|
for dependencies that follow the `node` versioning schedule if you need to keep them in line with Lambda Runtime
|
||||||
|
releases.
|
||||||
|
|
||||||
|
Its primary purpose is to add Node Runtime support awareness, e.g.:
|
||||||
|
|
||||||
|
- Old Runtimes that cannot be updated will be marked as unstable
|
||||||
|
- Node.js LTS releases that do not have Runtimes released for them will be marked as unstable
|
||||||
|
|
||||||
|
You can _not_ use `lambda-node` versioning to replace `docker` versioning if you are using node tags with suffixes like
|
||||||
|
`-alpine`. This is because npm versioning treats these suffixes as implying pre-releases/instability.
|
29
lib/modules/versioning/lambda-node/schedule.ts
Normal file
29
lib/modules/versioning/lambda-node/schedule.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import dataFiles from '../../../data-files.generated';
|
||||||
|
|
||||||
|
interface LambdaSchedule {
|
||||||
|
cycle: string;
|
||||||
|
releaseLabel: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Either `true` if currently in support or a string indicating the date at which support will end
|
||||||
|
*/
|
||||||
|
support: true | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LambdaData = Record<string, LambdaSchedule>;
|
||||||
|
|
||||||
|
const lambdaSchedule: LambdaData = JSON.parse(
|
||||||
|
dataFiles.get('data/lambda-node-js-schedule.json')!,
|
||||||
|
);
|
||||||
|
|
||||||
|
export function findLambdaScheduleForVersion(
|
||||||
|
version: string,
|
||||||
|
): LambdaSchedule | null {
|
||||||
|
const majorVersionMatch = version.match(/^v?([0-9]+)\./);
|
||||||
|
|
||||||
|
if (!majorVersionMatch?.[1]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lambdaSchedule[majorVersionMatch[1]];
|
||||||
|
}
|
|
@ -18,7 +18,7 @@ function normalizeValue(value: string): string {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNewValue({
|
export function getNewValue({
|
||||||
currentValue,
|
currentValue,
|
||||||
rangeStrategy,
|
rangeStrategy,
|
||||||
currentVersion,
|
currentVersion,
|
||||||
|
|
|
@ -58,7 +58,8 @@
|
||||||
"type-check": "run-s 'generate:*' 'tsc --noEmit {@}' --",
|
"type-check": "run-s 'generate:*' 'tsc --noEmit {@}' --",
|
||||||
"update-static-data": "run-s 'update-static-data:*'",
|
"update-static-data": "run-s 'update-static-data:*'",
|
||||||
"update-static-data:distro-info": "node tools/static-data/generate-distro-info.mjs",
|
"update-static-data:distro-info": "node tools/static-data/generate-distro-info.mjs",
|
||||||
"update-static-data:node-schedule": "node tools/static-data/generate-node-schedule.mjs"
|
"update-static-data:node-schedule": "node tools/static-data/generate-node-schedule.mjs",
|
||||||
|
"update-static-data:lambda-node-schedule": "node tools/static-data/generate-lambda-node-schedule.mjs"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
44
tools/static-data/generate-lambda-node-schedule.mjs
Normal file
44
tools/static-data/generate-lambda-node-schedule.mjs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import got from 'got';
|
||||||
|
import { updateJsonFile } from './utils.mjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef RuntimeDefinition
|
||||||
|
* @type {object}
|
||||||
|
* @property {string} cycle - The ID of the Runtime.
|
||||||
|
* @property {boolean|string} support - Either `true` if in support or a string denoting when support for this Runtime
|
||||||
|
* will end. 0.10.x is a sole exception which has `false` and will be filtered out.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const lambdaDataUrl = 'https://endoflife.date/api/aws-lambda.json';
|
||||||
|
|
||||||
|
await (async () => {
|
||||||
|
console.log('Generating node schedule');
|
||||||
|
const { body } = await got(lambdaDataUrl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type Array<RuntimeDefinition>
|
||||||
|
*/
|
||||||
|
const lambdas = JSON.parse(body);
|
||||||
|
const nodeRuntimes = lambdas
|
||||||
|
// Filter Runtimes down to only NodeJS Runtimes
|
||||||
|
.filter((lambda) => lambda.cycle.startsWith('nodejs'))
|
||||||
|
// The only Runtime where support is not either `true` or a Date as a string is `0.10.x`, which we don't need
|
||||||
|
.filter((lambda) => lambda.support !== false)
|
||||||
|
.reduce((schedule, lambda) => {
|
||||||
|
const versionMatch = lambda.cycle.match(/^nodejs([0-9]+)\.x$/);
|
||||||
|
|
||||||
|
if (!versionMatch?.[1]) {
|
||||||
|
return schedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...schedule,
|
||||||
|
[versionMatch[1]]: lambda,
|
||||||
|
};
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
await updateJsonFile(
|
||||||
|
'./data/lambda-node-js-schedule.json',
|
||||||
|
JSON.stringify(nodeRuntimes, null, 2),
|
||||||
|
);
|
||||||
|
})();
|
Loading…
Reference in a new issue