Skip to content

Commit 5f48700

Browse files
ShadowCat567Vieltojarvisobolk
authored
feat: Add option to for dependency validator to allow list dependencies 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]>
1 parent 5d6eef2 commit 5f48700

File tree

9 files changed

+216
-13
lines changed

9 files changed

+216
-13
lines changed

scripts/check_dependencies.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,20 @@ await new DependenciesValidator(
2121
],
2222
},
2323
},
24-
[['aws-cdk', 'aws-cdk-lib']]
24+
[['aws-cdk', 'aws-cdk-lib']],
25+
[
26+
{
27+
// @aws-amplify/plugin-types can depend on execa@^5.1.1 as a workaround for https://github.com/aws-amplify/amplify-backend/issues/962
28+
// all other packages must depend on execa@^8.0.1
29+
// this can be removed once execa is patched
30+
dependencyName: 'execa',
31+
globalDependencyVersion: '^8.0.1',
32+
exceptions: [
33+
{
34+
packageName: '@aws-amplify/plugin-types',
35+
dependencyVersion: '^5.1.1',
36+
},
37+
],
38+
},
39+
]
2540
).validate();

scripts/components/dependencies_validator.test.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ void describe('Dependency validator', () => {
4141
},
4242
},
4343
[],
44+
[],
4445
execaMock as never
4546
).validate(),
4647
(err: Error) => {
@@ -65,6 +66,7 @@ void describe('Dependency validator', () => {
6566
},
6667
},
6768
[],
69+
[],
6870
execaMock as never
6971
).validate(),
7072
(err: Error) => {
@@ -88,6 +90,7 @@ void describe('Dependency validator', () => {
8890
},
8991
},
9092
[],
93+
[],
9194
execaMock as never
9295
).validate();
9396
});
@@ -106,6 +109,7 @@ void describe('Dependency validator', () => {
106109
},
107110
},
108111
[],
112+
[],
109113
execaMock as never
110114
).validate(),
111115
(err: Error) => {
@@ -129,6 +133,7 @@ void describe('Dependency validator', () => {
129133
packagePaths,
130134
{},
131135
[],
136+
[],
132137
execaMock as never
133138
).validate();
134139
},
@@ -148,6 +153,108 @@ void describe('Dependency validator', () => {
148153
);
149154
});
150155

156+
void it('passes if dependency declaration that is known to be inconsistent uses multiple versions', async () => {
157+
const packagePaths = await glob(
158+
'scripts/components/test-resources/dependency-version-inconsistent-test-packages/*'
159+
);
160+
await new DependenciesValidator(
161+
packagePaths,
162+
{},
163+
[],
164+
[
165+
{
166+
dependencyName: 'glob',
167+
globalDependencyVersion: '^7.2.0',
168+
exceptions: [
169+
{
170+
packageName: 'package2',
171+
dependencyVersion: '^3.4.0',
172+
},
173+
{
174+
packageName: 'package3',
175+
dependencyVersion: '^1.6.0',
176+
},
177+
],
178+
},
179+
],
180+
execaMock as never
181+
).validate();
182+
});
183+
184+
void it('passes if multiple dependency declarations are known to be inconsistent', async () => {
185+
const packagePaths = await glob(
186+
'scripts/components/test-resources/dependency-version-multiple-inconsistencies-test-packages/*'
187+
);
188+
await new DependenciesValidator(
189+
packagePaths,
190+
{},
191+
[],
192+
[
193+
{
194+
dependencyName: 'glob',
195+
globalDependencyVersion: '^7.2.0',
196+
exceptions: [
197+
{
198+
packageName: 'package3',
199+
dependencyVersion: '^5.3.0',
200+
},
201+
],
202+
},
203+
{
204+
dependencyName: 'zod',
205+
globalDependencyVersion: '^3.8.2-alpha.6',
206+
exceptions: [
207+
{
208+
packageName: 'package2',
209+
dependencyVersion: '^2.0.0',
210+
},
211+
],
212+
},
213+
],
214+
execaMock as never
215+
).validate();
216+
});
217+
218+
void it('can detect unknown inconsistent dependency delcarations when known inconsistent dependency delcarations are present', async () => {
219+
await assert.rejects(
220+
async () => {
221+
const packagePaths = await glob(
222+
'scripts/components/test-resources/dependency-version-multiple-inconsistencies-test-packages/*'
223+
);
224+
await new DependenciesValidator(
225+
packagePaths,
226+
{},
227+
[],
228+
[
229+
{
230+
dependencyName: 'glob',
231+
globalDependencyVersion: '^7.2.0',
232+
exceptions: [
233+
{
234+
packageName: 'package3',
235+
dependencyVersion: '^5.3.0',
236+
},
237+
],
238+
},
239+
],
240+
execaMock as never
241+
).validate();
242+
},
243+
(err: Error) => {
244+
assert.ok(
245+
err.message.includes(
246+
'dependency declarations must all the on the same semver range'
247+
)
248+
);
249+
assert.ok(err.message.includes('zod'));
250+
assert.ok(err.message.includes('package1'));
251+
assert.ok(err.message.includes('package2'));
252+
assert.ok(err.message.includes('package3'));
253+
return true;
254+
}
255+
);
256+
});
257+
151258
void it('can detect inconsistent major versions of repo packages', async () => {
152259
const packagePaths = await glob(
153260
'scripts/components/test-resources/inter-repo-dependency-version-consistency-test-packages/*'
@@ -156,6 +263,7 @@ void describe('Dependency validator', () => {
156263
packagePaths,
157264
{},
158265
[],
266+
[],
159267
execaMock as never
160268
);
161269

@@ -185,6 +293,7 @@ void describe('Dependency validator', () => {
185293
packagePaths,
186294
{},
187295
[['aws-cdk', 'aws-cdk-lib']],
296+
[],
188297
execaMock as never
189298
).validate();
190299
},

scripts/components/dependencies_validator.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ export type DependencyRule =
1212
allowList: Array<string>;
1313
};
1414

15+
export type DependencyWithKnownVersionConsistencyException = {
16+
dependencyName: string;
17+
globalDependencyVersion: string;
18+
exceptions: Array<{ packageName: string; dependencyVersion: string }>;
19+
};
20+
1521
type NpmListOutputItem = {
1622
name?: string;
1723
dependencies?: Record<string, NpmListOutputItem>;
@@ -47,14 +53,16 @@ export class DependenciesValidator {
4753
/**
4854
* Creates dependency validator
4955
* @param packagePaths paths of packages to validate
50-
* @param dependencyRules dependency exclusion and inclusion rules
56+
* @param disallowedDependencies dependency exclusion and inclusion rules
5157
* @param linkedDependencies dependencies that should be versioned with the same version
58+
* @param knownInconsistentDependencyVersions dependencies that are known to violate the consistency check
5259
* @param execa in order to inject execa mock in tests
5360
*/
5461
constructor(
5562
private packagePaths: Array<string>,
56-
private dependencyRules: Record<string, DependencyRule>,
63+
private disallowedDependencies: Record<string, DependencyRule>,
5764
private linkedDependencies: Array<Array<string>>,
65+
private knownInconsistentDependencyVersions: Array<DependencyWithKnownVersionConsistencyException>,
5866
private execa = _execa
5967
) {}
6068

@@ -202,9 +210,9 @@ export class DependenciesValidator {
202210
// skip if self referencing
203211
continue;
204212
}
205-
if (dependencyName in this.dependencyRules) {
213+
if (dependencyName in this.disallowedDependencies) {
206214
const dependencyRule: DependencyRule =
207-
this.dependencyRules[dependencyName];
215+
this.disallowedDependencies[dependencyName];
208216
const isViolating =
209217
dependencyRule.denyAll ||
210218
!dependencyRule.allowList.includes(packageName);
@@ -243,20 +251,28 @@ export class DependenciesValidator {
243251
private getPackageVersionDeclarationPredicate = async (
244252
packageName: string
245253
): Promise<DependencyVersionPredicate> => {
246-
if (packageName === 'execa') {
247-
// @aws-amplify/plugin-types can depend on execa@^5.1.1 as a workaround for https://github.com/aws-amplify/amplify-backend/issues/962
248-
// all other packages must depend on execa@^8.0.1
249-
// this can be removed once execa is patched
254+
const inconsistentDependency =
255+
this.knownInconsistentDependencyVersions.find(
256+
(x) => x.dependencyName === packageName
257+
);
258+
if (inconsistentDependency) {
250259
return (declarations) => {
251260
const validationResult = declarations.every(
252261
({ dependentPackageName, version }) =>
253-
(dependentPackageName === '@aws-amplify/plugin-types' &&
254-
version === '^5.1.1') ||
255-
version === '^8.0.1'
262+
inconsistentDependency!.exceptions.find(
263+
(a) => a.packageName === dependentPackageName
264+
)?.dependencyVersion ||
265+
version === inconsistentDependency!.globalDependencyVersion
256266
);
257267
return (
258268
validationResult ||
259-
`${packageName} dependency declarations must depend on version ^8.0.1 except in @aws-amplify/plugin-types where it must depend on ^5.1.1.`
269+
`${packageName} dependency declarations must depend on version ${
270+
inconsistentDependency!.globalDependencyVersion
271+
} except in the following packages` +
272+
inconsistentDependency!.exceptions.forEach(
273+
(exception) =>
274+
`, ${exception.packageName} where it must depend on ${exception.dependencyVersion}`
275+
)
260276
);
261277
};
262278
} else if ((await this.getRepoPackageNames()).includes(packageName)) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "package1",
3+
"dependencies": {
4+
"glob": "^7.2.0"
5+
},
6+
"devDependencies": {
7+
"zod": "^3.8.2-alpha.6"
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "package2",
3+
"dependencies": {
4+
"glob": "^3.4.0"
5+
},
6+
"devDependencies": {
7+
"zod": "^3.8.2-alpha.6"
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "package2",
3+
"dependencies": {
4+
"glob": "^1.6.0"
5+
},
6+
"devDependencies": {
7+
"zod": "^3.8.2-alpha.6"
8+
}
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "package1",
3+
"dependencies": {
4+
"glob": "^7.2.0"
5+
},
6+
"devDependencies": {
7+
"zod": "^3.8.2-alpha.6"
8+
},
9+
"peerDependencies": {
10+
"yargs": "~14.2.3"
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "package2",
3+
"dependencies": {
4+
"glob": "^7.2.0"
5+
},
6+
"devDependencies": {
7+
"zod": "^2.0.0"
8+
},
9+
"peerDependencies": {
10+
"yargs": "~14.2.3"
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "package3",
3+
"dependencies": {
4+
"glob": "^5.3.0"
5+
},
6+
"devDependencies": {
7+
"zod": "^3.8.2-alpha.6"
8+
},
9+
"peerDependencies": {
10+
"yargs": "~14.2.3"
11+
}
12+
}

0 commit comments

Comments
 (0)