From 1f6ee736540bd6387be3743d87a9202b18391110 Mon Sep 17 00:00:00 2001 From: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> Date: Fri, 2 Feb 2024 15:19:53 -0500 Subject: [PATCH] chore(eslint-plugin): rule against invalid paths (#28828) 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* --- .../test/http/integ.lambda.ts | 4 +- .../test/http/integ.user-pool.ts | 2 +- .../aws-appsync/test/integ.appsync-lambda.ts | 2 +- .../aws-appsync/test/integ.js-resolver.ts | 2 +- .../aws-appsync/test/integ.lambda-auth.ts | 2 +- ...integ.pipeline-elastic-beanstalk-deploy.ts | 2 +- .../test/ec2/integ.environment-file.ts | 4 +- .../test/integ.two-products.ts | 4 +- .../app-staging-synthesizer-alpha/README.md | 2 +- .../aws-amplify-alpha/test/branch.test.ts | 2 +- .../test/integ.app-asset-deployment.ts | 2 +- .../@aws-cdk/aws-apprunner-alpha/README.md | 2 +- .../test/integ.service-ecr.ts | 2 +- .../aws-apprunner-alpha/test/service.test.ts | 6 +- .../@aws-cdk/aws-gamelift-alpha/README.md | 2 +- .../test/integ.matchmaking-ruleset.ts | 2 +- .../integ.queued-matchmaking-configuration.ts | 2 +- ...eg.standalone-matchmaking-configuration.ts | 2 +- .../test/matchmaking-ruleset-body.test.ts | 6 +- packages/@aws-cdk/aws-glue-alpha/README.md | 6 +- .../@aws-cdk/aws-glue-alpha/test/code.test.ts | 2 +- .../test/integ.job-python-shell.ts | 2 +- .../@aws-cdk/aws-glue-alpha/test/integ.job.ts | 2 +- .../aws-lambda-go-alpha/lib/bundling.ts | 2 +- .../aws-lambda-go-alpha/test/docker.test.ts | 2 +- .../aws-lambda-go-alpha/test/function.test.ts | 22 ++--- .../test/integ.function.provided.al2023.ts | 2 +- .../test/integ.function.ts | 2 +- .../aws-lambda-python-alpha/lib/bundling.ts | 2 +- .../test/bundling.test.ts | 4 +- .../test/layer.test.ts | 2 +- packages/@aws-cdk/integ-runner/lib/cli.ts | 2 +- .../test/runner/snapshot-test-runner.test.ts | 2 +- .../test/workers/integ-worker.test.ts | 2 +- .../test/workers/snapshot-worker.test.ts | 2 +- .../test/appsync-caching-config.test.ts | 2 +- .../aws-appsync/test/appsync-lambda.test.ts | 6 +- .../test/appsync-mapping-template.test.ts | 2 +- .../aws-ec2/test/cfn-init-element.test.ts | 4 +- .../aws-ecs/test/container-definition.test.ts | 6 +- .../test/ec2/ec2-task-definition.test.ts | 2 +- .../aws-ecs/test/environment-file.test.ts | 2 +- .../external/external-task-definition.test.ts | 2 +- packages/aws-cdk-lib/aws-eks/lib/cluster.ts | 2 +- .../aws-cdk-lib/aws-eks/test/cluster.test.ts | 8 +- .../aws-lambda-nodejs/lib/bundling.ts | 2 +- .../aws-lambda-nodejs/test/bundling.test.ts | 2 +- .../aws-lambda-nodejs/test/docker.test.ts | 2 +- .../test/batch/run-batch-job.test.ts | 2 +- .../test/batch/submit-job.test.ts | 2 +- .../aws-cdk-lib/core/test/bundling.test.ts | 4 +- .../cx-api/build-tools/update-vnext.ts | 3 +- .../aws-cdk-lib/cx-api/test/features.test.ts | 3 +- packages/aws-cdk/test/notices.test.ts | 12 +-- packages/aws-cdk/test/tree.test.ts | 4 +- .../cdk-build-tools/config/eslintrc.js | 1 + .../cdk-build-tools/lib/package-info.ts | 2 + tools/@aws-cdk/eslint-plugin/README.md | 5 +- tools/@aws-cdk/eslint-plugin/lib/index.ts | 1 + .../lib/rules/no-invalid-path.ts | 91 +++++++++++++++++++ .../eslint-plugin/test/rules/fixtures.test.ts | 2 +- .../fixtures/no-invalid-path/eslintrc.js | 6 ++ .../no-invalid-path/no-path.error.txt | 1 + .../rules/fixtures/no-invalid-path/no-path.ts | 3 + .../path-beyond-packagejson.error.txt | 1 + .../path-beyond-packagejson.ts | 4 + .../no-invalid-path/path-oscillates.error.txt | 1 + .../no-invalid-path/path-oscillates.ts | 3 + .../path-with-slashes.error.txt | 1 + .../no-invalid-path/path-with-slashes.ts | 3 + .../no-invalid-path/within-function.error.txt | 1 + .../no-invalid-path/within-function.ts | 5 + 72 files changed, 221 insertions(+), 92 deletions(-) create mode 100644 tools/@aws-cdk/eslint-plugin/lib/rules/no-invalid-path.ts create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/eslintrc.js create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.error.txt create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.ts create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.error.txt create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.ts create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.error.txt create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.ts create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.error.txt create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.ts create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.error.txt create mode 100644 tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts index 42bd3fd61c345..a184183d514f0 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts @@ -18,7 +18,7 @@ const stack = new Stack(app, 'AuthorizerInteg'); const authHandler = new lambda.Function(stack, 'auth-function', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', - code: lambda.Code.fromAsset(path.join(__dirname, '../auth-handler')), + code: lambda.Code.fromAsset(path.join(__dirname, '..', 'auth-handler')), }); const authorizer = new HttpLambdaAuthorizer('LambdaAuthorizer', authHandler, { @@ -41,7 +41,7 @@ const httpApiWithDefaultAuthorizer = new HttpApi(stack, 'MyHttpApiWithDefaultAut const handler = new lambda.Function(stack, 'lambda', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', - code: lambda.AssetCode.fromAsset(path.join(__dirname, '../integ.lambda.handler')), + code: lambda.AssetCode.fromAsset(path.join(__dirname, '..', 'integ.lambda.handler')), }); httpApi.addRoutes({ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts index 45016d6d6e85e..0704a91dc893a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts @@ -31,7 +31,7 @@ const httpApiWithDefaultAuthorizer = new HttpApi(stack, 'MyHttpApiWithDefaultAut const handler = new lambda.Function(stack, 'lambda', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', - code: lambda.AssetCode.fromAsset(path.join(__dirname, '../integ.user-pool.handler')), + code: lambda.AssetCode.fromAsset(path.join(__dirname, '..', 'integ.user-pool.handler')), }); httpApi.addRoutes({ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-lambda.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-lambda.ts index 106d73850eeb1..0ff2716d500c0 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-lambda.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-lambda.ts @@ -28,7 +28,7 @@ const api = new appsync.GraphqlApi(stack, 'LambdaAPI', { }); const func = new lambda.Function(stack, 'func', { - code: lambda.Code.fromAsset(path.join(__dirname, 'verify/lambda-tutorial')), + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'lambda-tutorial')), handler: 'lambda-tutorial.handler', runtime: STANDARD_NODEJS_RUNTIME, }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.js-resolver.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.js-resolver.ts index 8ba10b77e8f3b..be6d9b04bd317 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.js-resolver.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.js-resolver.ts @@ -58,7 +58,7 @@ const integ = new IntegTest(app, 'JsResolverIntegTest', { testCases: [stack] }); * Handler that calls our api with an `addTest` Mutation */ const invoke = new lambda.Function(stack, 'InvokeApi', { - code: lambda.Code.fromAsset(path.join(__dirname, 'integ-assets/js-resolver-assertion')), + code: lambda.Code.fromAsset(path.join(__dirname, 'integ-assets', 'js-resolver-assertion')), handler: 'index.handler', runtime: lambda.Runtime.NODEJS_18_X, }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.lambda-auth.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.lambda-auth.ts index aa39097be802c..ed955f56520f5 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.lambda-auth.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.lambda-auth.ts @@ -12,7 +12,7 @@ class GraphQLApiLambdaAuthStack extends cdk.Stack { const func = new lambda.Function(this, 'func', { code: lambda.Code.fromAsset( - path.join(__dirname, 'verify/lambda-tutorial'), + path.join(__dirname, 'verify', 'lambda-tutorial'), ), handler: 'lambda-tutorial.handler', runtime: STANDARD_NODEJS_RUNTIME, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts index 559e98fe4942c..32b44ba03f8d3 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-codepipeline-actions/test/integ.pipeline-elastic-beanstalk-deploy.ts @@ -32,7 +32,7 @@ const bucket = new s3.Bucket(stack, 'PipelineBucket', { }); const artifact = new deploy.BucketDeployment(stack, 'DeployApp', { - sources: [deploy.Source.asset(path.join(__dirname, 'assets/nodejs.zip'))], + sources: [deploy.Source.asset(path.join(__dirname, 'assets', 'nodejs.zip'))], destinationBucket: bucket, extract: false, }); diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts index dc5a0448a65ed..2a862f4de6c19 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-ecs/test/ec2/integ.environment-file.ts @@ -49,13 +49,13 @@ const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDefinition', { // deploy an envfile to S3 and delete when the bucket is deleted const envFileDeployment = new s3deployment.BucketDeployment(stack, 'EnvFileDeployment', { destinationBucket: bucket, - sources: [s3deployment.Source.asset(path.join(__dirname, '../demo-envfiles'))], + sources: [s3deployment.Source.asset(path.join(__dirname, '..', 'demo-envfiles'))], }); // define container with envfiles - one from local disk and another from S3 const containerDefinition = new ecs.ContainerDefinition(stack, 'Container', { environmentFiles: [ - ecs.EnvironmentFile.fromAsset(path.join(__dirname, '../demo-envfiles/test-envfile.env')), + ecs.EnvironmentFile.fromAsset(path.join(__dirname, '..', 'demo-envfiles', 'test-envfile.env')), ecs.EnvironmentFile.fromBucket(bucket, 'test-envfile.env'), ], image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.two-products.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.two-products.ts index f66f6b6060301..6c4902fcd2073 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.two-products.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.two-products.ts @@ -64,7 +64,7 @@ class TestAssetProductStack1 extends servicecatalog.ProductStack { new lambda.Function(this, 'HelloHandler', { runtime: lambda.Runtime.PYTHON_3_9, - code: lambda.Code.fromAsset(path.join(__dirname, './assets')), + code: lambda.Code.fromAsset(path.join(__dirname, 'assets')), handler: 'index.handler', }); } @@ -76,7 +76,7 @@ class TestAssetProductStack2 extends servicecatalog.ProductStack { new lambda.Function(this, 'HelloHandler2', { runtime: lambda.Runtime.PYTHON_3_9, - code: lambda.Code.fromAsset(path.join(__dirname, './assetsv2')), + code: lambda.Code.fromAsset(path.join(__dirname, 'assetsv2')), handler: 'index.handler', }); } diff --git a/packages/@aws-cdk/app-staging-synthesizer-alpha/README.md b/packages/@aws-cdk/app-staging-synthesizer-alpha/README.md index 6b430868f9865..8664303213f26 100644 --- a/packages/@aws-cdk/app-staging-synthesizer-alpha/README.md +++ b/packages/@aws-cdk/app-staging-synthesizer-alpha/README.md @@ -213,7 +213,7 @@ import { Asset } from 'aws-cdk-lib/aws-s3-assets'; declare const stack: Stack; const asset = new Asset(stack, 'deploy-time-asset', { deployTime: true, - path: path.join(__dirname, './deploy-time-asset'), + path: path.join(__dirname, 'deploy-time-asset'), }); ``` diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/branch.test.ts b/packages/@aws-cdk/aws-amplify-alpha/test/branch.test.ts index c4b7a6ac2f4e3..a0146ed84474a 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/test/branch.test.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/test/branch.test.ts @@ -105,7 +105,7 @@ test('with env vars', () => { test('with asset deployment', () => { // WHEN const asset = new Asset(app, 'SampleAsset', { - path: path.join(__dirname, './test-asset'), + path: path.join(__dirname, 'test-asset'), }); app.addBranch('dev', { asset }); diff --git a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-asset-deployment.ts b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-asset-deployment.ts index 73d2923233e4b..90043ad124051 100644 --- a/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-asset-deployment.ts +++ b/packages/@aws-cdk/aws-amplify-alpha/test/integ.app-asset-deployment.ts @@ -10,7 +10,7 @@ class TestStack extends Stack { super(scope, id, props); const asset = new Asset(this, 'SampleAsset', { - path: path.join(__dirname, './test-asset'), + path: path.join(__dirname, 'test-asset'), }); const amplifyApp = new amplify.App(this, 'App', {}); diff --git a/packages/@aws-cdk/aws-apprunner-alpha/README.md b/packages/@aws-cdk/aws-apprunner-alpha/README.md index 2e85bb3730cd5..1cc9363c8c139 100644 --- a/packages/@aws-cdk/aws-apprunner-alpha/README.md +++ b/packages/@aws-cdk/aws-apprunner-alpha/README.md @@ -74,7 +74,7 @@ You can specify whether to enable continuous integration from the source reposit import * as assets from 'aws-cdk-lib/aws-ecr-assets'; const imageAsset = new assets.DockerImageAsset(this, 'ImageAssets', { - directory: path.join(__dirname, './docker.assets'), + directory: path.join(__dirname, 'docker.assets'), }); new apprunner.Service(this, 'Service', { source: apprunner.Source.fromAsset({ diff --git a/packages/@aws-cdk/aws-apprunner-alpha/test/integ.service-ecr.ts b/packages/@aws-cdk/aws-apprunner-alpha/test/integ.service-ecr.ts index d6e7d10b692ac..012132a75e2e0 100644 --- a/packages/@aws-cdk/aws-apprunner-alpha/test/integ.service-ecr.ts +++ b/packages/@aws-cdk/aws-apprunner-alpha/test/integ.service-ecr.ts @@ -9,7 +9,7 @@ const stack = new cdk.Stack(app, 'integ-apprunner'); // Scenario 3: Create the service from local code assets const imageAsset = new assets.DockerImageAsset(stack, 'ImageAssets', { - directory: path.join(__dirname, './docker.assets'), + directory: path.join(__dirname, 'docker.assets'), }); const service3 = new Service(stack, 'Service3', { source: Source.fromAsset({ diff --git a/packages/@aws-cdk/aws-apprunner-alpha/test/service.test.ts b/packages/@aws-cdk/aws-apprunner-alpha/test/service.test.ts index d73b9cf0d7a16..d4ef80d552bd1 100644 --- a/packages/@aws-cdk/aws-apprunner-alpha/test/service.test.ts +++ b/packages/@aws-cdk/aws-apprunner-alpha/test/service.test.ts @@ -574,7 +574,7 @@ test('create a service with local assets(image repository type: ECR)', () => { const stack = new cdk.Stack(app, 'demo-stack'); // WHEN const dockerAsset = new ecr_assets.DockerImageAsset(stack, 'Assets', { - directory: path.join(__dirname, './docker.assets'), + directory: path.join(__dirname, 'docker.assets'), }); new apprunner.Service(stack, 'DemoService', { source: apprunner.Source.fromAsset({ @@ -864,7 +864,7 @@ test('custom IAM access role and instance role are allowed', () => { const stack = new cdk.Stack(app, 'demo-stack'); // WHEN const dockerAsset = new ecr_assets.DockerImageAsset(stack, 'Assets', { - directory: path.join(__dirname, './docker.assets'), + directory: path.join(__dirname, 'docker.assets'), }); new apprunner.Service(stack, 'DemoService', { source: apprunner.Source.fromAsset({ @@ -1177,7 +1177,7 @@ test('autoDeploymentsEnabled flag is set true', () => { const stack = new cdk.Stack(app, 'demo-stack'); // WHEN const dockerAsset = new ecr_assets.DockerImageAsset(stack, 'Assets', { - directory: path.join(__dirname, './docker.assets'), + directory: path.join(__dirname, 'docker.assets'), }); new apprunner.Service(stack, 'DemoService', { source: apprunner.Source.fromAsset({ diff --git a/packages/@aws-cdk/aws-gamelift-alpha/README.md b/packages/@aws-cdk/aws-gamelift-alpha/README.md index 64aa5ae057532..8dcccd6d4c5aa 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/README.md +++ b/packages/@aws-cdk/aws-gamelift-alpha/README.md @@ -99,7 +99,7 @@ match is made after 30 seconds, gradually relax the skill requirements. ```ts new gamelift.MatchmakingRuleSet(this, 'RuleSet', { matchmakingRuleSetName: 'my-test-ruleset', - content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset/ruleset.json')), + content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset', 'ruleset.json')), }); ``` diff --git a/packages/@aws-cdk/aws-gamelift-alpha/test/integ.matchmaking-ruleset.ts b/packages/@aws-cdk/aws-gamelift-alpha/test/integ.matchmaking-ruleset.ts index e2f2ffb723f18..f28c51db2e553 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/test/integ.matchmaking-ruleset.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/test/integ.matchmaking-ruleset.ts @@ -11,7 +11,7 @@ class TestStack extends cdk.Stack { const ruleSet = new gamelift.MatchmakingRuleSet(this, 'MatchmakingRuleSet', { matchmakingRuleSetName: 'my-test-ruleset', - content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset/ruleset.json')), + content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset', 'ruleset.json')), }); new CfnOutput(this, 'MatchmakingRuleSetArn', { value: ruleSet.matchmakingRuleSetArn }); diff --git a/packages/@aws-cdk/aws-gamelift-alpha/test/integ.queued-matchmaking-configuration.ts b/packages/@aws-cdk/aws-gamelift-alpha/test/integ.queued-matchmaking-configuration.ts index 696137c0c14d2..2d2b8310bb23c 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/test/integ.queued-matchmaking-configuration.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/test/integ.queued-matchmaking-configuration.ts @@ -12,7 +12,7 @@ class TestStack extends cdk.Stack { const ruleSet = new gamelift.MatchmakingRuleSet(this, 'QueuedMatchmakingConfiguration', { matchmakingRuleSetName: 'my-test-ruleset', - content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset/ruleset.json')), + content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset', 'ruleset.json')), }); const build = new gamelift.Build(this, 'Build', { diff --git a/packages/@aws-cdk/aws-gamelift-alpha/test/integ.standalone-matchmaking-configuration.ts b/packages/@aws-cdk/aws-gamelift-alpha/test/integ.standalone-matchmaking-configuration.ts index ffe775515c306..96664d2f5b197 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/test/integ.standalone-matchmaking-configuration.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/test/integ.standalone-matchmaking-configuration.ts @@ -11,7 +11,7 @@ class TestStack extends cdk.Stack { const ruleSet = new gamelift.MatchmakingRuleSet(this, 'StandaloneMatchmakingConfiguration', { matchmakingRuleSetName: 'my-test-ruleset', - content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset/ruleset.json')), + content: gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset', 'ruleset.json')), }); const matchmakingConfiguration = new gamelift.StandaloneMatchmakingConfiguration(this, 'MyStandaloneMatchmakingConfiguration', { diff --git a/packages/@aws-cdk/aws-gamelift-alpha/test/matchmaking-ruleset-body.test.ts b/packages/@aws-cdk/aws-gamelift-alpha/test/matchmaking-ruleset-body.test.ts index f0603ad324ac3..16e53ee71053d 100644 --- a/packages/@aws-cdk/aws-gamelift-alpha/test/matchmaking-ruleset-body.test.ts +++ b/packages/@aws-cdk/aws-gamelift-alpha/test/matchmaking-ruleset-body.test.ts @@ -35,14 +35,14 @@ describe('MatchmakingRuleSetBody', () => { describe('gamelift.MatchmakingRuleSetBody.fromJsonFile', () => { test('new RuleSetBody from Json file', () => { - const ruleSet = gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset/ruleset.json')); + const ruleSet = gamelift.RuleSetContent.fromJsonFile(path.join(__dirname, 'my-ruleset', 'ruleset.json')); const content = ruleSet.bind(stack); - const result = JSON.parse(fs.readFileSync(path.join(__dirname, 'my-ruleset/ruleset.json')).toString()); + const result = JSON.parse(fs.readFileSync(path.join(__dirname, 'my-ruleset', 'ruleset.json')).toString()); expect(content.ruleSetBody).toEqual(JSON.stringify(result)); }); test('fails if file not exist', () => { - const content = path.join(__dirname, 'my-ruleset/file-not-exist.json'); + const content = path.join(__dirname, 'my-ruleset', 'file-not-exist.json'); expect(() => gamelift.RuleSetContent.fromJsonFile(content)) .toThrow(`RuleSet path does not exist, please verify it, actual ${content}`); }); diff --git a/packages/@aws-cdk/aws-glue-alpha/README.md b/packages/@aws-cdk/aws-glue-alpha/README.md index 67018d6559724..051044a74c8ff 100644 --- a/packages/@aws-cdk/aws-glue-alpha/README.md +++ b/packages/@aws-cdk/aws-glue-alpha/README.md @@ -60,7 +60,7 @@ new glue.Job(this, 'PythonSparkStreamingJob', { executable: glue.JobExecutable.pythonStreaming({ glueVersion: glue.GlueVersion.V4_0, pythonVersion: glue.PythonVersion.THREE, - script: glue.Code.fromAsset(path.join(__dirname, 'job-script/hello_world.py')), + script: glue.Code.fromAsset(path.join(__dirname, 'job-script', 'hello_world.py')), }), description: 'an example Python Streaming job', }); @@ -97,7 +97,7 @@ new glue.Job(this, 'RayJob', { glueVersion: glue.GlueVersion.V4_0, pythonVersion: glue.PythonVersion.THREE_NINE, runtime: glue.Runtime.RAY_TWO_FOUR, - script: glue.Code.fromAsset(path.join(__dirname, 'job-script/hello_world.py')), + script: glue.Code.fromAsset(path.join(__dirname, 'job-script', 'hello_world.py')), }), workerType: glue.WorkerType.Z_2X, workerCount: 2, @@ -118,7 +118,7 @@ new glue.Job(this, 'EnableSparkUI', { executable: glue.JobExecutable.pythonEtl({ glueVersion: glue.GlueVersion.V3_0, pythonVersion: glue.PythonVersion.THREE, - script: glue.Code.fromAsset(path.join(__dirname, 'job-script/hello_world.py')), + script: glue.Code.fromAsset(path.join(__dirname, 'job-script', 'hello_world.py')), }), }); ``` diff --git a/packages/@aws-cdk/aws-glue-alpha/test/code.test.ts b/packages/@aws-cdk/aws-glue-alpha/test/code.test.ts index f67d6f71526b4..9b213cd891134 100644 --- a/packages/@aws-cdk/aws-glue-alpha/test/code.test.ts +++ b/packages/@aws-cdk/aws-glue-alpha/test/code.test.ts @@ -85,7 +85,7 @@ describe('Code', () => { }); describe('.fromAsset()', () => { - const filePath = path.join(__dirname, 'job-script/hello_world.py'); + const filePath = path.join(__dirname, 'job-script', 'hello_world.py'); const directoryPath = path.join(__dirname, 'job-script'); beforeEach(() => { diff --git a/packages/@aws-cdk/aws-glue-alpha/test/integ.job-python-shell.ts b/packages/@aws-cdk/aws-glue-alpha/test/integ.job-python-shell.ts index 4e283327f0ad4..a08a19713b9a7 100644 --- a/packages/@aws-cdk/aws-glue-alpha/test/integ.job-python-shell.ts +++ b/packages/@aws-cdk/aws-glue-alpha/test/integ.job-python-shell.ts @@ -22,7 +22,7 @@ const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-glue-job-python-shell'); -const script = glue.Code.fromAsset(path.join(__dirname, 'job-script/hello_world.py')); +const script = glue.Code.fromAsset(path.join(__dirname, 'job-script', 'hello_world.py')); new glue.Job(stack, 'ShellJob', { jobName: 'ShellJob', diff --git a/packages/@aws-cdk/aws-glue-alpha/test/integ.job.ts b/packages/@aws-cdk/aws-glue-alpha/test/integ.job.ts index aa420c52eccf4..c16b5f9691ae1 100644 --- a/packages/@aws-cdk/aws-glue-alpha/test/integ.job.ts +++ b/packages/@aws-cdk/aws-glue-alpha/test/integ.job.ts @@ -21,7 +21,7 @@ const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-glue-job'); -const script = glue.Code.fromAsset(path.join(__dirname, 'job-script/hello_world.py')); +const script = glue.Code.fromAsset(path.join(__dirname, 'job-script', 'hello_world.py')); [glue.GlueVersion.V2_0, glue.GlueVersion.V3_0, glue.GlueVersion.V4_0].forEach((glueVersion) => { const etlJob = new glue.Job(stack, 'EtlJob' + glueVersion.name, { diff --git a/packages/@aws-cdk/aws-lambda-go-alpha/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-go-alpha/lib/bundling.ts index de91e04bb360d..303b12f8b76d3 100644 --- a/packages/@aws-cdk/aws-lambda-go-alpha/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-go-alpha/lib/bundling.ts @@ -143,7 +143,7 @@ export class Bundling implements cdk.BundlingOptions { // Docker bundling const shouldBuildImage = props.forcedDockerBundling || !Bundling.runsLocally; this.image = shouldBuildImage - ? props.dockerImage ?? cdk.DockerImage.fromBuild(path.join(__dirname, '../lib'), { + ? props.dockerImage ?? cdk.DockerImage.fromBuild(path.join(__dirname, '..', 'lib'), { buildArgs: { ...props.buildArgs ?? {}, IMAGE: Runtime.GO_1_X.bundlingImage.image, // always use the GO_1_X build image diff --git a/packages/@aws-cdk/aws-lambda-go-alpha/test/docker.test.ts b/packages/@aws-cdk/aws-lambda-go-alpha/test/docker.test.ts index c67b2feac5ca7..9f25c23da4651 100644 --- a/packages/@aws-cdk/aws-lambda-go-alpha/test/docker.test.ts +++ b/packages/@aws-cdk/aws-lambda-go-alpha/test/docker.test.ts @@ -3,7 +3,7 @@ import * as path from 'path'; const docker = process.env.CDK_DOCKER ?? 'docker'; beforeAll(() => { - spawnSync(docker, ['build', '-t', 'golang', path.join(__dirname, '../lib')]); + spawnSync(docker, ['build', '-t', 'golang', path.join(__dirname, '..', 'lib')]); }); test('golang is available', async () => { diff --git a/packages/@aws-cdk/aws-lambda-go-alpha/test/function.test.ts b/packages/@aws-cdk/aws-lambda-go-alpha/test/function.test.ts index d557ea2d2fcda..c1989bbc4acbb 100644 --- a/packages/@aws-cdk/aws-lambda-go-alpha/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-go-alpha/test/function.test.ts @@ -27,7 +27,7 @@ beforeEach(() => { test('GoFunction with defaults', () => { // WHEN new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), }); expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ @@ -43,7 +43,7 @@ test('GoFunction with defaults', () => { test('GoFunction with using provided runtime', () => { // WHEN new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), runtime: Runtime.PROVIDED, }); @@ -60,7 +60,7 @@ test('GoFunction with using provided runtime', () => { test('GoFunction with using golang runtime', () => { // WHEN new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), runtime: Runtime.GO_1_X, }); @@ -77,7 +77,7 @@ test('GoFunction with using golang runtime', () => { test('GoFunction with container env vars', () => { // WHEN new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), bundling: { environment: { KEY: 'VALUE', @@ -94,7 +94,7 @@ test('GoFunction with container env vars', () => { test('throws with the wrong runtime family', () => { expect(() => new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), runtime: Runtime.PYTHON_3_8, })).toThrow(/Only `go` and `provided` runtimes are supported/); }); @@ -102,7 +102,7 @@ test('throws with the wrong runtime family', () => { test('resolves entry to an absolute path', () => { // WHEN new GoFunction(stack, 'fn', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api/main.go'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api', 'main.go'), }); expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ @@ -112,21 +112,21 @@ test('resolves entry to an absolute path', () => { test('throws with no existing go.mod file', () => { expect(() => new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), moduleDir: '/does/not/exist/go.mod', })).toThrow(/go.mod file at \/does\/not\/exist\/go.mod doesn't exist/); }); test('throws with incorrect moduleDir file', () => { expect(() => new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), moduleDir: '/does/not/exist.mod', })).toThrow(/moduleDir is specifying a file that is not go.mod/); }); test('custom moduleDir can be used', () => { new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), moduleDir: path.join(__dirname, 'lambda-handler-vendor'), }); @@ -137,8 +137,8 @@ test('custom moduleDir can be used', () => { test('custom moduleDir with file path can be used', () => { new GoFunction(stack, 'handler', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), - moduleDir: path.join(__dirname, 'lambda-handler-vendor/go.mod'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), + moduleDir: path.join(__dirname, 'lambda-handler-vendor', 'go.mod'), }); Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { diff --git a/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.provided.al2023.ts b/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.provided.al2023.ts index bf2d4945812a6..128a5727b290c 100644 --- a/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.provided.al2023.ts +++ b/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.provided.al2023.ts @@ -15,7 +15,7 @@ class TestStack extends Stack { super(scope, id, props); new lambda.GoFunction(this, 'go-handler-docker', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), runtime: Runtime.PROVIDED_AL2023, bundling: { forcedDockerBundling: true, diff --git a/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.ts b/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.ts index 7d6e4afebcf84..ee5a0898c03f8 100644 --- a/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.ts +++ b/packages/@aws-cdk/aws-lambda-go-alpha/test/integ.function.ts @@ -13,7 +13,7 @@ class TestStack extends Stack { super(scope, id, props); new lambda.GoFunction(this, 'go-handler-docker', { - entry: path.join(__dirname, 'lambda-handler-vendor/cmd/api'), + entry: path.join(__dirname, 'lambda-handler-vendor', 'cmd', 'api'), bundling: { forcedDockerBundling: true, goBuildFlags: ['-mod=readonly', '-ldflags "-s -w"'], diff --git a/packages/@aws-cdk/aws-lambda-python-alpha/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-python-alpha/lib/bundling.ts index de64c44908706..dc489300d63d4 100644 --- a/packages/@aws-cdk/aws-lambda-python-alpha/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-python-alpha/lib/bundling.ts @@ -99,7 +99,7 @@ export class Bundling implements CdkBundlingOptions { assetExcludes, }); - this.image = image ?? DockerImage.fromBuild(path.join(__dirname, '../lib'), { + this.image = image ?? DockerImage.fromBuild(path.join(__dirname, '..', 'lib'), { buildArgs: { ...props.buildArgs, IMAGE: runtime.bundlingImage.image, diff --git a/packages/@aws-cdk/aws-lambda-python-alpha/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-python-alpha/test/bundling.test.ts index a05fc4dab6834..54b61b3c03a34 100644 --- a/packages/@aws-cdk/aws-lambda-python-alpha/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-python-alpha/test/bundling.test.ts @@ -42,7 +42,7 @@ test('Bundling a function without dependencies', () => { }), })); - expect(DockerImage.fromBuild).toHaveBeenCalledWith(expect.stringMatching(path.join(__dirname, '../lib')), expect.objectContaining({ + expect(DockerImage.fromBuild).toHaveBeenCalledWith(expect.stringMatching(path.join(__dirname, '..', 'lib')), expect.objectContaining({ buildArgs: expect.objectContaining({ IMAGE: expect.stringMatching(/build-python/), }), @@ -394,7 +394,7 @@ test('Bundling with custom build args', () => { buildArgs: { PIP_INDEX_URL: testPypi }, }); - expect(DockerImage.fromBuild).toHaveBeenCalledWith(expect.stringMatching(path.join(__dirname, '../lib')), expect.objectContaining({ + expect(DockerImage.fromBuild).toHaveBeenCalledWith(expect.stringMatching(path.join(__dirname, '..', 'lib')), expect.objectContaining({ buildArgs: expect.objectContaining({ PIP_INDEX_URL: testPypi, }), diff --git a/packages/@aws-cdk/aws-lambda-python-alpha/test/layer.test.ts b/packages/@aws-cdk/aws-lambda-python-alpha/test/layer.test.ts index 3d17d896ab527..548b9579a8b10 100644 --- a/packages/@aws-cdk/aws-lambda-python-alpha/test/layer.test.ts +++ b/packages/@aws-cdk/aws-lambda-python-alpha/test/layer.test.ts @@ -30,7 +30,7 @@ beforeEach(() => { }); test('Bundling a layer from files', () => { - const entry = path.join(__dirname, 'test/lambda-handler-project'); + const entry = path.join(__dirname, 'test', 'lambda-handler-project'); new PythonLayerVersion(stack, 'layer', { entry, }); diff --git a/packages/@aws-cdk/integ-runner/lib/cli.ts b/packages/@aws-cdk/integ-runner/lib/cli.ts index 5847cec812e99..7ed6a5455f478 100644 --- a/packages/@aws-cdk/integ-runner/lib/cli.ts +++ b/packages/@aws-cdk/integ-runner/lib/cli.ts @@ -107,7 +107,7 @@ export async function main(args: string[]) { return; } - const pool = workerpool.pool(path.join(__dirname, '../lib/workers/extract/index.js'), { + const pool = workerpool.pool(path.join(__dirname, '..', 'lib', 'workers', 'extract', 'index.js'), { maxWorkers: options.watch ? 1 : options.maxWorkers, }); diff --git a/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts b/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts index 6a67c30eb00d5..87743e59b564e 100644 --- a/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts +++ b/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts @@ -10,7 +10,7 @@ let cdkMock: MockCdkProvider; const currentCwd = process.cwd(); beforeAll(() => { - process.chdir(path.join(__dirname, '../..')); + process.chdir(path.join(__dirname, '..', '..')); }); afterAll(() => { process.chdir(currentCwd); diff --git a/packages/@aws-cdk/integ-runner/test/workers/integ-worker.test.ts b/packages/@aws-cdk/integ-runner/test/workers/integ-worker.test.ts index e97e45bf48689..dfe028f9599df 100644 --- a/packages/@aws-cdk/integ-runner/test/workers/integ-worker.test.ts +++ b/packages/@aws-cdk/integ-runner/test/workers/integ-worker.test.ts @@ -9,7 +9,7 @@ let stderrMock: jest.SpyInstance; let pool: workerpool.WorkerPool; let spawnSyncMock: jest.SpyInstance; beforeAll(() => { - pool = workerpool.pool(path.join(__dirname, './mock-extract_worker.js')); + pool = workerpool.pool(path.join(__dirname, 'mock-extract_worker.js')); }); beforeEach(() => { jest.spyOn(fs, 'moveSync').mockImplementation(() => { return true; }); diff --git a/packages/@aws-cdk/integ-runner/test/workers/snapshot-worker.test.ts b/packages/@aws-cdk/integ-runner/test/workers/snapshot-worker.test.ts index 015b53861b622..8c53833710837 100644 --- a/packages/@aws-cdk/integ-runner/test/workers/snapshot-worker.test.ts +++ b/packages/@aws-cdk/integ-runner/test/workers/snapshot-worker.test.ts @@ -16,7 +16,7 @@ afterEach(() => { jest.restoreAllMocks(); }); -const directory = path.join(__dirname, '../test-data'); +const directory = path.join(__dirname, '..', 'test-data'); describe('Snapshot tests', () => { test('no snapshot', () => { // WHEN diff --git a/packages/aws-cdk-lib/aws-appsync/test/appsync-caching-config.test.ts b/packages/aws-cdk-lib/aws-appsync/test/appsync-caching-config.test.ts index b1475e412f3ff..655ba2a914e9c 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/appsync-caching-config.test.ts +++ b/packages/aws-cdk-lib/aws-appsync/test/appsync-caching-config.test.ts @@ -23,7 +23,7 @@ describe('Lambda caching config', () => { beforeEach(() => { func = new lambda.Function(stack, 'func', { - code: lambda.Code.fromAsset(path.join(__dirname, 'verify/lambda-tutorial')), + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'lambda-tutorial')), handler: 'lambda-tutorial.handler', runtime: lambda.Runtime.NODEJS_LATEST, }); diff --git a/packages/aws-cdk-lib/aws-appsync/test/appsync-lambda.test.ts b/packages/aws-cdk-lib/aws-appsync/test/appsync-lambda.test.ts index 29ba4d27f6446..e709e445b2d98 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/appsync-lambda.test.ts +++ b/packages/aws-cdk-lib/aws-appsync/test/appsync-lambda.test.ts @@ -20,7 +20,7 @@ describe('Lambda Data Source configuration', () => { let func: lambda.Function; beforeEach(() => { func = new lambda.Function(stack, 'func', { - code: lambda.Code.fromAsset(path.join(__dirname, 'verify/iam-query')), + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'iam-query')), handler: 'iam-query.handler', runtime: lambda.Runtime.NODEJS_LATEST, }); @@ -76,7 +76,7 @@ describe('Lambda Data Source configuration', () => { schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); const dummyFunction = new lambda.Function(newStack, 'func', { - code: lambda.Code.fromAsset(path.join(__dirname, 'verify/iam-query')), + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'iam-query')), handler: 'iam-query.handler', runtime: lambda.Runtime.NODEJS_LATEST, }); @@ -130,7 +130,7 @@ describe('adding lambda data source from imported api', () => { let func: lambda.Function; beforeEach(() => { func = new lambda.Function(stack, 'func', { - code: lambda.Code.fromAsset(path.join(__dirname, 'verify/iam-query')), + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'iam-query')), handler: 'iam-query.handler', runtime: lambda.Runtime.NODEJS_LATEST, }); diff --git a/packages/aws-cdk-lib/aws-appsync/test/appsync-mapping-template.test.ts b/packages/aws-cdk-lib/aws-appsync/test/appsync-mapping-template.test.ts index fd9ab94b91341..972138159dd36 100644 --- a/packages/aws-cdk-lib/aws-appsync/test/appsync-mapping-template.test.ts +++ b/packages/aws-cdk-lib/aws-appsync/test/appsync-mapping-template.test.ts @@ -24,7 +24,7 @@ describe('Lambda Mapping Templates', () => { beforeEach(() => { func = new lambda.Function(stack, 'func', { - code: lambda.Code.fromAsset(path.join(__dirname, 'verify/lambda-tutorial')), + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'lambda-tutorial')), handler: 'lambda-tutorial.handler', runtime: lambda.Runtime.NODEJS_LATEST, }); diff --git a/packages/aws-cdk-lib/aws-ec2/test/cfn-init-element.test.ts b/packages/aws-cdk-lib/aws-ec2/test/cfn-init-element.test.ts index 7ce066f2c1c69..2d3656e423322 100644 --- a/packages/aws-cdk-lib/aws-ec2/test/cfn-init-element.test.ts +++ b/packages/aws-cdk-lib/aws-ec2/test/cfn-init-element.test.ts @@ -352,7 +352,7 @@ describe('InitFile', () => { default: new ec2.InitConfig([ ec2.InitFile.fromAsset( '/target/path/config.json', - path.join(__dirname, 'init-configs/configFileForFirstInstance.json'), + path.join(__dirname, 'init-configs', 'configFileForFirstInstance.json'), ), ]), }, @@ -377,7 +377,7 @@ describe('InitFile', () => { default: new ec2.InitConfig([ ec2.InitFile.fromAsset( '/target/path/config.json', - path.join(__dirname, 'init-configs/configFileForSecondInstance.json'), + path.join(__dirname, 'init-configs', 'configFileForSecondInstance.json'), ), ]), }, diff --git a/packages/aws-cdk-lib/aws-ecs/test/container-definition.test.ts b/packages/aws-cdk-lib/aws-ecs/test/container-definition.test.ts index 76c1d5c254109..8a5c5ea165249 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/container-definition.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/container-definition.test.ts @@ -479,7 +479,7 @@ describe('container definition', () => { key: 'foo', value: 'bar', }, - environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles/test-envfile.env'))], + environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles', 'test-envfile.env'))], essential: true, extraHosts: { name: 'dev-db.hostname.pvt', @@ -1305,7 +1305,7 @@ describe('container definition', () => { taskDefinition.addContainer('cont', { image: ecs.ContainerImage.fromRegistry('test'), memoryLimitMiB: 1024, - environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles/test-envfile.env'))], + environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles', 'test-envfile.env'))], }); // THEN @@ -1417,7 +1417,7 @@ describe('container definition', () => { taskDefinition.addContainer('cont', { image: ecs.ContainerImage.fromRegistry('test'), memoryLimitMiB: 1024, - environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles/test-envfile.env'))], + environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles', 'test-envfile.env'))], }); // THEN diff --git a/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-task-definition.test.ts b/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-task-definition.test.ts index a7109bfc5c7d8..a66bad6fe1eed 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-task-definition.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-task-definition.test.ts @@ -247,7 +247,7 @@ describe('ec2 task definition', () => { dockerSecurityOptions: ['ECS_SELINUX_CAPABLE=true'], entryPoint: ['/app/node_modules/.bin/cdk'], environment: { TEST_ENVIRONMENT_VARIABLE: 'test environment variable value' }, - environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, '../demo-envfiles/test-envfile.env'))], + environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, '..', 'demo-envfiles', 'test-envfile.env'))], essential: true, extraHosts: { EXTRAHOST: 'extra host' }, healthCheck: { diff --git a/packages/aws-cdk-lib/aws-ecs/test/environment-file.test.ts b/packages/aws-cdk-lib/aws-ecs/test/environment-file.test.ts index d0ad2f53b7b7c..736523a2dcd46 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/environment-file.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/environment-file.test.ts @@ -21,7 +21,7 @@ describe('environment file', () => { // GIVEN const app = new cdk.App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); const stack = new cdk.Stack(app); - const fileAsset = ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles/test-envfile.env')); + const fileAsset = ecs.EnvironmentFile.fromAsset(path.join(__dirname, 'demo-envfiles', 'test-envfile.env')); // WHEN const image = ecs.ContainerImage.fromRegistry('/aws/aws-example-app'); diff --git a/packages/aws-cdk-lib/aws-ecs/test/external/external-task-definition.test.ts b/packages/aws-cdk-lib/aws-ecs/test/external/external-task-definition.test.ts index a78872cfbba2b..3ac58eaa8c680 100644 --- a/packages/aws-cdk-lib/aws-ecs/test/external/external-task-definition.test.ts +++ b/packages/aws-cdk-lib/aws-ecs/test/external/external-task-definition.test.ts @@ -162,7 +162,7 @@ describe('external task definition', () => { dockerSecurityOptions: ['ECS_SELINUX_CAPABLE=true'], entryPoint: ['/app/node_modules/.bin/cdk'], environment: { TEST_ENVIRONMENT_VARIABLE: 'test environment variable value' }, - environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, '../demo-envfiles/test-envfile.env'))], + environmentFiles: [ecs.EnvironmentFile.fromAsset(path.join(__dirname, '..', 'demo-envfiles', 'test-envfile.env'))], essential: true, extraHosts: { EXTRAHOST: 'extra host' }, healthCheck: { diff --git a/packages/aws-cdk-lib/aws-eks/lib/cluster.ts b/packages/aws-cdk-lib/aws-eks/lib/cluster.ts index f24beeab72346..639344f9c25f0 100644 --- a/packages/aws-cdk-lib/aws-eks/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-eks/lib/cluster.ts @@ -1967,7 +1967,7 @@ export class Cluster extends ClusterBase { */ private addNeuronDevicePlugin() { if (!this._neuronDevicePlugin) { - const fileContents = fs.readFileSync(path.join(__dirname, 'addons/neuron-device-plugin.yaml'), 'utf8'); + const fileContents = fs.readFileSync(path.join(__dirname, 'addons', 'neuron-device-plugin.yaml'), 'utf8'); const sanitized = YAML.parse(fileContents); this._neuronDevicePlugin = this.addManifest('NeuronDevicePlugin', sanitized); } diff --git a/packages/aws-cdk-lib/aws-eks/test/cluster.test.ts b/packages/aws-cdk-lib/aws-eks/test/cluster.test.ts index d46980277d152..fe48cc76355ae 100644 --- a/packages/aws-cdk-lib/aws-eks/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-eks/test/cluster.test.ts @@ -2183,7 +2183,7 @@ describe('cluster', () => { instanceType: new ec2.InstanceType('inf1.2xlarge'), minCapacity: 1, }); - const fileContents = fs.readFileSync(path.join(__dirname, '../lib', 'addons/neuron-device-plugin.yaml'), 'utf8'); + const fileContents = fs.readFileSync(path.join(__dirname, '..', 'lib', 'addons', 'neuron-device-plugin.yaml'), 'utf8'); const sanitized = YAML.parse(fileContents); // THEN @@ -2201,7 +2201,7 @@ describe('cluster', () => { instanceType: new ec2.InstanceType('inf2.xlarge'), minCapacity: 1, }); - const fileContents = fs.readFileSync(path.join(__dirname, '../lib', 'addons/neuron-device-plugin.yaml'), 'utf8'); + const fileContents = fs.readFileSync(path.join(__dirname, '..', 'lib', 'addons', 'neuron-device-plugin.yaml'), 'utf8'); const sanitized = YAML.parse(fileContents); // THEN @@ -2219,7 +2219,7 @@ describe('cluster', () => { cluster.addNodegroupCapacity('InferenceInstances', { instanceTypes: [new ec2.InstanceType('inf1.2xlarge')], }); - const fileContents = fs.readFileSync(path.join(__dirname, '../lib', 'addons/neuron-device-plugin.yaml'), 'utf8'); + const fileContents = fs.readFileSync(path.join(__dirname, '..', 'lib', 'addons', 'neuron-device-plugin.yaml'), 'utf8'); const sanitized = YAML.parse(fileContents); // THEN @@ -2236,7 +2236,7 @@ describe('cluster', () => { cluster.addNodegroupCapacity('InferenceInstances', { instanceTypes: [new ec2.InstanceType('inf2.xlarge')], }); - const fileContents = fs.readFileSync(path.join(__dirname, '../lib', 'addons/neuron-device-plugin.yaml'), 'utf8'); + const fileContents = fs.readFileSync(path.join(__dirname, '..', 'lib', 'addons', 'neuron-device-plugin.yaml'), 'utf8'); const sanitized = YAML.parse(fileContents); // THEN diff --git a/packages/aws-cdk-lib/aws-lambda-nodejs/lib/bundling.ts b/packages/aws-cdk-lib/aws-lambda-nodejs/lib/bundling.ts index c5bd7c4243e47..1f3fdd0cb3ed4 100644 --- a/packages/aws-cdk-lib/aws-lambda-nodejs/lib/bundling.ts +++ b/packages/aws-cdk-lib/aws-lambda-nodejs/lib/bundling.ts @@ -154,7 +154,7 @@ export class Bundling implements cdk.BundlingOptions { // Docker bundling const shouldBuildImage = props.forceDockerBundling || !Bundling.esbuildInstallation; - this.image = shouldBuildImage ? props.dockerImage ?? cdk.DockerImage.fromBuild(path.join(__dirname, '../lib'), + this.image = shouldBuildImage ? props.dockerImage ?? cdk.DockerImage.fromBuild(path.join(__dirname, '..', 'lib'), { buildArgs: { ...props.buildArgs ?? {}, diff --git a/packages/aws-cdk-lib/aws-lambda-nodejs/test/bundling.test.ts b/packages/aws-cdk-lib/aws-lambda-nodejs/test/bundling.test.ts index 10cfe72adf154..c0010a3328fe6 100644 --- a/packages/aws-cdk-lib/aws-lambda-nodejs/test/bundling.test.ts +++ b/packages/aws-cdk-lib/aws-lambda-nodejs/test/bundling.test.ts @@ -626,7 +626,7 @@ test('esbuild bundling with projectRoot', () => { }); test('esbuild bundling with projectRoot and externals and dependencies', () => { - const repoRoot = path.join(__dirname, '../../../..'); + const repoRoot = path.join(__dirname, '..', '..', '..', '..'); const packageLock = path.join(repoRoot, 'common', 'package-lock.json'); Bundling.bundle(stack, { entry: __filename, diff --git a/packages/aws-cdk-lib/aws-lambda-nodejs/test/docker.test.ts b/packages/aws-cdk-lib/aws-lambda-nodejs/test/docker.test.ts index e25938452357a..a29c4cbfe7954 100644 --- a/packages/aws-cdk-lib/aws-lambda-nodejs/test/docker.test.ts +++ b/packages/aws-cdk-lib/aws-lambda-nodejs/test/docker.test.ts @@ -3,7 +3,7 @@ import * as path from 'path'; const docker = process.env.CDK_DOCKER ?? 'docker'; beforeAll(() => { - const process = spawnSync(docker, ['build', '-t', 'esbuild', path.join(__dirname, '../lib')], { stdio: 'inherit' }); + const process = spawnSync(docker, ['build', '-t', 'esbuild', path.join(__dirname, '..', 'lib')], { stdio: 'inherit' }); expect(process.error).toBeUndefined(); expect(process.status).toBe(0); }); diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/run-batch-job.test.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/run-batch-job.test.ts index 15d9bb1617b5d..9870096ac6cbf 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/run-batch-job.test.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/run-batch-job.test.ts @@ -18,7 +18,7 @@ beforeEach(() => { batchJobDefinition = new batch.EcsJobDefinition(stack, 'JobDefinition', { container: new batch.EcsEc2ContainerDefinition(stack, 'Container', { image: ecs.ContainerImage.fromAsset( - path.join(__dirname, './batchjob-image'), + path.join(__dirname, 'batchjob-image'), ), cpu: 256, memory: cdk.Size.mebibytes(2048), diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/submit-job.test.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/submit-job.test.ts index 500dea14c5128..46c996ecfba1f 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/submit-job.test.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/batch/submit-job.test.ts @@ -17,7 +17,7 @@ beforeEach(() => { batchJobDefinition = new batch.EcsJobDefinition(stack, 'JobDefinition', { container: new batch.EcsEc2ContainerDefinition(stack, 'Container', { image: ecs.ContainerImage.fromAsset( - path.join(__dirname, './batchjob-image'), + path.join(__dirname, 'batchjob-image'), ), cpu: 256, memory: cdk.Size.mebibytes(2048), diff --git a/packages/aws-cdk-lib/core/test/bundling.test.ts b/packages/aws-cdk-lib/core/test/bundling.test.ts index 9e074c992efed..ea74e92998637 100644 --- a/packages/aws-cdk-lib/core/test/bundling.test.ts +++ b/packages/aws-cdk-lib/core/test/bundling.test.ts @@ -312,7 +312,7 @@ describe('bundling', () => { signal: null, }); - const imagePath = path.join(__dirname, 'fs/fixtures/test1'); + const imagePath = path.join(__dirname, 'fs', 'fixtures', 'test1'); DockerImage.fromAsset(imagePath, { file: 'my-dockerfile', }); @@ -332,7 +332,7 @@ describe('bundling', () => { signal: null, }); - const imagePath = path.join(__dirname, 'fs/fixtures/test1'); + const imagePath = path.join(__dirname, 'fs', 'fixtures', 'test1'); const image = DockerImage.fromAsset(imagePath, { file: 'my-dockerfile', }); diff --git a/packages/aws-cdk-lib/cx-api/build-tools/update-vnext.ts b/packages/aws-cdk-lib/cx-api/build-tools/update-vnext.ts index 554eeb4b2e699..007beab6f5ee2 100644 --- a/packages/aws-cdk-lib/cx-api/build-tools/update-vnext.ts +++ b/packages/aws-cdk-lib/cx-api/build-tools/update-vnext.ts @@ -8,7 +8,8 @@ import { MAGIC_V2NEXT } from '../lib/private/flag-modeling'; async function main() { const featuresSourceFile = path.join(__dirname, '..', 'lib', 'features.ts'); - let currentv2: string | undefined = JSON.parse(await fs.readFile(path.join(__dirname, '../../../../version.v2.json'), { encoding: 'utf-8' })).version; + // eslint-disable-next-line @aws-cdk/no-invalid-path + let currentv2: string | undefined = JSON.parse(await fs.readFile(path.join(__dirname, '..', '..', '..', '..', 'version.v2.json'), { encoding: 'utf-8' })).version; currentv2 = currentv2?.match(/^[0-9\.]+/)?.[0]; // Make sure to only retain the actual version number, not any '-rc.X' suffix if (!currentv2) { diff --git a/packages/aws-cdk-lib/cx-api/test/features.test.ts b/packages/aws-cdk-lib/cx-api/test/features.test.ts index 1aa592b15114c..e9119613c33b6 100644 --- a/packages/aws-cdk-lib/cx-api/test/features.test.ts +++ b/packages/aws-cdk-lib/cx-api/test/features.test.ts @@ -70,7 +70,8 @@ test.each([ expect(compareVersions(b, a)).toBeCloseTo(-expected, 10); // Gets around expect(-0).toEqual(0) failing... :x }); -const currentv2: string = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../../version.v2.json'), { encoding: 'utf-8' })).version; +// eslint-disable-next-line @aws-cdk/no-invalid-path +const currentv2: string = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', '..', '..', 'version.v2.json'), { encoding: 'utf-8' })).version; describe(`introducedIn.v2 is either <= ${currentv2} or magic value "${MAGIC_V2NEXT}"`, () => { test.each(Object.keys(feats.FLAGS))('for flag %p', flag => { diff --git a/packages/aws-cdk/test/notices.test.ts b/packages/aws-cdk/test/notices.test.ts index f95605a710cdb..db1023f842a9d 100644 --- a/packages/aws-cdk/test/notices.test.ts +++ b/packages/aws-cdk/test/notices.test.ts @@ -147,11 +147,11 @@ describe('cli notices', () => { const notices = [FRAMEWORK_2_1_0_AFFECTED_NOTICE]; expect(filterNotices(notices, { - outdir: path.join(__dirname, 'cloud-assembly-trees/built-with-2_12_0'), + outdir: path.join(__dirname, 'cloud-assembly-trees', 'built-with-2_12_0'), })).toEqual([]); expect(filterNotices(notices, { - outdir: path.join(__dirname, 'cloud-assembly-trees/built-with-1_144_0'), + outdir: path.join(__dirname, 'cloud-assembly-trees', 'built-with-1_144_0'), })).toEqual([FRAMEWORK_2_1_0_AFFECTED_NOTICE]); }); @@ -160,22 +160,22 @@ describe('cli notices', () => { // module-level match expect(filterNotices(notices, { - outdir: path.join(__dirname, 'cloud-assembly-trees/experimental-module'), + outdir: path.join(__dirname, 'cloud-assembly-trees', 'experimental-module'), })).toEqual([NOTICE_FOR_APIGATEWAYV2]); // no apigatewayv2 in the tree expect(filterNotices(notices, { - outdir: path.join(__dirname, 'cloud-assembly-trees/built-with-2_12_0'), + outdir: path.join(__dirname, 'cloud-assembly-trees', 'built-with-2_12_0'), })).toEqual([]); // module name mismatch: apigateway != apigatewayv2 expect(filterNotices([NOTICE_FOR_APIGATEWAY], { - outdir: path.join(__dirname, 'cloud-assembly-trees/experimental-module'), + outdir: path.join(__dirname, 'cloud-assembly-trees', 'experimental-module'), })).toEqual([]); // construct-level match expect(filterNotices([NOTICE_FOR_APIGATEWAYV2_CFN_STAGE], { - outdir: path.join(__dirname, 'cloud-assembly-trees/experimental-module'), + outdir: path.join(__dirname, 'cloud-assembly-trees', 'experimental-module'), })).toEqual([NOTICE_FOR_APIGATEWAYV2_CFN_STAGE]); }); diff --git a/packages/aws-cdk/test/tree.test.ts b/packages/aws-cdk/test/tree.test.ts index e6e92579f2282..52966973820cd 100644 --- a/packages/aws-cdk/test/tree.test.ts +++ b/packages/aws-cdk/test/tree.test.ts @@ -104,12 +104,12 @@ describe('some', () => { describe('loadTreeFromDir', () => { test('can find tree', () => { - const tree = loadTreeFromDir(path.join(__dirname, 'cloud-assembly-trees/built-with-1_144_0')); + const tree = loadTreeFromDir(path.join(__dirname, 'cloud-assembly-trees', 'built-with-1_144_0')); expect(tree.id).toEqual('App'); }); test('cannot find tree', () => { - const tree = loadTreeFromDir(path.join(__dirname, 'cloud-assembly-trees/foo')); + const tree = loadTreeFromDir(path.join(__dirname, 'cloud-assembly-trees', 'foo')); expect(tree).toEqual({}); }); }); \ No newline at end of file diff --git a/tools/@aws-cdk/cdk-build-tools/config/eslintrc.js b/tools/@aws-cdk/cdk-build-tools/config/eslintrc.js index 3eb417a86a437..065265d141003 100644 --- a/tools/@aws-cdk/cdk-build-tools/config/eslintrc.js +++ b/tools/@aws-cdk/cdk-build-tools/config/eslintrc.js @@ -44,6 +44,7 @@ module.exports = { '@aws-cdk/no-core-construct': ['error'], '@aws-cdk/invalid-cfn-imports': ['error'], '@aws-cdk/no-literal-partition': ['error'], + '@aws-cdk/no-invalid-path': [ 'error' ], // Require use of the `import { foo } from 'bar';` form instead of `import foo = require('bar');` '@typescript-eslint/no-require-imports': ['error'], '@typescript-eslint/indent': ['error', 2], diff --git a/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts b/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts index 025c0101aa1f9..c8a4ac4d6b574 100644 --- a/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts +++ b/tools/@aws-cdk/cdk-build-tools/lib/package-info.ts @@ -104,6 +104,8 @@ export function packageCompiler(compilers: CompilerOverrides, options?: CDKBuild args.push('--compress-assembly'); } if (options?.stripDeprecated) { + // This package is not published to npm so the linter rule is invalid + // eslint-disable-next-line @aws-cdk/no-invalid-path args.push(`--strip-deprecated ${path.join(__dirname, '..', '..', '..', '..', 'deprecated_apis.txt')}`); } return [compilers.jsii || require.resolve('jsii/bin/jsii'), ...args]; diff --git a/tools/@aws-cdk/eslint-plugin/README.md b/tools/@aws-cdk/eslint-plugin/README.md index 386c1c0f2040c..65c28cc8d0f1f 100644 --- a/tools/@aws-cdk/eslint-plugin/README.md +++ b/tools/@aws-cdk/eslint-plugin/README.md @@ -11,6 +11,9 @@ Eslint plugin for the CDK repository. Contains rules that need to be applied spe Instead use `Construct` and `IConstruct` from the "constructs" module. Rule only applies to typescript files under the `test/` folder. +* `no-invalid-path`: Checks paths specified using `path.join()` for validity, including not going backwards (`'..'`) + multiple times in the path and not going backwards beyond a package's `package.json`. + * `no-literal-partition`: Forbids the use of literal partitions (usually `aws`). Instead, use `Aws.PARTITION` to ensure that the code works for other partitions too. @@ -26,4 +29,4 @@ Eslint plugin for the CDK repository. Contains rules that need to be applied spe as well! * You can now run the test in debugging mode (make sure to have `npx tsc -w` running, then from a debugging terminal, `npx jest --no-coverage -it 'your rule name'`), set a breakpoint, and inspect the typeless objects. -To activate it for real on the repo, also add it to `cdk-build-tools/config/eslintrc.js`. \ No newline at end of file +To activate it for real on the repo, also add it to `cdk-build-tools/config/eslintrc.js`. diff --git a/tools/@aws-cdk/eslint-plugin/lib/index.ts b/tools/@aws-cdk/eslint-plugin/lib/index.ts index e25149d1b615a..834c6bf781d7d 100644 --- a/tools/@aws-cdk/eslint-plugin/lib/index.ts +++ b/tools/@aws-cdk/eslint-plugin/lib/index.ts @@ -2,4 +2,5 @@ export const rules = { 'no-core-construct': require('./rules/no-core-construct'), 'invalid-cfn-imports': require('./rules/invalid-cfn-imports'), 'no-literal-partition': require('./rules/no-literal-partition'), + 'no-invalid-path': require('./rules/no-invalid-path'), }; diff --git a/tools/@aws-cdk/eslint-plugin/lib/rules/no-invalid-path.ts b/tools/@aws-cdk/eslint-plugin/lib/rules/no-invalid-path.ts new file mode 100644 index 0000000000000..f8dbd374a7e03 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/lib/rules/no-invalid-path.ts @@ -0,0 +1,91 @@ +import { Rule } from 'eslint'; +import * as path from 'path'; +import * as fs from 'fs'; + +function isPathJoinFuncCall(node: any): boolean { + return ( + node.callee?.property?.name === 'join' && + (node.parent?.expression?.callee?.object?.name === 'path' || + node.parent?.arguments?.some((a: any) => a.callee?.object?.name === 'path')) + ); +} + +function noArgumentVariables(node: any): boolean { + // Outside of the first argument, all arguments should be strings + const components = node.arguments.slice(1); + return components.every((a: any) => a.value !== undefined); +} + +function hasSlashes(args: string[]): boolean { + return args.some((a) => a.includes('/')); +} + +function firstArgIsDirname(node: any): boolean { + return node.arguments[0].name && node.arguments[0].name === '__dirname'; +} + +function argumentList(node: any): string[] { + // Already confirmed that first argument is '__dirname', so can safely remove it + const args: string[] = node.arguments.slice(1).map((a: any) => { return a.value; }); + return args; +} + +function recreatePath(args: string[]): string { + return `path.join(__dirname, '${args.join('\', \'')}')`; +} + +export function create(context: Rule.RuleContext): Rule.NodeListener { + return { + CallExpression(node: any) { + if (isPathJoinFuncCall(node)) { + if (node.arguments.length === 0) { + // ERROR: this is 'path.join()' + context.report({ node, message: '\'path.join()\' is not a valid path. You must specify arguments into the function.'}) + return; + } + + if (!noArgumentVariables(node)) { + // WARNING: unexpected non-string in the argument list. This happens if part of the argument list is a variable, i.e. `path.join(__dirname, myPath)`. + // We may be able to do something about this, but we currently are just going to let it pass. + return; + } + + // We currently do not lint any path.join without '__dirname' as the first argument + if (!firstArgIsDirname(node)) { + return; + } + + const args = argumentList(node); + + if (hasSlashes(args)) { + // ERROR: This path looks like 'path.join(__dirname, 'a/b')' and should be changed to 'path.join(__dirname, 'a', 'b')' + context.report({ node, message: `${recreatePath(args)} is not a valid path. It has '/' in the arguments which is not allowed. Each directory should be its own separate argument.`}); + return; + } + + const firstDownDir = args.findIndex((p) => p !== '..'); + + // Confirm path does not have any unnecessary '..' paths + // This allows us to validate subsequent checks + if (firstDownDir > 0 && args.some((p, i) => p === '..' && i > firstDownDir)) { + // ERROR: This path oscillates between up and down commands + context.report({ node, message: `${recreatePath(args)} is not a valid path. It goes backwards and forwards and backwards again, and can be simplified.`}); + return; + } + + // Exclude the case where there are no '..' at all in the path -- those are never invalid + const currentFile = context.getFilename(); + if (firstDownDir > 0) { + for (let i = 0; i < firstDownDir; i++) { + const pjFile = path.join(...[path.dirname(currentFile), ...args.slice(0, i), 'package.json']); + if (fs.existsSync(pjFile)) { + // ERROR: this path will end up going out of the package.json directory + context.report({ node, message: `${recreatePath(args)} is not a valid path. It goes beyond the parent library's package.json file so the file it points to will not be available after the library is packaged.`}); + return; + } + } + } + } + } + } +} diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures.test.ts b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures.test.ts index 714df1b9db6ae..7f382e0d92b97 100644 --- a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures.test.ts +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures.test.ts @@ -20,7 +20,7 @@ fs.readdirSync(fixturesRoot).filter(f => fs.lstatSync(path.join(fixturesRoot, f) }, overrideConfigFile: path.join(fixturesDir, 'eslintrc.js'), rulePaths: [ - path.join(__dirname, '../../lib/rules'), + path.join(__dirname, '..', '..', 'lib', 'rules'), ], fix: true, }); diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/eslintrc.js b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/eslintrc.js new file mode 100644 index 0000000000000..9ae156ccc1ced --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: ['@aws-cdk'], + rules: { + '@aws-cdk/no-invalid-path': [ 'error' ], + } +} \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.error.txt b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.error.txt new file mode 100644 index 0000000000000..671706f27a204 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.error.txt @@ -0,0 +1 @@ +'path.join()' is not a valid path. You must specify arguments into the function. \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.ts b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.ts new file mode 100644 index 0000000000000..4cc707705fde1 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/no-path.ts @@ -0,0 +1,3 @@ +import * as path from 'path'; + +path.join(); \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.error.txt b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.error.txt new file mode 100644 index 0000000000000..304d6e7fb16d2 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.error.txt @@ -0,0 +1 @@ +path.join(__dirname, '..', '..', '..', '..', '..', 'cfn2ts', 'README.md') is not a valid path. It goes beyond the parent library's package.json file so the file it points to will not be available after the library is packaged. \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.ts b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.ts new file mode 100644 index 0000000000000..32592280df2c0 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-beyond-packagejson.ts @@ -0,0 +1,4 @@ +import path from 'path'; + +// depends on eslint-plugin to have a package.json +path.join(__dirname, '..', '..', '..', '..', '..', 'cfn2ts', 'README.md'); \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.error.txt b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.error.txt new file mode 100644 index 0000000000000..fffe5d427cdf1 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.error.txt @@ -0,0 +1 @@ +path.join(__dirname, '..', '..', 'no-path-outside-module', '..', '..', 'fixtures.test.ts') is not a valid path. It goes backwards and forwards and backwards again, and can be simplified. \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.ts b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.ts new file mode 100644 index 0000000000000..bce94ee028c4e --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-oscillates.ts @@ -0,0 +1,3 @@ +import path from 'path'; + +path.join(__dirname, '..', '..', 'no-path-outside-module', '..', '..', 'fixtures.test.ts'); diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.error.txt b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.error.txt new file mode 100644 index 0000000000000..4c9e26a535c1e --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.error.txt @@ -0,0 +1 @@ +ath.join(__dirname, '../..', 'fixtures.test.ts') is not a valid path. It has '/' in the arguments which is not allowed. Each directory should be its own separate argument. \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.ts b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.ts new file mode 100644 index 0000000000000..1750443533fc9 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/path-with-slashes.ts @@ -0,0 +1,3 @@ +import * as path from 'path'; + +path.join(__dirname, '../..', 'fixtures.test.ts'); \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.error.txt b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.error.txt new file mode 100644 index 0000000000000..64e8b877be8a0 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.error.txt @@ -0,0 +1 @@ +path.join(__dirname, './asdf') is not a valid path. It has '/' in the arguments which is not allowed. Each directory should be its own separate argument. \ No newline at end of file diff --git a/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.ts b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.ts new file mode 100644 index 0000000000000..72f86b4bc2d36 --- /dev/null +++ b/tools/@aws-cdk/eslint-plugin/test/rules/fixtures/no-invalid-path/within-function.ts @@ -0,0 +1,5 @@ +import * as path from 'path'; + +function Myfunction(_a: string, _p: string) {} + +Myfunction('arg1', path.join(__dirname, './asdf')); \ No newline at end of file