Skip to content

Commit

Permalink
feat: Add option to for dependency validator to allow list dependenci…
Browse files Browse the repository at this point in the history
…es that can violate consistency check (#1920)

* chore: created param to track inconsistent dependencies

* chore: changed knownInconsistentDependencyViolations to record for easier lookup

* fix: updated dependency validator to be more general in testing for known inconsistent dependencies

* chore: updated error message for incorrect verions

* chore: removed unused code

* fix: updated tests to include array for new parameter in dependendies validator

* chore: removed unnecessary comment

* chore: minor adjustment to test

* Update scripts/components/dependencies_validator.ts

Co-authored-by: Kamil Sobol <[email protected]>

* chore: changed variable name, moved find statement

* chore: added test for inconsistent dependency that has multiple versions in use

* chore: test added to check multiple dependencies that are marked as inconsistent yield correct results

* chore: added test for known vs unknown inconsistent dependencies

* chore: moved execa comment to check_dependencies.ts

* Revert "chore: moved execa comment to check_dependencies.ts"

This reverts commit 44a9051.

* chore: moved execa comment to check_dependencies from dependencies_validator

---------

Co-authored-by: Vieltojarvi <[email protected]>
Co-authored-by: Kamil Sobol <[email protected]>
  • Loading branch information
3 people authored Aug 30, 2024
1 parent 5d6eef2 commit 5f48700
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 13 deletions.
17 changes: 16 additions & 1 deletion scripts/check_dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,20 @@ await new DependenciesValidator(
],
},
},
[['aws-cdk', 'aws-cdk-lib']]
[['aws-cdk', 'aws-cdk-lib']],
[
{
// @aws-amplify/plugin-types can depend on execa@^5.1.1 as a workaround for https://github.com/aws-amplify/amplify-backend/issues/962
// all other packages must depend on execa@^8.0.1
// this can be removed once execa is patched
dependencyName: 'execa',
globalDependencyVersion: '^8.0.1',
exceptions: [
{
packageName: '@aws-amplify/plugin-types',
dependencyVersion: '^5.1.1',
},
],
},
]
).validate();
109 changes: 109 additions & 0 deletions scripts/components/dependencies_validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ void describe('Dependency validator', () => {
},
},
[],
[],
execaMock as never
).validate(),
(err: Error) => {
Expand All @@ -65,6 +66,7 @@ void describe('Dependency validator', () => {
},
},
[],
[],
execaMock as never
).validate(),
(err: Error) => {
Expand All @@ -88,6 +90,7 @@ void describe('Dependency validator', () => {
},
},
[],
[],
execaMock as never
).validate();
});
Expand All @@ -106,6 +109,7 @@ void describe('Dependency validator', () => {
},
},
[],
[],
execaMock as never
).validate(),
(err: Error) => {
Expand All @@ -129,6 +133,7 @@ void describe('Dependency validator', () => {
packagePaths,
{},
[],
[],
execaMock as never
).validate();
},
Expand All @@ -148,6 +153,108 @@ void describe('Dependency validator', () => {
);
});

void it('passes if dependency declaration that is known to be inconsistent uses multiple versions', async () => {
const packagePaths = await glob(
'scripts/components/test-resources/dependency-version-inconsistent-test-packages/*'
);
await new DependenciesValidator(
packagePaths,
{},
[],
[
{
dependencyName: 'glob',
globalDependencyVersion: '^7.2.0',
exceptions: [
{
packageName: 'package2',
dependencyVersion: '^3.4.0',
},
{
packageName: 'package3',
dependencyVersion: '^1.6.0',
},
],
},
],
execaMock as never
).validate();
});

void it('passes if multiple dependency declarations are known to be inconsistent', async () => {
const packagePaths = await glob(
'scripts/components/test-resources/dependency-version-multiple-inconsistencies-test-packages/*'
);
await new DependenciesValidator(
packagePaths,
{},
[],
[
{
dependencyName: 'glob',
globalDependencyVersion: '^7.2.0',
exceptions: [
{
packageName: 'package3',
dependencyVersion: '^5.3.0',
},
],
},
{
dependencyName: 'zod',
globalDependencyVersion: '^3.8.2-alpha.6',
exceptions: [
{
packageName: 'package2',
dependencyVersion: '^2.0.0',
},
],
},
],
execaMock as never
).validate();
});

void it('can detect unknown inconsistent dependency delcarations when known inconsistent dependency delcarations are present', async () => {
await assert.rejects(
async () => {
const packagePaths = await glob(
'scripts/components/test-resources/dependency-version-multiple-inconsistencies-test-packages/*'
);
await new DependenciesValidator(
packagePaths,
{},
[],
[
{
dependencyName: 'glob',
globalDependencyVersion: '^7.2.0',
exceptions: [
{
packageName: 'package3',
dependencyVersion: '^5.3.0',
},
],
},
],
execaMock as never
).validate();
},
(err: Error) => {
assert.ok(
err.message.includes(
'dependency declarations must all the on the same semver range'
)
);
assert.ok(err.message.includes('zod'));
assert.ok(err.message.includes('package1'));
assert.ok(err.message.includes('package2'));
assert.ok(err.message.includes('package3'));
return true;
}
);
});

void it('can detect inconsistent major versions of repo packages', async () => {
const packagePaths = await glob(
'scripts/components/test-resources/inter-repo-dependency-version-consistency-test-packages/*'
Expand All @@ -156,6 +263,7 @@ void describe('Dependency validator', () => {
packagePaths,
{},
[],
[],
execaMock as never
);

Expand Down Expand Up @@ -185,6 +293,7 @@ void describe('Dependency validator', () => {
packagePaths,
{},
[['aws-cdk', 'aws-cdk-lib']],
[],
execaMock as never
).validate();
},
Expand Down
40 changes: 28 additions & 12 deletions scripts/components/dependencies_validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ export type DependencyRule =
allowList: Array<string>;
};

export type DependencyWithKnownVersionConsistencyException = {
dependencyName: string;
globalDependencyVersion: string;
exceptions: Array<{ packageName: string; dependencyVersion: string }>;
};

type NpmListOutputItem = {
name?: string;
dependencies?: Record<string, NpmListOutputItem>;
Expand Down Expand Up @@ -47,14 +53,16 @@ export class DependenciesValidator {
/**
* Creates dependency validator
* @param packagePaths paths of packages to validate
* @param dependencyRules dependency exclusion and inclusion rules
* @param disallowedDependencies dependency exclusion and inclusion rules
* @param linkedDependencies dependencies that should be versioned with the same version
* @param knownInconsistentDependencyVersions dependencies that are known to violate the consistency check
* @param execa in order to inject execa mock in tests
*/
constructor(
private packagePaths: Array<string>,
private dependencyRules: Record<string, DependencyRule>,
private disallowedDependencies: Record<string, DependencyRule>,
private linkedDependencies: Array<Array<string>>,
private knownInconsistentDependencyVersions: Array<DependencyWithKnownVersionConsistencyException>,
private execa = _execa
) {}

Expand Down Expand Up @@ -202,9 +210,9 @@ export class DependenciesValidator {
// skip if self referencing
continue;
}
if (dependencyName in this.dependencyRules) {
if (dependencyName in this.disallowedDependencies) {
const dependencyRule: DependencyRule =
this.dependencyRules[dependencyName];
this.disallowedDependencies[dependencyName];
const isViolating =
dependencyRule.denyAll ||
!dependencyRule.allowList.includes(packageName);
Expand Down Expand Up @@ -243,20 +251,28 @@ export class DependenciesValidator {
private getPackageVersionDeclarationPredicate = async (
packageName: string
): Promise<DependencyVersionPredicate> => {
if (packageName === 'execa') {
// @aws-amplify/plugin-types can depend on execa@^5.1.1 as a workaround for https://github.com/aws-amplify/amplify-backend/issues/962
// all other packages must depend on execa@^8.0.1
// this can be removed once execa is patched
const inconsistentDependency =
this.knownInconsistentDependencyVersions.find(
(x) => x.dependencyName === packageName
);
if (inconsistentDependency) {
return (declarations) => {
const validationResult = declarations.every(
({ dependentPackageName, version }) =>
(dependentPackageName === '@aws-amplify/plugin-types' &&
version === '^5.1.1') ||
version === '^8.0.1'
inconsistentDependency!.exceptions.find(
(a) => a.packageName === dependentPackageName
)?.dependencyVersion ||
version === inconsistentDependency!.globalDependencyVersion
);
return (
validationResult ||
`${packageName} dependency declarations must depend on version ^8.0.1 except in @aws-amplify/plugin-types where it must depend on ^5.1.1.`
`${packageName} dependency declarations must depend on version ${
inconsistentDependency!.globalDependencyVersion
} except in the following packages` +
inconsistentDependency!.exceptions.forEach(
(exception) =>
`, ${exception.packageName} where it must depend on ${exception.dependencyVersion}`
)
);
};
} else if ((await this.getRepoPackageNames()).includes(packageName)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "package1",
"dependencies": {
"glob": "^7.2.0"
},
"devDependencies": {
"zod": "^3.8.2-alpha.6"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "package2",
"dependencies": {
"glob": "^3.4.0"
},
"devDependencies": {
"zod": "^3.8.2-alpha.6"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "package2",
"dependencies": {
"glob": "^1.6.0"
},
"devDependencies": {
"zod": "^3.8.2-alpha.6"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "package1",
"dependencies": {
"glob": "^7.2.0"
},
"devDependencies": {
"zod": "^3.8.2-alpha.6"
},
"peerDependencies": {
"yargs": "~14.2.3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "package2",
"dependencies": {
"glob": "^7.2.0"
},
"devDependencies": {
"zod": "^2.0.0"
},
"peerDependencies": {
"yargs": "~14.2.3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "package3",
"dependencies": {
"glob": "^5.3.0"
},
"devDependencies": {
"zod": "^3.8.2-alpha.6"
},
"peerDependencies": {
"yargs": "~14.2.3"
}
}

0 comments on commit 5f48700

Please sign in to comment.