-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(eslint-plugin): rule against invalid paths #28828
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just one minor comment.
} | ||
|
||
if (isPathJoinFuncCall(node)) { | ||
// Confirm path does not have unnecessary '..' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First: is this check against oscillating worth the squeeze? (Or is this just to make the subsequent checks easier? If so, I can dig that. Might want to write that down.)
Second: can this not be simplified in the following way:
..
may only occur in the path prefix.- So any
..
whose index is after the first non-..
is incorrect:
const components = confirmFirstArgumentIsDirnameAndRemove(node.arguments);
const firstDownDir = components.findIndex((p) => p !== '..');
if (components.some((p, i) => p === '..' && i > firstDownDir) {
// ERROR: Oscillating paths
return;
}
Then we can observe that package.json
may only exist in the very last directory that we ended up with by doing ..
: if it occurs anywhere earlier that's an error:
// Note the - 1 to exclude the last directory from the check
// Exclude the case where there are no '..' at all in the path -- those are never invalid
if (firstDownDir > 0) {
for (let i = 0; i < firstDownDir - 1; i++) {
const pjFile = path.join(...[path.dirname(currentFile), ...components.slice(0, i), 'package.json']);
if (existsSync(pjFile)) {
// ERROR: this path will end up going out of the package.json directory
return;
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take a moment to reason through this table to see how this works:
// components | firstDownDir | closest invalid package.json
['x'] 0 /* N/A */
['..', 'x'] 1 'package.json'
['..', '..', 'x'] 2 '../package.json'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh you should also add a check that /
doesn't occur anywhere inside any of the components, otherwise our checks are going to fail:
path.join(__dirname, '../../../..', 'banana')
Is bad style but works, and anything that accidentally works will occur in our code base 😅. We need to guard against it.
let forward = false; // Determines if the path is officially going forward | ||
let validPath = true; | ||
for (let i=1; i<node.arguments.length; i++) { | ||
const path = node.arguments[i].value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we confirming anywhere that the first argument to path.join()
is __dirname
? I can't find it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, in isPathJoinFuncCall
:
function isPathJoinFuncCall(node: any): boolean {
return (
node.callee?.property?.name === 'join' &&
node.arguments.length > 1 &&
node.arguments[0].name &&
node.arguments[0].name === '__dirname'
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that we don't have any rule that says path.join
must have __dirname
as the first argument, but rereading your comment suggests that that may be indeed what you are suggesting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, but just saying that we don't need to do any checks on path.join
s where the first argument ISN'T __dirname
.
// Note i + 1 here to include the current '..' in the path, since Array.slice excludes the end index. | ||
const pjFile = path.join(...[path.dirname(currentFile), ...args.slice(0, i + 1), 'package.json']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the correct implementation of your algo @rix0rrr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, you are right. Good catch!
I suppose we could also do i
in [1..firstDownDir)
as opposed to [0..firstDownDir - 1)
, and that would have avoided this i + 1
.
tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/variable-path.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conditionally approved! I'll leave you to decide what to do with the i + 1
/i - 1
business
// Note i + 1 here to include the current '..' in the path, since Array.slice excludes the end index. | ||
const pjFile = path.join(...[path.dirname(currentFile), ...args.slice(0, i + 1), 'package.json']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, you are right. Good catch!
I suppose we could also do i
in [1..firstDownDir)
as opposed to [0..firstDownDir - 1)
, and that would have avoided this i + 1
.
@Mergifyio update |
✅ Branch has been successfully updated |
packages/@aws-cdk/app-staging-synthesizer-alpha/test/app-staging-synthesizer.test.ts
Outdated
Show resolved
Hide resolved
…ng-synthesizer.test.ts
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
This is a follow up to #28658, #28772, and #28760. We had to fix multiple places where that file path extended beyond the package itself into other areas of the local repository (that would not be available after packaging). This caused myriad issues at synth time with `file not found` errors. This PR introduces a linter rule with the following specifications: - no inefficient paths, i.e. no going backwards multiple times. Ex. `path.join(__dirname, '..', 'folder', '..', 'another-folder')`. This should and can be easily simplified - no paths that go backwards past a `package.json` file. This should catch the instances we faced next time. The `yarn lint` command on `aws-cdk-lib` took 51.47s seconds without this new rule and 53.32s seconds with the rule enabled. The difference of ~2 seconds shouldn't be a hindrance in this case but I am happy to look for additional efficiencies in the rule I've written. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
This is a follow up to #28658, #28772, and #28760. We had to fix multiple places where that file path extended beyond the package itself into other areas of the local repository (that would not be available after packaging). This caused myriad issues at synth time with `file not found` errors. This PR introduces a linter rule with the following specifications: - no inefficient paths, i.e. no going backwards multiple times. Ex. `path.join(__dirname, '..', 'folder', '..', 'another-folder')`. This should and can be easily simplified - no paths that go backwards past a `package.json` file. This should catch the instances we faced next time. The `yarn lint` command on `aws-cdk-lib` took 51.47s seconds without this new rule and 53.32s seconds with the rule enabled. The difference of ~2 seconds shouldn't be a hindrance in this case but I am happy to look for additional efficiencies in the rule I've written. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
This is a follow up to #28658, #28772, and #28760. We had to fix multiple places where that file path extended beyond the package itself into other areas of the local repository (that would not be available after packaging). This caused myriad issues at synth time with
file not found
errors.This PR introduces a linter rule with the following specifications:
path.join(__dirname, '..', 'folder', '..', 'another-folder')
. This should and can be easily simplifiedpackage.json
file. This should catch the instances we faced next time.The
yarn lint
command onaws-cdk-lib
took 51.47s seconds without this new rule and 53.32s seconds with the rule enabled. The difference of ~2 seconds shouldn't be a hindrance in this case but I am happy to look for additional efficiencies in the rule I've written.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license