diff --git a/src/__tests__/__snapshots__/construct-hub.test.ts.snap b/src/__tests__/__snapshots__/construct-hub.test.ts.snap index bd3c9a19f..154eeae85 100644 --- a/src/__tests__/__snapshots__/construct-hub.test.ts.snap +++ b/src/__tests__/__snapshots__/construct-hub.test.ts.snap @@ -2144,7 +2144,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "3b2e45c592464b8d26e9f0326cc096032ea4ea8e68ae9cc5467b6b4c52496e65.zip", + "S3Key": "f6e25b911a4b8c4ba2ecd21a0691fe825b2e707faff84ddf0cb298e83311c410.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": Object { @@ -14502,7 +14502,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "3b2e45c592464b8d26e9f0326cc096032ea4ea8e68ae9cc5467b6b4c52496e65.zip", + "S3Key": "f6e25b911a4b8c4ba2ecd21a0691fe825b2e707faff84ddf0cb298e83311c410.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": Object { @@ -26774,7 +26774,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "3b2e45c592464b8d26e9f0326cc096032ea4ea8e68ae9cc5467b6b4c52496e65.zip", + "S3Key": "f6e25b911a4b8c4ba2ecd21a0691fe825b2e707faff84ddf0cb298e83311c410.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": Object { @@ -38987,7 +38987,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "3b2e45c592464b8d26e9f0326cc096032ea4ea8e68ae9cc5467b6b4c52496e65.zip", + "S3Key": "f6e25b911a4b8c4ba2ecd21a0691fe825b2e707faff84ddf0cb298e83311c410.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": Object { @@ -51421,7 +51421,7 @@ def submit_response(event: dict, context, response_status: str, error_message: s "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "3b2e45c592464b8d26e9f0326cc096032ea4ea8e68ae9cc5467b6b4c52496e65.zip", + "S3Key": "f6e25b911a4b8c4ba2ecd21a0691fe825b2e707faff84ddf0cb298e83311c410.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": Object { diff --git a/src/__tests__/backend/ingestion/ingestion.lambda.test.ts b/src/__tests__/backend/ingestion/ingestion.lambda.test.ts index 7e4944f8f..87799befb 100644 --- a/src/__tests__/backend/ingestion/ingestion.lambda.test.ts +++ b/src/__tests__/backend/ingestion/ingestion.lambda.test.ts @@ -8,6 +8,7 @@ import { SchemaVersion, Stability, TypeKind, + SPEC_FILE_NAME, } from '@jsii/spec'; import type { metricScope, MetricsLogger } from 'aws-embedded-metrics'; import { Context, SQSEvent } from 'aws-lambda'; @@ -147,7 +148,7 @@ test('basic happy case', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ name: packageName, @@ -374,7 +375,7 @@ test('basic happy case with license file', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/LICENSE.md': fakeLicense, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ @@ -617,7 +618,7 @@ test('basic happy case with custom package links', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ name: packageName, @@ -887,7 +888,7 @@ test('basic happy case with custom tags', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ name: packageName, @@ -1123,7 +1124,7 @@ for (const [frameworkName, frameworkPackage] of [ mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ name: packageName, @@ -1342,7 +1343,7 @@ for (const [frameworkName, frameworkPackage] of [ mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ name: frameworkPackage, @@ -1569,7 +1570,7 @@ for (const [frameworkName, frameworkPackage] of [ mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ name: packageName, @@ -1790,7 +1791,7 @@ test('mismatched package name', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/LICENSE.md': fakeLicense, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ @@ -1928,7 +1929,7 @@ test('mismatched package version', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/LICENSE.md': fakeLicense, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ @@ -2066,7 +2067,7 @@ test('mismatched package license', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/LICENSE.md': fakeLicense, 'package/index.js': '// Ignore me!', 'package/package.json': JSON.stringify({ @@ -2332,7 +2333,7 @@ test('missing package.json file', async () => { mockExtract.mockImplementation( () => new FakeExtract(fakeTar, { - 'package/.jsii': fakeDotJsii, + [`package/${SPEC_FILE_NAME}`]: fakeDotJsii, 'package/LICENSE.md': fakeLicense, 'package/index.js': '// Ignore me!', }) as any diff --git a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap index ab0fc83b3..05acc98db 100644 --- a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap +++ b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap @@ -6304,7 +6304,7 @@ Resources: Code: S3Bucket: Fn::Sub: cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region} - S3Key: 3b2e45c592464b8d26e9f0326cc096032ea4ea8e68ae9cc5467b6b4c52496e65.zip + S3Key: f6e25b911a4b8c4ba2ecd21a0691fe825b2e707faff84ddf0cb298e83311c410.zip Role: Fn::GetAtt: - ConstructHubIngestionServiceRole6380BAB6 diff --git a/src/__tests__/package-sources/__snapshots__/code-artifact.test.ts.snap b/src/__tests__/package-sources/__snapshots__/code-artifact.test.ts.snap index 82118bc87..b6c99f3dd 100644 --- a/src/__tests__/package-sources/__snapshots__/code-artifact.test.ts.snap +++ b/src/__tests__/package-sources/__snapshots__/code-artifact.test.ts.snap @@ -240,7 +240,7 @@ Object { "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "e766aef9bfcb5580eeb16072ef5522876bc3b8edb7a103acc8a502b0f65f4230.zip", + "S3Key": "d438ede6f3d607178a5d74010de88ea8259413c6d271d73d67078928ac889ac1.zip", }, "DeadLetterConfig": Object { "TargetArn": Object { @@ -721,7 +721,7 @@ Object { "S3Bucket": Object { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "e766aef9bfcb5580eeb16072ef5522876bc3b8edb7a103acc8a502b0f65f4230.zip", + "S3Key": "d438ede6f3d607178a5d74010de88ea8259413c6d271d73d67078928ac889ac1.zip", }, "DeadLetterConfig": Object { "TargetArn": Object { diff --git a/src/__tests__/package-sources/codeartifact/code-artifact-forwarder.lambda.test.ts b/src/__tests__/package-sources/codeartifact/code-artifact-forwarder.lambda.test.ts index 5898070a9..a0bf4d76d 100644 --- a/src/__tests__/package-sources/codeartifact/code-artifact-forwarder.lambda.test.ts +++ b/src/__tests__/package-sources/codeartifact/code-artifact-forwarder.lambda.test.ts @@ -1,4 +1,5 @@ import { pseudoRandomBytes } from 'crypto'; +import { SPEC_FILE_NAME } from '@jsii/spec'; import type { Context } from 'aws-lambda'; import * as AWS from 'aws-sdk'; import * as AWSMock from 'aws-sdk-mock'; @@ -142,7 +143,9 @@ test('happy path', async () => { expect(tgz).toEqual( Buffer.from(mockGetPackageVersionAssetResult.asset! as any) ); - expect(selector).toHaveProperty('assemblyJson', { path: 'package/.jsii' }); + expect(selector).toHaveProperty('assemblyJson', { + path: `package/${SPEC_FILE_NAME}`, + }); expect(selector).toHaveProperty('packageJson', { path: 'package/package.json', required: true, @@ -295,7 +298,9 @@ test('no license (i.e: UNLICENSED)', async () => { expect(tgz).toEqual( Buffer.from(mockGetPackageVersionAssetResult.asset! as any) ); - expect(selector).toHaveProperty('assemblyJson', { path: 'package/.jsii' }); + expect(selector).toHaveProperty('assemblyJson', { + path: `package/${SPEC_FILE_NAME}`, + }); expect(selector).toHaveProperty('packageJson', { path: 'package/package.json', required: true, @@ -370,7 +375,9 @@ test('ineligible license', async () => { expect(tgz).toEqual( Buffer.from(mockGetPackageVersionAssetResult.asset! as any) ); - expect(selector).toHaveProperty('assemblyJson', { path: 'package/.jsii' }); + expect(selector).toHaveProperty('assemblyJson', { + path: `package/${SPEC_FILE_NAME}`, + }); expect(selector).toHaveProperty('packageJson', { path: 'package/package.json', required: true, @@ -444,7 +451,9 @@ test('not a jsii package', async () => { expect(tgz).toEqual( Buffer.from(mockGetPackageVersionAssetResult.asset! as any) ); - expect(selector).toHaveProperty('assemblyJson', { path: 'package/.jsii' }); + expect(selector).toHaveProperty('assemblyJson', { + path: `package/${SPEC_FILE_NAME}`, + }); expect(selector).toHaveProperty('packageJson', { path: 'package/package.json', required: true, diff --git a/src/backend/ingestion/index.ts b/src/backend/ingestion/index.ts index 41c59a7b9..c6dbb9fbf 100644 --- a/src/backend/ingestion/index.ts +++ b/src/backend/ingestion/index.ts @@ -374,7 +374,7 @@ export class Ingestion extends Construct implements IGrantable { /** * This metrics is the total count of packages that were rejected due to * mismatched identity (name, version, license) between the `package.json` - * file and te `.jsii` attribute. + * file and the `.jsii` attribute. */ public metricMismatchedIdentityRejections(opts?: MetricOptions): Metric { return new Metric({ diff --git a/src/backend/ingestion/ingestion.lambda.ts b/src/backend/ingestion/ingestion.lambda.ts index 5c5fe4823..0622daa2e 100644 --- a/src/backend/ingestion/ingestion.lambda.ts +++ b/src/backend/ingestion/ingestion.lambda.ts @@ -2,7 +2,12 @@ import { createHash } from 'crypto'; import { basename, extname } from 'path'; import { URL } from 'url'; -import { Assembly, validateAssembly } from '@jsii/spec'; +import { + SPEC_FILE_NAME, + Assembly, + loadAssemblyFromBuffer, + SPEC_FILE_NAME_COMPRESSED, +} from '@jsii/spec'; import { metricScope, Configuration, Unit } from 'aws-embedded-metrics'; import type { Context, SQSEvent } from 'aws-lambda'; import { CacheStrategy } from '../../caching'; @@ -87,18 +92,21 @@ export const handler = metricScope( ); } + const dotJsiiFile = `package/${SPEC_FILE_NAME}`; + const compDotJsiiFile = `package/${SPEC_FILE_NAME_COMPRESSED}`; + let dotJsii: Buffer; + let compDotJsii: Buffer | undefined; let packageJson: Buffer; let licenseText: Buffer | undefined; try { - ({ dotJsii, packageJson, licenseText } = await extractObjects( - Buffer.from(tarball.Body! as any), - { - dotJsii: { path: 'package/.jsii', required: true }, + ({ dotJsii, compDotJsii, packageJson, licenseText } = + await extractObjects(Buffer.from(tarball.Body! as any), { + dotJsii: { path: dotJsiiFile, required: true }, + compDotJsii: { path: compDotJsiiFile }, packageJson: { path: 'package/package.json', required: true }, licenseText: { filter: isLicenseFile }, - } - )); + })); } catch (err) { console.error(`Invalid tarball content: ${err}`); metrics.putMetric(MetricName.INVALID_TARBALL, 1, Unit.Count); @@ -112,8 +120,16 @@ export const handler = metricScope( let packageVersion: string; let packageReadme: string; try { - parsedAssembly = validateAssembly( - JSON.parse(dotJsii.toString('utf-8')) + parsedAssembly = loadAssemblyFromBuffer( + dotJsii, + compDotJsii + ? (filename: string) => { + if (filename !== compDotJsiiFile) { + throw new Error(''); + } + return compDotJsii!; + } + : undefined ); // needs `dependencyClosure` diff --git a/src/package-sources/codeartifact/code-artifact-forwarder.lambda.ts b/src/package-sources/codeartifact/code-artifact-forwarder.lambda.ts index a615f997c..083720035 100644 --- a/src/package-sources/codeartifact/code-artifact-forwarder.lambda.ts +++ b/src/package-sources/codeartifact/code-artifact-forwarder.lambda.ts @@ -1,3 +1,4 @@ +import { SPEC_FILE_NAME } from '@jsii/spec'; import { metricScope, Unit } from 'aws-embedded-metrics'; import type { Context, EventBridgeEvent } from 'aws-lambda'; @@ -75,7 +76,7 @@ export const handler = metricScope( const tarball = Buffer.from(asset! as any); const { assemblyJson, packageJson } = await extractObjects(tarball, { - assemblyJson: { path: 'package/.jsii' }, + assemblyJson: { path: `package/${SPEC_FILE_NAME}` }, packageJson: { path: 'package/package.json', required: true }, }); metrics.putMetric( @@ -85,7 +86,7 @@ export const handler = metricScope( ); if (assemblyJson == null) { console.log( - `Package "${packageName}@${event.detail.packageVersion}" does not contain a .jsii assembly` + `Package "${packageName}@${event.detail.packageVersion}" does not contain a ${SPEC_FILE_NAME} assembly` ); return; }