Repository navigation
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
Automated review A maintainer will still review this — treat the notes below as a starting point. 📌 Commit This PR extends the CLI integration-test harness ( 🔴 0 blocking · 🟡 1 recommended · ⚪ 1 optional Files with findings (2)
Generated automatically. React 👍 or 👎 to tell us whether this review helped, so we can improve these reviews. |
There was a problem hiding this comment.
See the review summary comment for the overview; the notes below are inline.
|
|
||
| public async runnerPrepare(): Promise<IPreparedRunnerSource<ITestCliSource>> { | ||
| // Pretend to be in the test directory and resolve the package | ||
| const searchPath = path.resolve(__dirname, '../../tests'); | ||
|
|
||
| let resolvedPjPath; | ||
| try { | ||
| resolvedPjPath = require.resolve(`${this.packageName}/package.json`, { | ||
| paths: [searchPath], | ||
| }); | ||
| } catch (e) { | ||
| throw new Error(`${this.packageName} not found preinstalled (searching from ${searchPath}): ${e}`); | ||
| } | ||
| const pj = JSON.parse(await readFile(resolvedPjPath, 'utf-8')); | ||
| const version = pj.version; | ||
|
|
||
| // Walk up from the resolved package.json to the `node_modules` directory it lives directly under, | ||
| // so we can add `<node_modules>/.bin` to the $PATH (same bin layout as a regular npm install). | ||
| const packageDir = path.dirname(resolvedPjPath); | ||
| const nodeModulesDir = path.resolve(packageDir, ...this.packageName.startsWith('@') ? ['..', '..'] : ['..']); |
There was a problem hiding this comment.
🟡 Recommended — RunnerCliPreinstalledSource.runnerPrepare() re-implements the resolve-and-read-version block that already exists as the static preinstalledVersion(packageName) on the library preinstalled source: the same searchPath = path.resolve(__dirname, '../../tests'), the same require.resolve("<pkg>/package.json", { paths: [searchPath] }), the same try/catch, and the same JSON.parse(readFile(...)).version. Two copies of this resolution logic will drift — a future change to the search path or error wording lands in one and not the other.
Suggested change: Extract a shared helper (e.g. resolvePreinstalledPackageJson(packageName): string) that returns the resolved package.json path, and have both the library source's preinstalledVersion and this new CLI source call it — the CLI source reads the version and derives binDir from the returned path.
| const testsNodeModules = path.resolve(__dirname, '..', 'tests', 'node_modules'); | ||
| const fakePackageDir = path.join(testsNodeModules, FAKE_PACKAGE_NAME); | ||
|
|
||
| afterEach(async () => { | ||
| await fs.rm(fakePackageDir, { recursive: true, force: true }); | ||
| }); | ||
|
|
||
| test('resolves version and .bin dir from a preinstalled package under tests/node_modules', async () => { | ||
| await fs.mkdir(fakePackageDir, { recursive: true }); | ||
| await fs.writeFile( | ||
| path.join(fakePackageDir, 'package.json'), | ||
| JSON.stringify({ name: FAKE_PACKAGE_NAME, version: '9.9.9' }), | ||
| ); |
There was a problem hiding this comment.
⚪ Optional — The test creates fakePackageDir under the real, committed tests/node_modules directory with fs.mkdir(..., { recursive: true }). When tests/node_modules does not already exist in a checkout, recursive: true creates it, but afterEach only removes fakePackageDir, so the run can leave a stray empty tests/node_modules behind in a real source directory. The fixture name is collision-proof and cleanup uses { recursive: true, force: true }, so this is not a correctness or parallel-run concern — only unwanted residue.
Suggested change: Point cleanup at the directory the test actually created (remove tests/node_modules only if the test created it), or assert that tests/node_modules already exists before writing the fixture.
…ization The test process reconstructs each package source from $SOURCES by looking up its class name in the CONSTRUCTORS list in subprocess.ts. The preinstalled sources (TestCliPreinstalledSource, TestLibraryPreinstalledSource) and TestLibraryGlobalInstallSource were never registered there, so any test using a withCdkApp-family fixture failed at TestFixture construction with 'Unrecognized constructor' once a --*-preinstalled flag was used. Register the three missing test-side source classes.
| } | ||
| } | ||
|
|
||
| export class TestCliPreinstalledSource implements ITestCliSource { |
There was a problem hiding this comment.
You can reuse TestCliNpmSource:
Just maybe rename it to TestCliSource since it really is not tied to NPM anyway.
| } | ||
|
|
||
| // Preinstalled cdk-assets: already available in node_modules/.bin or on $PATH, no network install. | ||
| if (args['cdk-assets-preinstalled']) { |
There was a problem hiding this comment.
I see the intent but I think it creates an options inflation because we also want the user to be able to pass in a custom path. So you'd need cdk-assets-preinstalled-path in addition to this.
Lets just have cdk-assets-path instead (similarly to cdk-assets-version which we already have). So if a user wants to use a pre-installed package, they must tell us where is it installed.
| * | ||
| * Resolves the package with `require.resolve`, so this performs no npm network calls. | ||
| */ | ||
| export class RunnerCliPreinstalledSource implements IRunnerSource<ITestCliSource> { |
There was a problem hiding this comment.
| export class RunnerCliPreinstalledSource implements IRunnerSource<ITestCliSource> { | |
| export class RunnerCliPathSource implements IRunnerSource<ITestCliSource> { |
|
|
||
| public async runnerPrepare(): Promise<IPreparedRunnerSource<ITestCliSource>> { | ||
| // Pretend to be in the test directory and resolve the package | ||
| const searchPath = path.resolve(__dirname, '../../tests'); | ||
|
|
||
| let resolvedPjPath; | ||
| try { | ||
| resolvedPjPath = require.resolve(`${this.packageName}/package.json`, { | ||
| paths: [searchPath], | ||
| }); | ||
| } catch (e) { | ||
| throw new Error(`${this.packageName} not found preinstalled (searching from ${searchPath}): ${e}`); | ||
| } | ||
| const pj = JSON.parse(await readFile(resolvedPjPath, 'utf-8')); | ||
| const version = pj.version; | ||
|
|
||
| // Walk up from the resolved package.json to the `node_modules` directory it lives directly under, | ||
| // so we can add `<node_modules>/.bin` to the $PATH (same bin layout as a regular npm install). | ||
| const packageDir = path.dirname(resolvedPjPath); | ||
| const nodeModulesDir = path.resolve(packageDir, ...this.packageName.startsWith('@') ? ['..', '..'] : ['..']); |
This pr adds a consistent "preinstalled" option across
run-suite's 4 test dependencies (aws-cdk,cdk-assets,aws-cdk-lib,@aws-cdk/toolkit-lib). This feature helps so thatrun-suitecan run in an isolated environment where every dependency has already been installed ahead of time.Currently, we resolve its four deps through package sources. Based on the selected source, resolution uses
npm installornpm viewagainst the public registry.@aws-cdk/toolkit-libalready had aRunnerLibraryPreinstalledSource, but it was only reachable through an auto-detect fallback, and the other three dependencies had no equivalent at all.I'm also adding 2 unit tests for this use case. The first one drops a fake package into the target directory and directs the source to find and use it. The second one asserts on an error thrown if no package is found.
Furthermore, to verify, the below command passes with 0 internet
We kick off the test run with the pre-installed sources but don't run any tests. This is because the tests themselves have npm installs in them and I wanted to separate concerns.
Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license