diff --git a/.github/workflows/close-stale-prs.yml b/.github/workflows/close-stale-prs.yml index 928948b14e278..0fd02ddfdcd5f 100644 --- a/.github/workflows/close-stale-prs.yml +++ b/.github/workflows/close-stale-prs.yml @@ -3,7 +3,7 @@ on: # Cron format: min hr day month dow - cron: "0 0 * * *" jobs: - rix0rrr/close-stale-prs: + close-stale-prs: permissions: pull-requests: write runs-on: ubuntu-latest diff --git a/deprecated_apis.txt b/deprecated_apis.txt index 2799630df4e1c..1f52234d183f6 100644 --- a/deprecated_apis.txt +++ b/deprecated_apis.txt @@ -27,7 +27,6 @@ @aws-cdk/core.DefaultStackSynthesizerProps#fileAssetKeyArnExportName @aws-cdk/core.DockerImageAssetSource#repositoryName @aws-cdk/core.Duration#toISOString -@aws-cdk/core.FileAssetLocation#kmsKeyArn @aws-cdk/core.FileAssetLocation#s3Url @aws-cdk/core.ITemplateOptions#transform @aws-cdk/core.Lazy#anyValue diff --git a/package.json b/package.json index d01f1f0adffd2..c14d5e45cac13 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,10 @@ "fs-extra": "^9.1.0", "graceful-fs": "^4.2.10", "jest-junit": "^13.1.0", - "jsii-diff": "^1.56.0", - "jsii-pacmak": "^1.56.0", - "jsii-reflect": "^1.56.0", - "jsii-rosetta": "^1.56.0", + "jsii-diff": "^1.57.0", + "jsii-pacmak": "^1.57.0", + "jsii-reflect": "^1.57.0", + "jsii-rosetta": "^1.57.0", "lerna": "^4.0.0", "patch-package": "^6.4.7", "semver": "^6.3.0", diff --git a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json index 1821a5a5c0c9a..19ffb0de8ed1f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json @@ -33713,7 +33713,7 @@ "properties": { "AllocatedStorage": "The amount of storage (in gigabytes) to be initially allocated for the database instance.\n\n> If any value is set in the `Iops` parameter, `AllocatedStorage` must be at least 100 GiB, which corresponds to the minimum Iops value of 1,000. If you increase the `Iops` value (in 1,000 IOPS increments), then you must also increase the `AllocatedStorage` value (in 100-GiB increments). \n\n*Amazon Aurora*\n\nNot applicable. Aurora cluster volumes automatically grow as the amount of data in your database increases, though you are only charged for the space that you use in an Aurora cluster volume.\n\n*MySQL*\n\nConstraints to the amount of storage for each storage type are the following:\n\n- General Purpose (SSD) storage (gp2): Must be an integer from 20 to 65536.\n- Provisioned IOPS storage (io1): Must be an integer from 100 to 65536.\n- Magnetic storage (standard): Must be an integer from 5 to 3072.\n\n*MariaDB*\n\nConstraints to the amount of storage for each storage type are the following:\n\n- General Purpose (SSD) storage (gp2): Must be an integer from 20 to 65536.\n- Provisioned IOPS storage (io1): Must be an integer from 100 to 65536.\n- Magnetic storage (standard): Must be an integer from 5 to 3072.\n\n*PostgreSQL*\n\nConstraints to the amount of storage for each storage type are the following:\n\n- General Purpose (SSD) storage (gp2): Must be an integer from 20 to 65536.\n- Provisioned IOPS storage (io1): Must be an integer from 100 to 65536.\n- Magnetic storage (standard): Must be an integer from 5 to 3072.\n\n*Oracle*\n\nConstraints to the amount of storage for each storage type are the following:\n\n- General Purpose (SSD) storage (gp2): Must be an integer from 20 to 65536.\n- Provisioned IOPS storage (io1): Must be an integer from 100 to 65536.\n- Magnetic storage (standard): Must be an integer from 10 to 3072.\n\n*SQL Server*\n\nConstraints to the amount of storage for each storage type are the following:\n\n- General Purpose (SSD) storage (gp2):\n\n- Enterprise and Standard editions: Must be an integer from 20 to 16384.\n- Web and Express editions: Must be an integer from 20 to 16384.\n- Provisioned IOPS storage (io1):\n\n- Enterprise and Standard editions: Must be an integer from 20 to 16384.\n- Web and Express editions: Must be an integer from 20 to 16384.\n- Magnetic storage (standard):\n\n- Enterprise and Standard editions: Must be an integer from 20 to 1024.\n- Web and Express editions: Must be an integer from 20 to 1024.", "AllowMajorVersionUpgrade": "A value that indicates whether major version upgrades are allowed. Changing this parameter doesn't result in an outage and the change is asynchronously applied as soon as possible.\n\nConstraints: Major version upgrades must be allowed when specifying a value for the `EngineVersion` parameter that is a different major version than the DB instance's current version.", - "AssociatedRoles": "The AWS Identity and Access Management (IAM) roles associated with the DB instance.", + "AssociatedRoles": "The AWS Identity and Access Management (IAM) roles associated with the DB instance.\n\n*Amazon Aurora*\n\nNot applicable. The associated roles are managed by the DB cluster.", "AutoMinorVersionUpgrade": "A value that indicates whether minor engine upgrades are applied automatically to the DB instance during the maintenance window. By default, minor engine upgrades are applied automatically.", "AvailabilityZone": "The Availability Zone (AZ) where the database will be created. For information on AWS Regions and Availability Zones, see [Regions and Availability Zones](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html) .\n\n*Amazon Aurora*\n\nEach Aurora DB cluster hosts copies of its storage in three separate Availability Zones. Specify one of these Availability Zones. Aurora automatically chooses an appropriate Availability Zone if you don't specify one.\n\nDefault: A random, system-chosen Availability Zone in the endpoint's AWS Region .\n\nExample: `us-east-1d`\n\nConstraint: The `AvailabilityZone` parameter can't be specified if the DB instance is a Multi-AZ deployment. The specified Availability Zone must be in the same AWS Region as the current endpoint.\n\n> If you're creating a DB instance in an RDS on VMware environment, specify the identifier of the custom Availability Zone to create the DB instance in.\n> \n> For more information about RDS on VMware, see the [RDS on VMware User Guide.](https://docs.aws.amazon.com/AmazonRDS/latest/RDSonVMwareUserGuide/rds-on-vmware.html)", "BackupRetentionPeriod": "The number of days for which automated backups are retained. Setting this parameter to a positive number enables backups. Setting this parameter to 0 disables automated backups.\n\n*Amazon Aurora*\n\nNot applicable. The retention period for automated backups is managed by the DB cluster.\n\nDefault: 1\n\nConstraints:\n\n- Must be a value from 0 to 35\n- Can't be set to 0 if the DB instance is a source to read replicas", @@ -33723,10 +33723,10 @@ "DBClusterIdentifier": "The identifier of the DB cluster that the instance will belong to.", "DBInstanceClass": "The compute and memory capacity of the DB instance, for example, `db.m4.large` . Not all DB instance classes are available in all AWS Regions, or for all database engines.\n\nFor the full list of DB instance classes, and availability for your engine, see [DB Instance Class](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html) in the *Amazon RDS User Guide.* For more information about DB instance class pricing and AWS Region support for DB instance classes, see [Amazon RDS Pricing](https://docs.aws.amazon.com/rds/pricing/) .", "DBInstanceIdentifier": "A name for the DB instance. If you specify a name, AWS CloudFormation converts it to lowercase. If you don't specify a name, AWS CloudFormation generates a unique physical ID and uses that ID for the DB instance. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\nFor information about constraints that apply to DB instance identifiers, see [Naming constraints in Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints) in the *Amazon RDS User Guide* .\n\n> If you specify a name, you can't perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", - "DBName": "The meaning of this parameter differs according to the database engine you use.\n\n> If you specify the `[DBSnapshotIdentifier](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-dbsnapshotidentifier)` property, AWS CloudFormation ignores this property.\n> \n> If you restore DB instances from snapshots, this property doesn't apply to the MySQL, PostgreSQL, or MariaDB engines. \n\n*MySQL*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, no database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 64 letters or numbers.\n- Can't be a word reserved by the specified database engine\n\n*MariaDB*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, no database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 64 letters or numbers.\n- Can't be a word reserved by the specified database engine\n\n*PostgreSQL*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, the default `postgres` database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 63 letters, numbers, or underscores.\n- Must begin with a letter or an underscore. Subsequent characters can be letters, underscores, or digits (0-9).\n- Can't be a word reserved by the specified database engine\n\n*Oracle*\n\nThe Oracle System ID (SID) of the created DB instance. If you specify `null` , the default value `ORCL` is used. You can't specify the string NULL, or any other reserved word, for `DBName` .\n\nDefault: `ORCL`\n\nConstraints:\n\n- Can't be longer than 8 characters\n\n*SQL Server*\n\nNot applicable. Must be null.\n\n*Amazon Aurora MySQL*\n\nThe name of the database to create when the primary DB instance of the Aurora MySQL DB cluster is created. If this parameter isn't specified for an Aurora MySQL DB cluster, no database is created in the DB cluster.\n\nConstraints:\n\n- It must contain 1 to 64 alphanumeric characters.\n- It can't be a word reserved by the database engine.\n\n*Amazon Aurora PostgreSQL*\n\nThe name of the database to create when the primary DB instance of the Aurora PostgreSQL DB cluster is created. If this parameter isn't specified for an Aurora PostgreSQL DB cluster, a database named `postgres` is created in the DB cluster.\n\nConstraints:\n\n- It must contain 1 to 63 alphanumeric characters.\n- It must begin with a letter or an underscore. Subsequent characters can be letters, underscores, or digits (0 to 9).\n- It can't be a word reserved by the database engine.", + "DBName": "The meaning of this parameter differs according to the database engine you use.\n\n> If you specify the `[DBSnapshotIdentifier](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-dbsnapshotidentifier)` property, AWS CloudFormation ignores this property.\n> \n> If you restore DB instances from snapshots, this property doesn't apply to the MySQL, PostgreSQL, or MariaDB engines. \n\n*Amazon Aurora*\n\nNot applicable. The database name is managed by the DB cluster.\n\n*MySQL*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, no database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 64 letters or numbers.\n- Can't be a word reserved by the specified database engine\n\n*MariaDB*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, no database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 64 letters or numbers.\n- Can't be a word reserved by the specified database engine\n\n*PostgreSQL*\n\nThe name of the database to create when the DB instance is created. If this parameter is not specified, the default `postgres` database is created in the DB instance.\n\nConstraints:\n\n- Must contain 1 to 63 letters, numbers, or underscores.\n- Must begin with a letter or an underscore. Subsequent characters can be letters, underscores, or digits (0-9).\n- Can't be a word reserved by the specified database engine\n\n*Oracle*\n\nThe Oracle System ID (SID) of the created DB instance. If you specify `null` , the default value `ORCL` is used. You can't specify the string NULL, or any other reserved word, for `DBName` .\n\nDefault: `ORCL`\n\nConstraints:\n\n- Can't be longer than 8 characters\n\n*SQL Server*\n\nNot applicable. Must be null.", "DBParameterGroupName": "The name of an existing DB parameter group or a reference to an [AWS::RDS::DBParameterGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbparametergroup.html) resource created in the template.\n\nTo list all of the available DB parameter group names, use the following command:\n\n`aws rds describe-db-parameter-groups --query \"DBParameterGroups[].DBParameterGroupName\" --output text`\n\n> If any of the data members of the referenced parameter group are changed during an update, the DB instance might need to be restarted, which causes some interruption. If the parameter group contains static parameters, whether they were changed or not, an update triggers a reboot. \n\nIf you don't specify a value for the `DBParameterGroupName` property, the default DB parameter group for the specified engine and engine version is used.", "DBSecurityGroups": "A list of the DB security groups to assign to the DB instance. The list can include both the name of existing DB security groups or references to AWS::RDS::DBSecurityGroup resources created in the template.\n\nIf you set DBSecurityGroups, you must not set VPCSecurityGroups, and vice versa. Also, note that the DBSecurityGroups property exists only for backwards compatibility with older regions and is no longer recommended for providing security information to an RDS DB instance. Instead, use VPCSecurityGroups.\n\n> If you specify this property, AWS CloudFormation sends only the following properties (if specified) to Amazon RDS during create operations:\n> \n> - `AllocatedStorage`\n> - `AutoMinorVersionUpgrade`\n> - `AvailabilityZone`\n> - `BackupRetentionPeriod`\n> - `CharacterSetName`\n> - `DBInstanceClass`\n> - `DBName`\n> - `DBParameterGroupName`\n> - `DBSecurityGroups`\n> - `DBSubnetGroupName`\n> - `Engine`\n> - `EngineVersion`\n> - `Iops`\n> - `LicenseModel`\n> - `MasterUsername`\n> - `MasterUserPassword`\n> - `MultiAZ`\n> - `OptionGroupName`\n> - `PreferredBackupWindow`\n> - `PreferredMaintenanceWindow`\n> \n> All other properties are ignored. Specify a virtual private cloud (VPC) security group if you want to submit other properties, such as `StorageType` , `StorageEncrypted` , or `KmsKeyId` . If you're already using the `DBSecurityGroups` property, you can't use these other properties by updating your DB instance to use a VPC security group. You must recreate the DB instance.", - "DBSnapshotIdentifier": "The name or Amazon Resource Name (ARN) of the DB snapshot that's used to restore the DB instance. If you're restoring from a shared manual DB snapshot, you must specify the ARN of the snapshot.\n\nBy specifying this property, you can create a DB instance from the specified DB snapshot. If the `DBSnapshotIdentifier` property is an empty string or the `AWS::RDS::DBInstance` declaration has no `DBSnapshotIdentifier` property, AWS CloudFormation creates a new database. If the property contains a value (other than an empty string), AWS CloudFormation creates a database from the specified snapshot. If a snapshot with the specified name doesn't exist, AWS CloudFormation can't create the database and it rolls back the stack.\n\nSome DB instance properties aren't valid when you restore from a snapshot, such as the `MasterUsername` and `MasterUserPassword` properties. For information about the properties that you can specify, see the `RestoreDBInstanceFromDBSnapshot` action in the *Amazon RDS API Reference* .\n\nAfter you restore a DB instance with a `DBSnapshotIdentifier` property, you must specify the same `DBSnapshotIdentifier` property for any future updates to the DB instance. When you specify this property for an update, the DB instance is not restored from the DB snapshot again, and the data in the database is not changed. However, if you don't specify the `DBSnapshotIdentifier` property, an empty DB instance is created, and the original DB instance is deleted. If you specify a property that is different from the previous snapshot restore property, a new DB instance is restored from the specified `DBSnapshotIdentifier` property, and the original DB instance is deleted.\n\nIf you specify the `DBSnapshotIdentifier` property to restore a DB instance (as opposed to specifying it for DB instance updates), then don't specify the following properties:\n\n- `CharacterSetName`\n- `DBClusterIdentifier`\n- `DBName`\n- `DeleteAutomatedBackups`\n- `EnablePerformanceInsights`\n- `KmsKeyId`\n- `MasterUsername`\n- `MonitoringInterval`\n- `MonitoringRoleArn`\n- `PerformanceInsightsKMSKeyId`\n- `PerformanceInsightsRetentionPeriod`\n- `PromotionTier`\n- `SourceDBInstanceIdentifier`\n- `SourceRegion`\n- `StorageEncrypted`\n- `Timezone`", + "DBSnapshotIdentifier": "The name or Amazon Resource Name (ARN) of the DB snapshot that's used to restore the DB instance. If you're restoring from a shared manual DB snapshot, you must specify the ARN of the snapshot.\n\nBy specifying this property, you can create a DB instance from the specified DB snapshot. If the `DBSnapshotIdentifier` property is an empty string or the `AWS::RDS::DBInstance` declaration has no `DBSnapshotIdentifier` property, AWS CloudFormation creates a new database. If the property contains a value (other than an empty string), AWS CloudFormation creates a database from the specified snapshot. If a snapshot with the specified name doesn't exist, AWS CloudFormation can't create the database and it rolls back the stack.\n\nSome DB instance properties aren't valid when you restore from a snapshot, such as the `MasterUsername` and `MasterUserPassword` properties. For information about the properties that you can specify, see the `RestoreDBInstanceFromDBSnapshot` action in the *Amazon RDS API Reference* .\n\nAfter you restore a DB instance with a `DBSnapshotIdentifier` property, you must specify the same `DBSnapshotIdentifier` property for any future updates to the DB instance. When you specify this property for an update, the DB instance is not restored from the DB snapshot again, and the data in the database is not changed. However, if you don't specify the `DBSnapshotIdentifier` property, an empty DB instance is created, and the original DB instance is deleted. If you specify a property that is different from the previous snapshot restore property, a new DB instance is restored from the specified `DBSnapshotIdentifier` property, and the original DB instance is deleted.\n\nIf you specify the `DBSnapshotIdentifier` property to restore a DB instance (as opposed to specifying it for DB instance updates), then don't specify the following properties:\n\n- `CharacterSetName`\n- `DBClusterIdentifier`\n- `DBName`\n- `DeleteAutomatedBackups`\n- `EnablePerformanceInsights`\n- `KmsKeyId`\n- `MasterUsername`\n- `MonitoringInterval`\n- `MonitoringRoleArn`\n- `PerformanceInsightsKMSKeyId`\n- `PerformanceInsightsRetentionPeriod`\n- `PromotionTier`\n- `SourceDBInstanceIdentifier`\n- `SourceRegion`\n- `StorageEncrypted`\n- `Timezone`\n\n*Amazon Aurora*\n\nNot applicable. Snapshot restore is managed by the DB cluster.", "DBSubnetGroupName": "A DB subnet group to associate with the DB instance. If you update this value, the new subnet group must be a subnet group in a new VPC.\n\nIf there's no DB subnet group, then the DB instance isn't a VPC DB instance.\n\nFor more information about using Amazon RDS in a VPC, see [Using Amazon RDS with Amazon Virtual Private Cloud (VPC)](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.html) in the *Amazon RDS User Guide* .\n\n*Amazon Aurora*\n\nNot applicable. The DB subnet group is managed by the DB cluster. If specified, the setting must match the DB cluster setting.", "DeleteAutomatedBackups": "A value that indicates whether to remove automated backups immediately after the DB instance is deleted. This parameter isn't case-sensitive. The default is to remove automated backups immediately after the DB instance is deleted.", "DeletionProtection": "A value that indicates whether the DB instance has deletion protection enabled. The database can't be deleted when deletion protection is enabled. By default, deletion protection is disabled. For more information, see [Deleting a DB Instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_DeleteInstance.html) .\n\n*Amazon Aurora*\n\nNot applicable. You can enable or disable deletion protection for the DB cluster. For more information, see `CreateDBCluster` . DB instances in a DB cluster can be deleted even when deletion protection is enabled for the DB cluster.", diff --git a/packages/@aws-cdk/core/lib/assets.ts b/packages/@aws-cdk/core/lib/assets.ts index 7466ded8e6d60..b9a0ebd2b1bc6 100644 --- a/packages/@aws-cdk/core/lib/assets.ts +++ b/packages/@aws-cdk/core/lib/assets.ts @@ -274,21 +274,14 @@ export interface FileAssetLocation { readonly s3ObjectUrl: string; /** - * The ARN of the KMS key used to encrypt the file asset bucket, if any + * The ARN of the KMS key used to encrypt the file asset bucket, if any. * - * If so, the consuming role should be given "kms:Decrypt" permissions in its - * identity policy. + * The CDK bootstrap stack comes with a key policy that does not require + * setting this property, so you only need to set this property if you + * have customized the bootstrap stack to require it. * - * It's the responsibility of they key's creator to make sure that all - * consumers that the key's key policy is configured such that the key can be used - * by all consumers that need it. - * - * The default bootstrap stack provisioned by the CDK CLI ensures this, and - * can be used as an example for how to configure the key properly. - * - * @default - Asset bucket is not encrypted - * @deprecated Since bootstrap bucket v4, the key policy properly allows use of the - * key via the bucket and no additional parameters have to be granted anymore. + * @default - Asset bucket is not encrypted, or decryption permissions are + * defined by a Key Policy. */ readonly kmsKeyArn?: string; diff --git a/packages/@aws-cdk/integ-tests/README.md b/packages/@aws-cdk/integ-tests/README.md index d8ae02bd93d7a..9d67d10c8bb6e 100644 --- a/packages/@aws-cdk/integ-tests/README.md +++ b/packages/@aws-cdk/integ-tests/README.md @@ -1,4 +1,4 @@ -# integ-runner +# integ-tests diff --git a/packages/@aws-cdk/integ-tests/test/manifest-writer.test.ts b/packages/@aws-cdk/integ-tests/test/manifest-writer.test.ts index e0e43ae9563d9..537939647b3d7 100644 --- a/packages/@aws-cdk/integ-tests/test/manifest-writer.test.ts +++ b/packages/@aws-cdk/integ-tests/test/manifest-writer.test.ts @@ -21,7 +21,7 @@ describe(IntegManifestWriter, () => { }; beforeEach(() => { - tmpDir = fs.mkdtempSync(os.tmpdir()); + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-test')); }); afterEach(() => { diff --git a/packages/aws-cdk/lib/cli.ts b/packages/aws-cdk/lib/cli.ts index 684b415dd2524..5e813f4f9a2f4 100644 --- a/packages/aws-cdk/lib/cli.ts +++ b/packages/aws-cdk/lib/cli.ts @@ -282,8 +282,7 @@ async function initCommandLine() { if (shouldDisplayNotices()) { void refreshNotices() - .then(_ => debug('Notices refreshed')) - .catch(e => debug(`Notices refresh failed: ${e}`)); + .catch(e => debug(`Could not refresh notices: ${e}`)); } const sdkProvider = await SdkProvider.withAwsCliCompatibleDefaults({ diff --git a/packages/aws-cdk/lib/notices.ts b/packages/aws-cdk/lib/notices.ts index b0d40990ca1f8..e719dc1739f21 100644 --- a/packages/aws-cdk/lib/notices.ts +++ b/packages/aws-cdk/lib/notices.ts @@ -107,9 +107,7 @@ export interface NoticeDataSource { export class WebsiteNoticeDataSource implements NoticeDataSource { fetch(): Promise { const timeout = 3000; - - return new Promise((resolve) => { - setTimeout(() => resolve([]), timeout); + return new Promise((resolve, reject) => { try { const req = https.get('https://cli.cdk.dev-tools.aws.dev/notices.json', { timeout }, @@ -123,29 +121,39 @@ export class WebsiteNoticeDataSource implements NoticeDataSource { res.on('end', () => { try { const data = JSON.parse(rawData).notices as Notice[]; + if (!data) { + throw new Error("'notices' key is missing"); + } + debug('Notices refreshed'); resolve(data ?? []); } catch (e) { - debug(`Failed to parse notices: ${e}`); - resolve([]); + reject(new Error(`Failed to parse notices: ${e.message}`)); } }); res.on('error', e => { - debug(`Failed to fetch notices: ${e}`); - resolve([]); + reject(new Error(`Failed to fetch notices: ${e.message}`)); }); } else { - debug(`Failed to fetch notices. Status code: ${res.statusCode}`); - resolve([]); + reject(new Error(`Failed to fetch notices. Status code: ${res.statusCode}`)); } }); - req.on('error', e => { - debug(`Error on request: ${e}`); - resolve([]); + req.on('error', reject); + req.on('timeout', () => { + // The 'timeout' event doesn't stop anything by itself, it just + // notifies that it has been long time since we saw bytes. + // In our case, we want to give up. + req.destroy(new Error('Request timed out')); }); - req.on('timeout', _ => resolve([])); + + // It's not like I don't *trust* the 'timeout' event... but I don't trust it. + // Add a backup timer that will destroy the request after all. + // (This is at least necessary to make the tests pass, but that's probably because of 'nock'. + // It's not clear whether users will hit this). + setTimeout(() => { + req.destroy(new Error('Request timed out. You should never see this message; if you do, please let us know at https://github.com/aws/aws-cdk/issues')); + }, timeout + 200); } catch (e) { - debug(`HTTPS 'get' call threw an error: ${e}`); - resolve([]); + reject(new Error(`HTTPS 'get' call threw an error: ${e.message}`)); } }); } @@ -156,7 +164,8 @@ interface CachedNotices { notices: Notice[], } -const TIME_TO_LIVE = 60 * 60 * 1000; // 1 hour +const TIME_TO_LIVE_SUCCESS = 60 * 60 * 1000; // 1 hour +const TIME_TO_LIVE_ERROR = 1 * 60 * 1000; // 1 minute export class CachedDataSource implements NoticeDataSource { constructor( @@ -171,17 +180,30 @@ export class CachedDataSource implements NoticeDataSource { const expiration = cachedData.expiration ?? 0; if (Date.now() > expiration || this.skipCache) { - const freshData = { - expiration: Date.now() + TIME_TO_LIVE, - notices: await this.dataSource.fetch(), - }; + const freshData = await this.fetchInner(); await this.save(freshData); return freshData.notices; } else { + debug(`Reading cached notices from ${this.fileName}`); return data; } } + private async fetchInner(): Promise { + try { + return { + expiration: Date.now() + TIME_TO_LIVE_SUCCESS, + notices: await this.dataSource.fetch(), + }; + } catch (e) { + debug(`Could not refresh notices: ${e}`); + return { + expiration: Date.now() + TIME_TO_LIVE_ERROR, + notices: [], + }; + } + } + private async load(): Promise { const defaultValue = { expiration: 0, diff --git a/packages/aws-cdk/test/notices.test.ts b/packages/aws-cdk/test/notices.test.ts index c2efe5cfaf904..dd9ae31c7fb76 100644 --- a/packages/aws-cdk/test/notices.test.ts +++ b/packages/aws-cdk/test/notices.test.ts @@ -191,50 +191,50 @@ describe('cli notices', () => { expect(result).toEqual([BASIC_NOTICE, MULTIPLE_AFFECTED_VERSIONS_NOTICE]); }); - test('returns empty array when the server returns an unexpected status code', async () => { - const result = await mockCall(500, { + test('returns appropriate error when the server returns an unexpected status code', async () => { + const result = mockCall(500, { notices: [BASIC_NOTICE, MULTIPLE_AFFECTED_VERSIONS_NOTICE], }); - expect(result).toEqual([]); + await expect(result).rejects.toThrow(/500/); }); - test('returns empty array when the server returns an unexpected structure', async () => { - const result = await mockCall(200, { + test('returns appropriate error when the server returns an unexpected structure', async () => { + const result = mockCall(200, { foo: [BASIC_NOTICE, MULTIPLE_AFFECTED_VERSIONS_NOTICE], }); - expect(result).toEqual([]); + await expect(result).rejects.toThrow(/key is missing/); }); - test('returns empty array when the server returns invalid json', async () => { - const result = await mockCall(200, '-09aiskjkj838'); + test('returns appropriate error when the server returns invalid json', async () => { + const result = mockCall(200, '-09aiskjkj838'); - expect(result).toEqual([]); + await expect(result).rejects.toThrow(/Failed to parse/); }); - test('returns empty array when HTTPS call throws', async () => { + test('returns appropriate error when HTTPS call throws', async () => { const mockGet = jest.spyOn(https, 'get') .mockImplementation(() => { throw new Error('No connection'); }); - const result = await dataSource.fetch(); + const result = dataSource.fetch(); - expect(result).toEqual([]); + await expect(result).rejects.toThrow(/No connection/); mockGet.mockRestore(); }); - test('returns empty array when the request has an error', async () => { + test('returns appropriate error when the request has an error', async () => { nock('https://cli.cdk.dev-tools.aws.dev') .get('/notices.json') .replyWithError('DNS resolution failed'); - const result = await dataSource.fetch(); + const result = dataSource.fetch(); - expect(result).toEqual([]); + await expect(result).rejects.toThrow(/DNS resolution failed/); }); - test('returns empty array when the connection stays idle for too long', async () => { + test('returns appropriate error when the connection stays idle for too long', async () => { nock('https://cli.cdk.dev-tools.aws.dev') .get('/notices.json') .delayConnection(3500) @@ -242,9 +242,9 @@ describe('cli notices', () => { notices: [BASIC_NOTICE], }); - const result = await dataSource.fetch(); + const result = dataSource.fetch(); - expect(result).toEqual([]); + await expect(result).rejects.toThrow(/timed out/); }); test('returns empty array when the request takes too long to finish', async () => { @@ -255,9 +255,9 @@ describe('cli notices', () => { notices: [BASIC_NOTICE], }); - const result = await dataSource.fetch(); + const result = dataSource.fetch(); - expect(result).toEqual([]); + await expect(result).rejects.toThrow(/timed out/); }); function mockCall(statusCode: number, body: any): Promise { @@ -313,6 +313,10 @@ describe('cli notices', () => { test('retrieves data from the delegate when the file cannot be read', async () => { const debugSpy = jest.spyOn(logging, 'debug'); + if (fs.existsSync('does-not-exist.json')) { + fs.unlinkSync('does-not-exist.json'); + } + const dataSource = dataSourceWithDelegateReturning(freshData, 'does-not-exist.json'); const notices = await dataSource.fetch(); @@ -335,6 +339,20 @@ describe('cli notices', () => { expect(notices).toEqual(freshData); }); + test('error in delegate gets turned into empty result by cached source', async () => { + // GIVEN + const delegate = { + fetch: jest.fn().mockRejectedValue(new Error('fetching failed')), + }; + const dataSource = new CachedDataSource(fileName, delegate, true); + + // WHEN + const notices = await dataSource.fetch(); + + // THEN + expect(notices).toEqual([]); + }); + function dataSourceWithDelegateReturning(notices: Notice[], file: string = fileName, ignoreCache: boolean = false) { const delegate = { fetch: jest.fn(), diff --git a/packages/awslint/package.json b/packages/awslint/package.json index ac72856c34126..672db3cb61816 100644 --- a/packages/awslint/package.json +++ b/packages/awslint/package.json @@ -18,11 +18,11 @@ "awslint": "bin/awslint" }, "dependencies": { - "@jsii/spec": "^1.56.0", + "@jsii/spec": "^1.57.0", "camelcase": "^6.3.0", "chalk": "^4", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.56.0", + "jsii-reflect": "^1.57.0", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/scripts/find-latest-release.js b/scripts/find-latest-release.js index dc1cd715d5f82..bb51ccc539734 100644 --- a/scripts/find-latest-release.js +++ b/scripts/find-latest-release.js @@ -30,7 +30,6 @@ async function main(matchRange) { // 60 requests/hour, so we need to sleep for a full minute to get any kind of response const sleepTime = Math.floor(Math.random() * 60 * Math.pow(2, attempt)); - console.log('Sleeping for', sleepTime, 'seconds'); await sleep(sleepTime * 1000); continue; } diff --git a/tools/@aws-cdk/cdk-build-tools/package.json b/tools/@aws-cdk/cdk-build-tools/package.json index 8809726cec145..ccb9398d56ff5 100644 --- a/tools/@aws-cdk/cdk-build-tools/package.json +++ b/tools/@aws-cdk/cdk-build-tools/package.json @@ -57,9 +57,9 @@ "fs-extra": "^9.1.0", "jest": "^27.5.1", "jest-junit": "^13.1.0", - "jsii": "^1.56.0", - "jsii-pacmak": "^1.56.0", - "jsii-reflect": "^1.56.0", + "jsii": "^1.57.0", + "jsii-pacmak": "^1.57.0", + "jsii-reflect": "^1.57.0", "markdownlint-cli": "^0.31.1", "nyc": "^15.1.0", "semver": "^7.3.6", diff --git a/yarn.lock b/yarn.lock index 9e4904f726a87..558a1a9af40eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -622,6 +622,14 @@ chalk "^4.1.2" semver "^7.3.5" +"@jsii/check-node@1.57.0": + version "1.57.0" + resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.57.0.tgz#c41e28f47e6210e0ec127349a73aa871d6227943" + integrity sha512-7c4D07I8xefmafKtiXQkarpRsSRufpach4lcM/mepWhBqVGxFjzGF7S4vRT7MAQiEKEpGhnIfpWFhmBgUtP6bw== + dependencies: + chalk "^4.1.2" + semver "^7.3.5" + "@jsii/spec@1.56.0", "@jsii/spec@^1.54.0", "@jsii/spec@^1.56.0": version "1.56.0" resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.56.0.tgz#c7012ddbc945df0748319d664e3680265168fa59" @@ -629,6 +637,13 @@ dependencies: jsonschema "^1.4.0" +"@jsii/spec@1.57.0", "@jsii/spec@^1.57.0": + version "1.57.0" + resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.57.0.tgz#f22cf639fed22e1fb2cc39ae818e2c0eecf999bd" + integrity sha512-Pt1wWIVeBN7UHJ9Flj676hNA3sNN06YSbErUd3loLgCUjRDOUzp2QysaRQK2Zsf2DBIjwLq048btoWkjPsTFJQ== + dependencies: + jsonschema "^1.4.0" + "@lerna/add@4.0.0": version "4.0.0" resolved "https://registry.npmjs.org/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f" @@ -3196,6 +3211,15 @@ codemaker@^1.56.0: decamelize "^5.0.1" fs-extra "^9.1.0" +codemaker@^1.57.0: + version "1.57.0" + resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.57.0.tgz#a68d7c71302f62746c05a7c94e6e63dfd5f1fdc2" + integrity sha512-M2/8sfQxQ9IkN2tsbOIwHn9U6KqG/mCRsg14muK8HIZH5oqjgc8Ucfqboqlrye8+9kyuQLieIhABiRV2gqeEDg== + dependencies: + camelcase "^6.3.0" + decamelize "^5.0.1" + fs-extra "^9.1.0" + collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -6732,39 +6756,39 @@ jsesc@^2.5.1: resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsii-diff@^1.56.0: - version "1.56.0" - resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.56.0.tgz#161c0bcfb99aea43e423d52d69ca9219b2a28b5c" - integrity sha512-ivw3GyiFxzJaLYBinuJSoxpLsVidrmY5FmwU0VtdXKT1KounLpnywHkx82VRmrDAfsl8Afoi8yrlSNqPpj0ylA== +jsii-diff@^1.57.0: + version "1.57.0" + resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.57.0.tgz#5bcb1698c3ad165474bfdf3e359621099aa4471b" + integrity sha512-rVqm5HQQJhfW8u2gVVo8wSApu+gdCx0pkD0YiHKUyCebB/3OTBJx/mimEoDfntYMK0plKoBzFPjY7gp9sCBE7A== dependencies: - "@jsii/check-node" "1.56.0" - "@jsii/spec" "^1.56.0" + "@jsii/check-node" "1.57.0" + "@jsii/spec" "^1.57.0" fs-extra "^9.1.0" - jsii-reflect "^1.56.0" + jsii-reflect "^1.57.0" log4js "^6.4.4" typescript "~3.9.10" yargs "^16.2.0" -jsii-pacmak@^1.56.0: - version "1.56.0" - resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.56.0.tgz#2cc75cfb08e6cfd46a535a1589c3a7d8a6ae13d7" - integrity sha512-7Sk+LHZ98G6G82FZdaUbZU38N/ZSve2kjp0pInkjw3TQUGfO9IdI7EhH5eEUeGO2maTzxIcgn8ZElASUsXk8gA== +jsii-pacmak@^1.57.0: + version "1.57.0" + resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.57.0.tgz#9d8636f64991ab740658b96df393590c7156b8dd" + integrity sha512-yUIuhVqovNEE8Oq0BKVauiv1/5AT1JguhsuKkB4AWTxdkXHxOkv4eVA/w4jiCBaGjbwVg7BjgWR8zuMuNCU98w== dependencies: - "@jsii/check-node" "1.56.0" - "@jsii/spec" "^1.56.0" + "@jsii/check-node" "1.57.0" + "@jsii/spec" "^1.57.0" clone "^2.1.2" - codemaker "^1.56.0" + codemaker "^1.57.0" commonmark "^0.30.0" escape-string-regexp "^4.0.0" fs-extra "^9.1.0" - jsii-reflect "^1.56.0" - jsii-rosetta "^1.56.0" + jsii-reflect "^1.57.0" + jsii-rosetta "^1.57.0" semver "^7.3.5" spdx-license-list "^6.5.0" xmlbuilder "^15.1.1" yargs "^16.2.0" -jsii-reflect@^1.54.0, jsii-reflect@^1.56.0: +jsii-reflect@^1.54.0: version "1.56.0" resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.56.0.tgz#23d78f9c81ba048be780a96eeafea4775ee721e2" integrity sha512-OGpINABFiiwnvndlLjJU3mZSaXwzyuLyIkKidAV24PLS5XkFZYKXlA+Qz6HA8AWdDNJVCW0S9AbAr3Ab4J6QDQ== @@ -6776,7 +6800,19 @@ jsii-reflect@^1.54.0, jsii-reflect@^1.56.0: oo-ascii-tree "^1.56.0" yargs "^16.2.0" -jsii-rosetta@^1.54.0, jsii-rosetta@^1.56.0: +jsii-reflect@^1.57.0: + version "1.57.0" + resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.57.0.tgz#4eb4b05664f5c71da3ecd4b05544e95436a8c4f4" + integrity sha512-aSmEAxxBjyrdTnzzFx1O0Q+6D8pi1jwIB7LTvdlPQMy8GuLqO8K3nAiZPjfnNpzKBM65iJKFY3I5XNjJf2iIfA== + dependencies: + "@jsii/check-node" "1.57.0" + "@jsii/spec" "^1.57.0" + chalk "^4" + fs-extra "^9.1.0" + oo-ascii-tree "^1.57.0" + yargs "^16.2.0" + +jsii-rosetta@^1.54.0: version "1.56.0" resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.56.0.tgz#3192638adafdee2e7bd6b5e83d0b77468a04d13d" integrity sha512-aeFHXnO9hQXirgLjYqYMoAdvBGnpLOEhRVe4w7RuYjaqwsIPof4xIfSj2YvNQ9ZAWalYpg1Tm8kiLeWEyEeX6w== @@ -6795,7 +6831,26 @@ jsii-rosetta@^1.54.0, jsii-rosetta@^1.56.0: workerpool "^6.2.0" yargs "^16.2.0" -jsii@1.56.0, jsii@^1.54.0, jsii@^1.56.0: +jsii-rosetta@^1.57.0: + version "1.57.0" + resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.57.0.tgz#0ffa9b7ec30cdc480cf4b5c085b29c2f62524b28" + integrity sha512-ey0tBYk6or4CGkgiP+Ox+9Qxf2HD0KZnqr2dN4hpu8aiyZRJYinktaL/ryARM89EqhfpHKrgHAPD11RPDhFo9w== + dependencies: + "@jsii/check-node" "1.57.0" + "@jsii/spec" "1.57.0" + "@xmldom/xmldom" "^0.8.2" + commonmark "^0.30.0" + fast-glob "^3.2.11" + fs-extra "^9.1.0" + jsii "1.57.0" + semver "^7.3.5" + semver-intersect "^1.4.0" + sort-json "^2.0.1" + typescript "~3.9.10" + workerpool "^6.2.0" + yargs "^16.2.0" + +jsii@1.56.0, jsii@^1.54.0: version "1.56.0" resolved "https://registry.npmjs.org/jsii/-/jsii-1.56.0.tgz#22de00f37595fc0412e698d01adc9076c587addf" integrity sha512-G1etNH8JRSfSlgicTBYsi/yVUxxreMnWYwAtXN6BH/sIiv5o6gFnYkumF2x+OTqmQAkKj1NxSssn5icvOrONzA== @@ -6814,6 +6869,25 @@ jsii@1.56.0, jsii@^1.54.0, jsii@^1.56.0: typescript "~3.9.10" yargs "^16.2.0" +jsii@1.57.0, jsii@^1.57.0: + version "1.57.0" + resolved "https://registry.npmjs.org/jsii/-/jsii-1.57.0.tgz#58bf3644065f805b4693f1691bcfb8698aa67507" + integrity sha512-r9U1+vAfYlKgJ4FnBmf8Fj/VP+ngx/uSi3FxH9BL2KrCS0PBcHml5YXsH9pBGfCSrDQvOxULlONnw+RqEbI1Lw== + dependencies: + "@jsii/check-node" "1.57.0" + "@jsii/spec" "^1.57.0" + case "^1.6.3" + chalk "^4" + deep-equal "^2.0.5" + fs-extra "^9.1.0" + log4js "^6.4.4" + semver "^7.3.5" + semver-intersect "^1.4.0" + sort-json "^2.0.1" + spdx-license-list "^6.5.0" + typescript "~3.9.10" + yargs "^16.2.0" + json-buffer@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -8341,6 +8415,11 @@ oo-ascii-tree@^1.56.0: resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.56.0.tgz#be7313106598e33b6159a48547eba70140286ae5" integrity sha512-tPOSOEjN1uq2NktoBU2KExOU9lVghkpg+tDLWMtnqSSmX+lnDJIYIFpa/HqXwyiAXoHpcKh+bcmTPMZagLNIZA== +oo-ascii-tree@^1.57.0: + version "1.57.0" + resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.57.0.tgz#7948791e43699130ae6cee8a750abac784c8da7c" + integrity sha512-f0YTN8p0IN/X05R3N8yfENqCx7seBtDdVdJa8yQc2kx/v5OuEz/femhwEerxSsVXlb/OKjo2u4QAXTkjWjbPHA== + open@^7.4.2: version "7.4.2" resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321"