From c1004990ddbfae16a669605f1d0075b9ecb215db Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 31 Oct 2024 13:52:03 +0100 Subject: [PATCH 1/2] chore: automatically age out old TypeScript versions from testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In our integ tests, we were testing TypeScript versions from 3.9 up to the latest version, which recently broke because of a change to modernize the init templates. We should up this range to a recent version; the common support lifetime of a TypeScript version is the one on `DefinitelyTyped`, the types registry for TypeScript packages. They only target TS versions less than 2 years old, which at the time of this PR is 4.9 and higher. Encode that policy into code automatically, so that we don't have to manually keep this minimum version up-to-date. This currently ages out the following versions: ``` ✕ typescript 3.9 init app ✕ typescript 4.0 init app ✕ typescript 4.1 init app ✕ typescript 4.2 init app ✕ typescript 4.3 init app ✕ typescript 4.4 init app ✕ typescript 4.5 init app ✕ typescript 4.6 init app ✕ typescript 4.7 init app ✕ typescript 4.8 init app ------------------------------8< cut line ----- ✕ typescript 4.9 init app ✓ typescript 5.0 init app ✓ typescript 5.1 init app ✓ typescript 5.2 init app ✓ typescript 5.3 init app ✓ typescript 5.4 init app ✓ typescript 5.5 init app ✓ typescript 5.6 init app ``` Unfortunately not enough to save the TypeScript template modernization change entirely... but at least it's an improvement. --- .../@aws-cdk-testing/cli-integ/lib/npm.ts | 30 ++++++++++++++++++- .../init-typescript-app.integtest.ts | 11 +++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk-testing/cli-integ/lib/npm.ts b/packages/@aws-cdk-testing/cli-integ/lib/npm.ts index 0ec1052247478..fd7923c2e01ee 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/npm.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/npm.ts @@ -10,4 +10,32 @@ export function typescriptVersionsSync(): string[] { const versions: string[] = JSON.parse(stdout); return Array.from(new Set(versions.map(v => v.split('.').slice(0, 2).join('.')))); -} \ No newline at end of file +} + +/** + * Use NPM preinstalled on the machine to query publish times of versions + */ +export function typescriptVersionsYoungerThanDaysSync(days: number, versions: string[]): string[] { + const { stdout } = spawnSync('npm', ['--silent', 'view', 'typescript', 'time', '--json'], { encoding: 'utf-8' }); + const versionTsMap: Record = JSON.parse(stdout); + + const cutoffDate = new Date(Date.now() - (days * 24 * 3600 * 1000)); + const cutoffDateS = cutoffDate.toISOString(); + + const recentVersions = Object.entries(versionTsMap) + .filter(([_, dateS]) => dateS > cutoffDateS) + .map(([v]) => v); + + // Input versions are of the form 3.9, 5.2, etc. + // Actual versions are of the form `3.9.15`, `5.3.0-dev.20511311`. + // Return only 2-digit versions for which there is a non-prerelease version in the set of recentVersions + // So a 2-digit versions that is followed by `.` until the end of the string. + return versions.filter((twoV) => { + const re = new RegExp(`^${reQuote(twoV)}\\.\\d+$`); + return recentVersions.some(fullV => fullV.match(re)); + }); +} + +function reQuote(str: string): string { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} diff --git a/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts index 158764ef3c973..c035c556a6bb1 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts @@ -1,7 +1,7 @@ import { promises as fs } from 'fs'; import * as path from 'path'; import { integTest, withTemporaryDirectory, ShellHelper, withPackages, TemporaryDirectoryContext } from '../../lib'; -import { typescriptVersionsSync } from '../../lib/npm'; +import { typescriptVersionsSync, typescriptVersionsYoungerThanDaysSync } from '../../lib/npm'; ['app', 'sample-app'].forEach(template => { integTest(`typescript init ${template}`, withTemporaryDirectory(withPackages(async (context) => { @@ -19,10 +19,17 @@ import { typescriptVersionsSync } from '../../lib/npm'; }))); }); +const TYPESCRIPT_VERSION_AGE_DAYS = 2 * 365; + +const TYPESCRIPT_VERSIONS = typescriptVersionsYoungerThanDaysSync(TYPESCRIPT_VERSION_AGE_DAYS, typescriptVersionsSync()); + +// eslint-disable-next-line no-console +console.log(TYPESCRIPT_VERSIONS); + /** * Test our generated code with various versions of TypeScript */ -typescriptVersionsSync().forEach(tsVersion => { +TYPESCRIPT_VERSIONS.forEach(tsVersion => { integTest(`typescript ${tsVersion} init app`, withTemporaryDirectory(withPackages(async (context) => { const shell = ShellHelper.fromContext(context); await context.packages.makeCliAvailable(); From ca5e933bfb4d030f9f05ff411be64294c2341dd5 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 31 Oct 2024 13:57:33 +0100 Subject: [PATCH 2/2] Add comment --- .../tests/init-typescript-app/init-typescript-app.integtest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts index c035c556a6bb1..f45cfaeff0ac5 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/init-typescript-app/init-typescript-app.integtest.ts @@ -19,6 +19,7 @@ import { typescriptVersionsSync, typescriptVersionsYoungerThanDaysSync } from '. }))); }); +// Same as https://github.com/DefinitelyTyped/DefinitelyTyped?tab=readme-ov-file#support-window const TYPESCRIPT_VERSION_AGE_DAYS = 2 * 365; const TYPESCRIPT_VERSIONS = typescriptVersionsYoungerThanDaysSync(TYPESCRIPT_VERSION_AGE_DAYS, typescriptVersionsSync());