diff --git a/src/__tests__/__snapshots__/construct-hub.test.ts.snap b/src/__tests__/__snapshots__/construct-hub.test.ts.snap index ad333a7b6..0a22ad2d1 100644 --- a/src/__tests__/__snapshots__/construct-hub.test.ts.snap +++ b/src/__tests__/__snapshots__/construct-hub.test.ts.snap @@ -201,6 +201,18 @@ Object { "Description": "S3 key for asset version \\"359fc80cc30507dac2046dab4f282d3ccbe9dbc662a872489e0152aab4a06b6e\\"", "Type": "String", }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aArtifactHashFE8941E4": Object { + "Description": "Artifact hash for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B": Object { + "Description": "S3 bucket for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485": Object { + "Description": "S3 key for asset version \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, "AssetParameters745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3dArtifactHash9AA75D59": Object { "Description": "Artifact hash for asset \\"745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3d\\"", "Type": "String", @@ -249,18 +261,6 @@ Object { "Description": "S3 key for asset version \\"8a009c34d8c83f47e94fa949e991192d92d605ea00d5100391cb4759a9f682ae\\"", "Type": "String", }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271ArtifactHashB9505E75": Object { - "Description": "Artifact hash for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92": Object { - "Description": "S3 bucket for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8": Object { - "Description": "S3 key for asset version \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, "AssetParameters8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900ArtifactHash121EF458": Object { "Description": "Artifact hash for asset \\"8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900\\"", "Type": "String", @@ -2162,7 +2162,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B", }, "S3Key": Object { "Fn::Join": Array [ @@ -2175,7 +2175,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -2188,7 +2188,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -11387,6 +11387,18 @@ Object { "Description": "S3 key for asset version \\"4074092ab8b435c90a773e082601fa36def54c91cadfae59451bd0beda547cbc\\"", "Type": "String", }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aArtifactHashFE8941E4": Object { + "Description": "Artifact hash for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B": Object { + "Description": "S3 bucket for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485": Object { + "Description": "S3 key for asset version \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, "AssetParameters745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3dArtifactHash9AA75D59": Object { "Description": "Artifact hash for asset \\"745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3d\\"", "Type": "String", @@ -11435,18 +11447,6 @@ Object { "Description": "S3 key for asset version \\"8a009c34d8c83f47e94fa949e991192d92d605ea00d5100391cb4759a9f682ae\\"", "Type": "String", }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271ArtifactHashB9505E75": Object { - "Description": "Artifact hash for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92": Object { - "Description": "S3 bucket for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8": Object { - "Description": "S3 key for asset version \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, "AssetParameters8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900ArtifactHash121EF458": Object { "Description": "Artifact hash for asset \\"8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900\\"", "Type": "String", @@ -13637,7 +13637,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B", }, "S3Key": Object { "Fn::Join": Array [ @@ -13650,7 +13650,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -13663,7 +13663,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -23021,6 +23021,18 @@ Object { "Description": "S3 key for asset version \\"359fc80cc30507dac2046dab4f282d3ccbe9dbc662a872489e0152aab4a06b6e\\"", "Type": "String", }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aArtifactHashFE8941E4": Object { + "Description": "Artifact hash for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B": Object { + "Description": "S3 bucket for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485": Object { + "Description": "S3 key for asset version \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, "AssetParameters745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3dArtifactHash9AA75D59": Object { "Description": "Artifact hash for asset \\"745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3d\\"", "Type": "String", @@ -23069,18 +23081,6 @@ Object { "Description": "S3 key for asset version \\"8a009c34d8c83f47e94fa949e991192d92d605ea00d5100391cb4759a9f682ae\\"", "Type": "String", }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271ArtifactHashB9505E75": Object { - "Description": "Artifact hash for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92": Object { - "Description": "S3 bucket for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8": Object { - "Description": "S3 key for asset version \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, "AssetParameters8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900ArtifactHash121EF458": Object { "Description": "Artifact hash for asset \\"8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900\\"", "Type": "String", @@ -24982,7 +24982,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B", }, "S3Key": Object { "Fn::Join": Array [ @@ -24995,7 +24995,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -25008,7 +25008,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -34217,6 +34217,18 @@ Object { "Description": "S3 key for asset version \\"359fc80cc30507dac2046dab4f282d3ccbe9dbc662a872489e0152aab4a06b6e\\"", "Type": "String", }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aArtifactHashFE8941E4": Object { + "Description": "Artifact hash for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B": Object { + "Description": "S3 bucket for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485": Object { + "Description": "S3 key for asset version \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, "AssetParameters745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3dArtifactHash9AA75D59": Object { "Description": "Artifact hash for asset \\"745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3d\\"", "Type": "String", @@ -34277,18 +34289,6 @@ Object { "Description": "S3 key for asset version \\"8a009c34d8c83f47e94fa949e991192d92d605ea00d5100391cb4759a9f682ae\\"", "Type": "String", }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271ArtifactHashB9505E75": Object { - "Description": "Artifact hash for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92": Object { - "Description": "S3 bucket for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8": Object { - "Description": "S3 key for asset version \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, "AssetParameters8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900ArtifactHash121EF458": Object { "Description": "Artifact hash for asset \\"8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900\\"", "Type": "String", @@ -36339,7 +36339,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B", }, "S3Key": Object { "Fn::Join": Array [ @@ -36352,7 +36352,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -36365,7 +36365,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -45852,6 +45852,18 @@ Object { "Description": "S3 key for asset version \\"4074092ab8b435c90a773e082601fa36def54c91cadfae59451bd0beda547cbc\\"", "Type": "String", }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aArtifactHashFE8941E4": Object { + "Description": "Artifact hash for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B": Object { + "Description": "S3 bucket for asset \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, + "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485": Object { + "Description": "S3 key for asset version \\"443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a\\"", + "Type": "String", + }, "AssetParameters745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3dArtifactHash9AA75D59": Object { "Description": "Artifact hash for asset \\"745b59468864e5aea4f3660175a79d8d17fa7a7a939182b38565a3b7b1228b3d\\"", "Type": "String", @@ -45900,18 +45912,6 @@ Object { "Description": "S3 key for asset version \\"8a009c34d8c83f47e94fa949e991192d92d605ea00d5100391cb4759a9f682ae\\"", "Type": "String", }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271ArtifactHashB9505E75": Object { - "Description": "Artifact hash for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92": Object { - "Description": "S3 bucket for asset \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, - "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8": Object { - "Description": "S3 key for asset version \\"8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271\\"", - "Type": "String", - }, "AssetParameters8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900ArtifactHash121EF458": Object { "Description": "Artifact hash for asset \\"8d968e7576898e39de27ff4cf5f336e8f112a4de9757412123e2dd725f451900\\"", "Type": "String", @@ -47922,7 +47922,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Properties": Object { "Code": Object { "S3Bucket": Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B", }, "S3Key": Object { "Fn::Join": Array [ @@ -47935,7 +47935,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, @@ -47948,7 +47948,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "Fn::Split": Array [ "||", Object { - "Ref": "AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8", + "Ref": "AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485", }, ], }, diff --git a/src/__tests__/backend/ingestion/framework-detection.test.ts b/src/__tests__/backend/ingestion/framework-detection.test.ts index 7e2eb8583..b43c6b087 100644 --- a/src/__tests__/backend/ingestion/framework-detection.test.ts +++ b/src/__tests__/backend/ingestion/framework-detection.test.ts @@ -1,61 +1,110 @@ import { Assembly } from '@jsii/spec'; -import { ConstructFramework, ConstructFrameworkName, detectConstructFramework } from '../../../backend/ingestion/framework-detection.lambda-shared'; +import { ConstructFramework, ConstructFrameworkName, detectConstructFrameworks } from '../../../backend/ingestion/framework-detection.lambda-shared'; describe('AWS CDK frameworks', () => { - expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0'])).toEqual({ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }); - expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', '@aws-cdk/aws-lambda@1.134.0'])).toEqual({ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }); - expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', '@aws-cdk/aws-lambda@1.135.0'])).toEqual({ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }); + expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0'])) + .toEqual([{ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }]); + + expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', '@aws-cdk/aws-lambda@1.134.0'])) + .toEqual([{ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }]); + + expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', '@aws-cdk/aws-lambda@1.135.0'])) + .toEqual([{ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }]); it('classifies no major version if versions are mixed', () => { - expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', '@aws-cdk/aws-lambda@2.0.0'])).toEqual({ name: ConstructFrameworkName.AWS_CDK, majorVersion: undefined }); + expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', '@aws-cdk/aws-lambda@2.0.0'])) + .toEqual([{ name: ConstructFrameworkName.AWS_CDK, majorVersion: undefined }]); }); - it('classifies core libraries', () => { - for (const name of ['monocdk', 'aws-cdk-lib', '@aws-cdk/aws-s3']) { + it('classifies v1 libraries', () => { + for (const name of ['monocdk', '@aws-cdk/core', '@aws-cdk/aws-s3']) { const assembly = { name, version: '1.134.0' }; - expect(detectConstructFramework(assembly as Assembly)).toEqual({ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }); + expect(detectConstructFrameworks(assembly as Assembly)) + .toEqual([{ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }]); } }); + + it('classifies v2 libraries', () => { + expect(frameworkForDeps(['aws-cdk-lib@2.0.0'])) + .toEqual([{ name: ConstructFrameworkName.AWS_CDK, majorVersion: 2 }]); + }); + + it('classifies when there are transitive dependencies without major version information', () => { + const assembly = { + name: 'mylib', + version: '1.2.3', + dependencies: { + '@aws-cdk/core': '1.123.0', + '@aws-cdk/s3': '1.123.0', + '@aws-cdk/ec2': '1.123.0', + }, + dependencyClosure: { + '@aws-cdk/assets': {}, + '@aws-cdk/core': {}, + '@aws-cdk/s3': {}, + '@aws-cdk/iam': {}, + '@aws-cdk/ec2': {}, + }, + }; + expect(detectConstructFrameworks(assembly as unknown as Assembly)) + .toEqual([{ name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }]); + }); }); -describe('CDK8s frameworks', () => { - expect(frameworkForDeps(['cdk8s@1.1.0'])).toEqual({ name: ConstructFrameworkName.CDK8S, majorVersion: 1 }); - expect(frameworkForDeps(['cdk8s@1.1.0', 'cdk8s-plus-22@1.0.0-beta.54'])).toEqual({ name: ConstructFrameworkName.CDK8S, majorVersion: 1 }); +describe('cdk8s frameworks', () => { + expect(frameworkForDeps(['cdk8s@1.1.0'])) + .toEqual([{ name: ConstructFrameworkName.CDK8S, majorVersion: 1 }]); + + expect(frameworkForDeps(['cdk8s@1.1.0', 'cdk8s-plus-22@1.0.0-beta.54'])) + .toEqual([{ name: ConstructFrameworkName.CDK8S, majorVersion: 1 }]); }); describe('cdktf frameworks', () => { - expect(frameworkForDeps(['cdktf@0.7.0'])).toEqual({ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }); - expect(frameworkForDeps(['cdktf@0.7.0', '@cdktf/provider-aws@0.1.0'])).toEqual({ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }); + expect(frameworkForDeps(['cdktf@0.7.0'])) + .toEqual([{ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }]); - it('ignores cdktf provider versions', () => { - expect(frameworkForDeps(['cdktf@0.7.0', '@cdktf/provider-aws@2.0.0'])).toEqual({ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }); - }); - - it('classifies cdktf', () => { - const assembly = { name: 'cdktf', version: '0.7.0' }; - expect(detectConstructFramework(assembly as Assembly)).toEqual({ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }); - }); + expect(frameworkForDeps(['cdktf@0.7.0', '@cdktf/provider-aws@0.1.0'])) + .toEqual([{ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }]); - it('never classifies @cdktf/ as ambiguous', () => { - const mixedAssembly = assemblyWithDeps(['cdktf@0.7.0', 'aws-cdk-lib@2.0.0-rc.17'], '@cdktf/aws-cdk'); - expect(detectConstructFramework(mixedAssembly)).toEqual({ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }); + it('ignores cdktf provider versions', () => { + expect(frameworkForDeps(['cdktf@0.7.0', '@cdktf/provider-aws@2.0.0'])) + .toEqual([{ name: ConstructFrameworkName.CDKTF, majorVersion: 0 }]); }); }); it('classifies non-frameworks', () => { const assembly = { name: 'constructs', version: '10.0.0' }; - expect(detectConstructFramework(assembly as Assembly)).toEqual(undefined); + expect(detectConstructFrameworks(assembly as Assembly)).toEqual([]); }); it('classifies mixed frameworks', () => { - expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', 'cdk8s@1.1.0'])).toEqual(undefined); + expect(frameworkForDeps(['@aws-cdk/aws-s3@1.134.0', 'cdk8s@1.1.0'])) + .toEqual([ + { name: ConstructFrameworkName.AWS_CDK, majorVersion: 1 }, + { name: ConstructFrameworkName.CDK8S, majorVersion: 1 }, + ]); + + expect(frameworkForDeps(['cdktf@0.7.0', 'aws-cdk-lib@2.0.0-rc.17'])) + .toEqual([ + { name: ConstructFrameworkName.CDKTF, majorVersion: 0 }, + { name: ConstructFrameworkName.AWS_CDK, majorVersion: 2 }, + ]); + + // wow all three!! + expect(frameworkForDeps(['cdktf@0.7.0', 'aws-cdk-lib@2.0.0-rc.17', 'cdk8s@1.1.0'])) + .toEqual([ + { name: ConstructFrameworkName.CDKTF, majorVersion: 0 }, + { name: ConstructFrameworkName.AWS_CDK, majorVersion: 2 }, + { name: ConstructFrameworkName.CDK8S, majorVersion: 1 }, + ]); }); -function frameworkForDeps(deps: string[]): ConstructFramework | undefined { - return detectConstructFramework(assemblyWithDeps(deps)); +function frameworkForDeps(deps: string[]): ConstructFramework[] { + return detectConstructFrameworks(assemblyWithDeps({ deps })); } -function assemblyWithDeps(deps: string[], name?: string): Assembly { +function assemblyWithDeps(options: { deps: string[]; name?: string }): Assembly { + const { deps, name } = options; // Split on the @ that is not at the beginning of the string const depVersions: string[][] = deps.map((dep) => dep.split(/(?!^)@/)); const assembly: Partial = { diff --git a/src/__tests__/backend/ingestion/ingestion.lambda.test.ts b/src/__tests__/backend/ingestion/ingestion.lambda.test.ts index 43912882f..61fa9439e 100644 --- a/src/__tests__/backend/ingestion/ingestion.lambda.test.ts +++ b/src/__tests__/backend/ingestion/ingestion.lambda.test.ts @@ -142,7 +142,12 @@ test('basic happy case', async () => { break; case metadataKey: expect(req.ContentType).toBe('application/json'); - expect(Buffer.from(req.Body! as any)).toEqual(Buffer.from(JSON.stringify({ date: time, packageLinks: {}, packageTags: [] }))); + expect(Buffer.from(req.Body! as any)).toEqual(Buffer.from(JSON.stringify({ + constructFrameworks: [], + date: time, + packageLinks: {}, + packageTags: [], + }))); mockMetadataCreated = true; break; case packageKey: @@ -302,6 +307,7 @@ test('basic happy case with license file', async () => { expect(req.ContentType).toBe('application/json'); expect(Buffer.from(req.Body! as any)) .toEqual(Buffer.from(JSON.stringify({ + constructFrameworks: [], date: time, licenseText: fakeLicense, packageLinks: {}, @@ -490,6 +496,7 @@ test('basic happy case with custom package links', async () => { case metadataKey: expect(req.ContentType).toBe('application/json'); expect(Buffer.from(req.Body! as any)).toEqual(Buffer.from(JSON.stringify({ + constructFrameworks: [], date: time, packageLinks: { PackageLinkKey: packageLinkValue, @@ -699,6 +706,7 @@ test('basic happy case with custom tags', async () => { case metadataKey: expect(req.ContentType).toBe('application/json'); expect(Buffer.from(req.Body! as any)).toEqual(Buffer.from(JSON.stringify({ + constructFrameworks: [], date: time, packageLinks: {}, // only includes true tags @@ -865,7 +873,7 @@ for (const [frameworkName, frameworkPackage] of [['aws-cdk', '@aws-cdk/core'], [ case metadataKey: expect(req.ContentType).toBe('application/json'); expect(JSON.parse(req.Body!.toString('utf-8'))).toEqual({ - constructFramework: { name: frameworkName, majorVersion: 1337 }, + constructFrameworks: [{ name: frameworkName, majorVersion: 1337 }], date: time, packageLinks: {}, packageTags: [], @@ -1025,7 +1033,7 @@ for (const [frameworkName, frameworkPackage] of [['aws-cdk', '@aws-cdk/core'], [ case metadataKey: expect(req.ContentType).toBe('application/json'); expect(JSON.parse(req.Body!.toString('utf-8'))).toEqual({ - constructFramework: { name: frameworkName, majorVersion: 42 }, + constructFrameworks: [{ name: frameworkName, majorVersion: 42 }], date: time, packageLinks: {}, packageTags: [], @@ -1191,7 +1199,7 @@ for (const [frameworkName, frameworkPackage] of [['aws-cdk', '@aws-cdk/core'], [ case metadataKey: expect(req.ContentType).toBe('application/json'); expect(JSON.parse(req.Body!.toString('utf-8'))).toEqual({ - constructFramework: { name: frameworkName }, // No major versio here (intentional) + constructFrameworks: [{ name: frameworkName }], // No major version here (intentional) date: time, packageLinks: {}, packageTags: [], diff --git a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap index 412ea677e..5237f23fe 100644 --- a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap +++ b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap @@ -4546,7 +4546,7 @@ Resources: Properties: Code: S3Bucket: - Ref: AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92 + Ref: AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B S3Key: Fn::Join: - "" @@ -4554,12 +4554,12 @@ Resources: - 0 - Fn::Split: - "||" - - Ref: AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8 + - Ref: AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485 - Fn::Select: - 1 - Fn::Split: - "||" - - Ref: AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8 + - Ref: AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485 Role: Fn::GetAtt: - ConstructHubIngestionServiceRole6380BAB6 @@ -7932,18 +7932,18 @@ Parameters: Type: String Description: Artifact hash for asset "b32de5d6fb92c01b03e93e387691b3f444ac4e9800273abf834874c427c640f0" - AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3BucketCC856B92: + AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3Bucket756D462B: Type: String Description: S3 bucket for asset - "8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271" - AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271S3VersionKeyAA6E7BA8: + "443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a" + AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aS3VersionKeyF72B2485: Type: String Description: S3 key for asset version - "8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271" - AssetParameters8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271ArtifactHashB9505E75: + "443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a" + AssetParameters443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604aArtifactHashFE8941E4: Type: String Description: Artifact hash for asset - "8d434dc3ba6dd6030546193937ec100e8fbd3a0cc043dc689fa5af027ed07271" + "443c9b23caa9dcbbbfb2b5cde4c6ad6ffada48a67c70b248b9a6f946a3a7604a" AssetParameterscba21fdff4caf13627bf82842c2c71312f281947caf192523dbaf730beb3340cS3Bucket965D0655: Type: String Description: S3 bucket for asset diff --git a/src/backend/ingestion/framework-detection.lambda-shared.ts b/src/backend/ingestion/framework-detection.lambda-shared.ts index f0200730b..096dd4f42 100644 --- a/src/backend/ingestion/framework-detection.lambda-shared.ts +++ b/src/backend/ingestion/framework-detection.lambda-shared.ts @@ -1,6 +1,10 @@ +// eslint-disable-next-line @typescript-eslint/no-require-imports +import assert = require('assert'); + import { Assembly } from '@jsii/spec'; import { minVersion } from 'semver'; + export const enum ConstructFrameworkName { AWS_CDK = 'aws-cdk', CDK8S = 'cdk8s', @@ -20,6 +24,18 @@ export interface ConstructFramework { readonly majorVersion?: number; } +/** + * Predicates that determine whether a package is indicative of the CDK + * framework someone is using. + */ +const FRAMEWORK_MATCHERS: Record boolean> = { + [ConstructFrameworkName.AWS_CDK]: (name: string) => name.startsWith('@aws-cdk/') || name === 'aws-cdk-lib' || name === 'monocdk', + [ConstructFrameworkName.CDK8S]: (name: string) => name === 'cdk8s' || /^cdk8s-plus(?:-(?:17|20|21|22))?$/.test(name), + // cdktf providers dependencies ("@cdktf/provider-xxx") are major versioned + // differently than the core library, so do not take them into account + [ConstructFrameworkName.CDKTF]: (name: string) => name === 'cdktf', +}; + /** * Determines the Construct framework used by the provided assembly. * @@ -28,65 +44,73 @@ export interface ConstructFramework { * * @returns a construct framework if one could be identified. */ -export function detectConstructFramework(assembly: Assembly): ConstructFramework | undefined { - let name: ConstructFramework['name'] | undefined; - let nameAmbiguous = false; - let majorVersion: number | undefined; - let majorVersionAmbiguous = false; - - // exception: we assume all @cdktf/ libraries are cdktf, even if they - // also take other CDK types as dependencies - if (assembly.name.startsWith('@cdktf/')) { - name = ConstructFrameworkName.CDKTF; - if ('cdktf' in (assembly.dependencyClosure ?? {})) { - detectConstructFrameworkPackage('cdktf'); - } - return { name, majorVersion }; - } +export function detectConstructFrameworks(assembly: Assembly): ConstructFramework[] { + // "not-sure" means we haven't seen a major version for the framework yet, + // e.g. in the case of a transitive dependency where the info isn't provided + // "ambiguous" means we have seen multiple major versions so it's impossible + // to resolve a single number + const detectedFrameworks: { [P in ConstructFrameworkName]?: number | 'no-data' | 'ambiguous' } = {}; detectConstructFrameworkPackage(assembly.name, assembly.version); for (const depName of Object.keys(assembly.dependencyClosure ?? {})) { detectConstructFrameworkPackage(depName); - if (nameAmbiguous) { - return undefined; + } + + const frameworks = new Array(); + for (const [frameworkName, majorVersion] of Object.entries(detectedFrameworks)) { + const name = frameworkName as ConstructFrameworkName; + if (majorVersion === undefined) { + continue; + } else if (majorVersion === 'ambiguous' || majorVersion === 'no-data') { + frameworks.push({ name }); + } else if (typeof majorVersion === 'number') { + frameworks.push({ name, majorVersion }); } } - return name && { name, majorVersion: majorVersionAmbiguous ? undefined : majorVersion }; + return frameworks; + /** + * Analyses the package name and version range, and updates + * `detectedFrameworks` from the parent scope appropriately + */ function detectConstructFrameworkPackage(packageName: string, versionRange = assembly.dependencies?.[packageName]): void { - if (packageName.startsWith('@aws-cdk/') || packageName === 'aws-cdk-lib' || packageName === 'monocdk') { - if (name && name !== ConstructFrameworkName.AWS_CDK) { - // Identified multiple candidates, so returning ambiguous... - nameAmbiguous = true; - return; - } - name = ConstructFrameworkName.AWS_CDK; - } else if (packageName === 'cdktf') { - if (name && name !== ConstructFrameworkName.CDKTF) { - // Identified multiple candidates, so returning ambiguous... - nameAmbiguous = true; - return; - } - name = ConstructFrameworkName.CDKTF; - } else if (packageName === 'cdk8s' || /^cdk8s-plus(?:-(?:17|20|21|22))?$/.test(packageName)) { - if (name && name !== ConstructFrameworkName.CDK8S) { - // Identified multiple candidates, so returning ambiguous... - nameAmbiguous = true; - return; - } - name = ConstructFrameworkName.CDK8S; - } else { - return; - } - if (versionRange) { - const major = minVersion(versionRange)?.major; - if (majorVersion != null && majorVersion !== major) { - // Identified multiple candidates, so this is ambiguous... - majorVersionAmbiguous = true; + for (const frameworkName of [ConstructFrameworkName.AWS_CDK, ConstructFrameworkName.CDK8S, ConstructFrameworkName.CDKTF]) { + const matchesFramework = FRAMEWORK_MATCHERS[frameworkName]; + if (matchesFramework(packageName)) { + const frameworkVersion = detectedFrameworks[frameworkName]; + if (frameworkVersion === 'ambiguous') { + // We have already seen multiple major versions and have determined + // the major version is ambiguous, so this package won't give + // us any new information. + return; + } + + const packageMajor = (versionRange ? minVersion(versionRange)?.major : undefined) ?? 'no-data'; + + if (frameworkVersion === undefined) { + // It's the first time seeing this major version, so we record + // whatever new information we found ("no-data" or number). + detectedFrameworks[frameworkName] = packageMajor; + return; + } else if (frameworkVersion === 'no-data') { + // We've seen this framework before but haven't seen a major version, + // so record whatever new information we found ("no-data" or number). + detectedFrameworks[frameworkName] = packageMajor; + return; + } else { + // At this point, frameworkVersion can only be a MV number + assert(typeof frameworkVersion === 'number'); + + // We've seen evidence of a particular major version for this + // framework, so only update if this package conflicts with what + // we're expecting. + if (packageMajor !== 'no-data' && frameworkVersion !== packageMajor) { + detectedFrameworks[frameworkName] = 'ambiguous'; + } + return; + } } - majorVersion = major; } - return; } } diff --git a/src/backend/ingestion/ingestion.lambda.ts b/src/backend/ingestion/ingestion.lambda.ts index d02c13910..74907931d 100644 --- a/src/backend/ingestion/ingestion.lambda.ts +++ b/src/backend/ingestion/ingestion.lambda.ts @@ -18,7 +18,7 @@ import { integrity } from '../shared/integrity.lambda-shared'; import { isTagApplicable } from '../shared/tags'; import { extractObjects } from '../shared/tarball.lambda-shared'; import { MetricName, METRICS_NAMESPACE } from './constants'; -import { ConstructFramework, detectConstructFramework } from './framework-detection.lambda-shared'; +import { ConstructFramework, detectConstructFrameworks } from './framework-detection.lambda-shared'; Configuration.namespace = METRICS_NAMESPACE; @@ -95,7 +95,7 @@ export const handler = metricScope( let parsedAssembly: Assembly; - let constructFramework: ConstructFramework | undefined; + let constructFrameworks: ConstructFramework[]; let packageLicense: string; let packageName: string; let packageVersion: string; @@ -104,7 +104,7 @@ export const handler = metricScope( parsedAssembly = validateAssembly(JSON.parse(dotJsii.toString('utf-8'))); // needs `dependencyClosure` - constructFramework = detectConstructFramework(parsedAssembly); + constructFrameworks = detectConstructFrameworks(parsedAssembly); const { license, name, version, readme } = parsedAssembly; packageLicense = license; packageName = name; @@ -204,7 +204,7 @@ export const handler = metricScope( } const metadata = { - constructFramework, + constructFrameworks, date: payload.time, licenseText: licenseText?.toString('utf-8'), packageLinks,