From 52b9d3fa15df88ca3db1a0fd6d249f86aaf4d567 Mon Sep 17 00:00:00 2001 From: amazon-meaisiah Date: Wed, 3 Jun 2020 09:29:20 -0700 Subject: [PATCH 1/3] Clarify deployer config documentation --- BUILDING.md | 1 + dev-portal/example-deployer.config.js | 3 ++ dev-portal/example-dev-deployer.config.js | 38 ++--------------------- 3 files changed, 7 insertions(+), 35 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index f93605aa0..8631f337e 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -21,6 +21,7 @@ Note: this is for advanced users who want to modify the developer portal code it - If you're just building this to release it locally and a fresh environment isn't needed, you can just copy `/dev-portal/example-deployer.config.js` and fill it in locally. - If you need to develop in a fresh environment (say, for contributing back to the developer portal or for some more advanced customization), you can customize this further, and you may find `/dev-portal/example-dev-deployer.config.js` as an easier starting point. The fields are the same, just you can switch between deployments far more easily. - You can put this elsewhere and pass `DEPLOYER_CONFIG=/path/to/deployer.config.js` as an environment variable each time you run a task that uses it, in case you would prefer to manage it outside the repo. + - Please refer to [the example non-development config file](./dev-portal/example-deployer.config.js) for explanation of all the various options. 5. Run `node run install release`. This will install everything (the `install`), build the static assets for the first time (the `build` part of `release`), and deploy them (the `deploy` part of `release`). diff --git a/dev-portal/example-deployer.config.js b/dev-portal/example-deployer.config.js index 8e92108b0..6064f6b35 100644 --- a/dev-portal/example-deployer.config.js +++ b/dev-portal/example-deployer.config.js @@ -4,6 +4,9 @@ // org name, or some other unique identifier. // // The resulting bucket names must be globally unique. +// +// Note: these configuration options do not always correlate to SAM template parameters, and many +// that do feature different casing and/or different names entirely. module.exports = { // Required, bucket must be pre-made buildAssetsBucket: 'YOUR_LAMBDA_ARTIFACTS_BUCKET_NAME', diff --git a/dev-portal/example-dev-deployer.config.js b/dev-portal/example-dev-deployer.config.js index 9344e08b7..aca00f898 100644 --- a/dev-portal/example-dev-deployer.config.js +++ b/dev-portal/example-dev-deployer.config.js @@ -1,3 +1,6 @@ +// See `example-deployer.config.js` in this directory for more detailed documentation of each of +// the relevant options. +// // It's recommended you track your live deployments here. You can change this // any time you want to do a fresh deployment. // Live: 0 @@ -35,39 +38,4 @@ module.exports = { // you're actively developing on the developer portal itself locally, you should generally leave // it unset as it disables most protections, including CORS. // developmentMode: false, -} - -module.exports = { - // required; bucket must be pre-made - buildAssetsBucket: `YOUR_LAMBDA_ARTIFACTS_BUCKET_NAME`, - - // required, created by stack - stackName: `YOUR_NAMESPACE-dev-portal${n}`, - siteAssetsBucket: `YOUR_NAMESPACE-dev-portal-static-assets${n}`, - apiAssetsBucket: `YOUR_NAMESPACE-dev-portal-artifacts${n}`, - - // optional, created by stack - cognitoDomainName: `YOUR_NAMESPACE-auth${n}`, - customersTableName: `DevPortalCustomers${n}`, - preLoginAccountsTableName: `DevPortalPreLoginAccounts${n}`, - feedbackTableName: `DevPortalFeedback${n}`, - - // required; Turns on cognito hosted sign in / sign up UI - cognitoDomainName: `CUSTOM_PREFIX-auth`, - - // optional, created by stack - // It's recommended you set this, though, for easier identification later. - cognitoIdentityPoolName: `DevPortalIdentityPool${n}`, - - // AWS SAM CLI profile option: optional specific profile from your AWS credential file. Not used - // by default. - // awsSamCliProfile: 'my-profile', - - // Always nuke and rebuild - staticAssetRebuildMode: 'overwrite-content', - - // Set this to `true` if you want to enable development mode. It's `false` by default, and unless - // you're actively developing on the developer portal itself locally, you should generally leave - // it unset as it disables most CORS protections. - developmentMode: true } \ No newline at end of file From 136b8add62df246658d3c9425177faddeb1831b8 Mon Sep 17 00:00:00 2001 From: amazon-meaisiah Date: Thu, 4 Jun 2020 18:14:54 -0700 Subject: [PATCH 2/3] Fix several docs omissions and inconsistencies Other changes: - Moved all the deployer config docs from the example file to BUILDING.md for easier reading and formatting. - Removed from the user-visible docs any trace of the `'request'` mode for account registration, as it's not currently supported and the existing implementation is untested and critically broken. It's just commented out, so anyone who views the source code can still see traces of it (and infer that it's a likely WIP feature). - Revised the deployment scripts so I could better understand the numerous points of configuration. (It helped me write the rest of this patch.) --- BUILDING.md | 140 ++++++++++++++++++++-- cloudformation/template.yaml | 5 +- dev-portal/example-deployer.config.js | 60 ++++------ dev-portal/example-dev-deployer.config.js | 43 +++---- scripts/internal/deploy-template.js | 71 ++++++----- scripts/internal/get-deployer-config.js | 67 ++++++++++- scripts/internal/write-config.js | 4 +- scripts/run.js | 11 +- 8 files changed, 275 insertions(+), 126 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 8631f337e..d839b7b16 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1,6 +1,6 @@ # Development guide -Note: this is for advanced users who want to modify the developer portal code itself. +*Note: this is for advanced users who want to modify the developer portal itself.* ## Getting Started @@ -16,20 +16,142 @@ Note: this is for advanced users who want to modify the developer portal code it 3. Create a private S3 bucket for putting zipped lambda functions and zipped templates in. Note the bucket name for the next step. (This can be the same one you used during in the initial deployment.) -4. Create a `/dev-portal/deployer.config.js` file. We recommend using the same values you used during the initial deployment. +4. Create a `dev-portal/deployer.config.js` file. We recommend using the same values you used during the initial deployment. - - If you're just building this to release it locally and a fresh environment isn't needed, you can just copy `/dev-portal/example-deployer.config.js` and fill it in locally. - - If you need to develop in a fresh environment (say, for contributing back to the developer portal or for some more advanced customization), you can customize this further, and you may find `/dev-portal/example-dev-deployer.config.js` as an easier starting point. The fields are the same, just you can switch between deployments far more easily. - - You can put this elsewhere and pass `DEPLOYER_CONFIG=/path/to/deployer.config.js` as an environment variable each time you run a task that uses it, in case you would prefer to manage it outside the repo. - - Please refer to [the example non-development config file](./dev-portal/example-deployer.config.js) for explanation of all the various options. + - If you're just building this to release it locally and a fresh environment isn't needed, you can just copy [`dev-portal/example-deployer.config.js`](dev-portal/example-deployer.config.js) and fill it in locally. + - If you need to develop in a fresh environment (say, for contributing back to the developer portal or for some more advanced customization), you can customize this further, and you may find [`dev-portal/example-dev-deployer.config.js`](dev-portal/example-dev-deployer.config.js) as an easier starting point. The fields are the same, just you can switch between deployments far more easily. + - You can put this elsewhere and pass `DEPLOYER_CONFIG=/path/to/deployer.config.js` as an environment variable each time you run a task that uses it (like `release`), in case you would prefer to manage it outside the repo. + - Please see [here](#deployer-configuration) for explanation of all the various options available. 5. Run `node run install release`. This will install everything (the `install`), build the static assets for the first time (the `build` part of `release`), and deploy them (the `deploy` part of `release`). -6. Run `node run start` to start the local development server at `http://localhost:3000`. This also fetches the config from the live website so everything's hooked up correctly. (You can do both this and the previous step in one go via `node run install release start`.) +6. Run `node run start` to start the local development server at [`http://localhost:3000`](http://localhost:3000). This also fetches the config from the live website so everything's hooked up correctly. (You can do both this and the previous step in one go via `node run install release start`.) 7. If you created the stack for the first time (or changed the `n` from the development `deployer.config.js` example), you'll need to register a new admin account. In the dev portal, register it as an ordinary user, then go into the Cognito user pool generated for it (you can find it by going to the deployed stack in CloudFormation and searching for "CognitoUserPool" in the "Logical ID" column), search for the account in question (by email is easiest), open it, and add it to the admin group (look for `${STACK_NAME}AdminsGroup`). -8. Make changes locally, test them at `http://localhost:3000`, and, when satisfied, run `node run release` to build and upload the changes to your cloud dev portal. +8. Make changes locally, test them at [`http://localhost:3000`](http://localhost:3000), and, when satisfied, run `node run release` to build and upload the changes to your cloud dev portal. + +## Deployer configuration + +The deployer configuration file is used to control the SAM deployment scripts. There are several various configuration parameters, most of which correspond to SAM template parameters, but some that affect behavior outside of that as well. + +Required paramters are explicitly denoted as such, and all other parameters are optional. + +### `awsSamCliProfile: string` + +*Default: `"default"`* + +This is the AWS CLI profile to use for the deployment. If you have multiple profiles, it's highly recommended that you change this accordingly. + +### `buildAssetsBucket: string` (Required) + +This S3 bucket is used to hold all the build artifacts. Unlike everything else here, it must be pre-made, and as an S3 bucket, the name must be globally unique. + +### `stackName: string` (Required) + +This is the name of the CloudFormation stack to create and deploy. As a CloudFormation stack name, it must be unique to your account. + +### `siteAssetsBucket: string` (Required) + +This S3 bucket holds the site's static assets to serve from the generated CloudFront distribution. As an S3 bucket, the name must be globally unique. + +### `customDomainName: string` + +The domain name to serve the site from. If omitted, CloudFront generates a random subdomain for you and provides that. + +### `customDomainNameAcmCertArn: string` + +The ARN of the ACM certificate corresponding to the custom domain given by `customDomainName` above. This has no effect unless `customDomainName` is configured. + +### `useRoute53Nameservers: boolean` + +*Default: `false`* + +Whether to use Route53's nameservers for your custom domain. If omitted, you will have to provide your own nameservers. This has no effect unless `customDomainName` is configured. + +### `cognitoDomainName: string` (Required) + +This is the Cognito user pool domain prefix to use for the sign up/sign in UI. If you also provide `cognitoDomainAcmCertArn`, this is a subdomain of the certificate's associated domain and it must be unique to all subdomains of that domain. If not, this is just a subdomain of Cognito's domain and it must be globally unique. + +### `cognitoDomainAcmCertArn: string` + +The ARN of the ACM certificate corresponding to the custom domain to use to host the Cognito sign up/sign in UI. This may be omitted, in which it just uses Cognito's domain for the region it's deploied in. + +### `cognitoIdentityPoolName: string` + +*Default: `'DevPortalIdentityPool'`* + +The name of the generated Cognito identity pool. + +### `customersTableName: string` + +*Default: `'DevPortalCustomers'`* + +The name of the customers DynamoDB table. + +### `preLoginAccountsTableName: string` + +*Default: `'DevPortalPreLoginAccounts'`* + +The name of the pre-login accounts DynamoDB table. + +### `feedbackTableName: string` + +*Default: `'DevPortalFeedback'`* + +The name of the feedback DynamoDB table. + +### `marketplaceSubscriptionTopic: string` + +*Default: `'DevPortalMarketplaceSubscriptionTopic'`* + +The marketplace SNS topic suffix for subscription/unsubscription events. + +### `accountRegistrationMode: string` + +*Default: `'open'`* + +This determines who can register for an account. + +- `'open'` - Any user may register for an account. + +- In `'invite'` mode, users cannot register or request an account; instead, an Admin must send an invite for the user to accept. + +### `feedbackEmail: string` + +The email address where user submitted feedback notifications get sent. This may be omitted, in which feedback submission is disabled. + +### `staticAssetRebuildMode: string` + +*Default: `''`* + +Set this to `'overwrite-content'` if you want to reset your custom content (like in `custom-content/content-fragments/`) within the static assets bucket back to the defaults generated at build time, or to `''` to retain custom content. + +### `awsSamCliProfile: string` + +*Default: `'my-profile'`* + +AWS SAM CLI profile option: optional specific profile from your AWS credential file. Not used by default. + +### `developmentMode: boolean` + +*Default: `false`* + +Set this to `true` if you want to enable development mode. It's `false` by default, and unless you're actively developing on the developer portal itself locally, you should generally leave it unset as it disables most protections, including CORS. + +### `samTemplate: string` + +*Default: `cloudformation/template.yaml` relative to the repo's root* + +Set this to the path to your SAM template. It defaults to the one in the repo, and you generally shouldn't need to change it. + +### `packageConfig: string` + +*Default: `cloudformation/packaged.yaml` relative to the repo's root* + +Set this to where you wish to save the packaged template to a specific location other than the reserved location in the repo. In general, you shouldn't need to configure this, but it exists for more advanced use cases. ## npm Scripts @@ -61,4 +183,4 @@ Gets the output from the CFN stack, writes a local version of the config.js file ## Notes on static assets -The static assets are only re-uploaded on deployment if the previous deployment and the current deployment were provided different `StaticAssetRebuildToken` parameters. The `node run deploy` script automatically creates a unique `StaticAssetRebuildToken` for you based on the current date. +The static assets are only re-uploaded on deployment if the previous deployment and the current deployment were provided different `StaticAssetRebuildToken` parameters. The `node run deploy` script automatically creates a unique `StaticAssetRebuildToken` for you based on the current date, so it updates on every deployment. diff --git a/cloudformation/template.yaml b/cloudformation/template.yaml index 6ecd6487d..bed8431ec 100644 --- a/cloudformation/template.yaml +++ b/cloudformation/template.yaml @@ -33,6 +33,8 @@ Metadata: - CustomDomainName - CustomDomainNameAcmCertArn - UseRoute53Nameservers + - CognitoDomainNameOrPrefix + - CognitoDomainAcmCertArn - Label: default: "Dev Portal Customer Feedback Configuration" @@ -143,7 +145,8 @@ Parameters: AccountRegistrationMode: Type: String - Description: Methods allowed for account registration. In 'open' mode, any user may register for an account. In 'request' mode, any user may request an account, but an Admin must approve the request in order for the account to perform any privileged actions (like subscribing to an API). In 'invite' mode, users cannot register or request an account; instead, an Admin must send an invite for the user to accept. See the documentation for details. + # Description: Methods allowed for account registration. In 'open' mode, any user may register for an account. In 'request' mode, any user may request an account, but an Admin must approve the request in order for the account to perform any privileged actions (like subscribing to an API). In 'invite' mode, users cannot register or request an account; instead, an Admin must send an invite for the user to accept. + Description: Methods allowed for account registration. In 'open' mode, any user may register for an account. In 'invite' mode, users cannot register or request an account; instead, an Admin must send an invite for the user to accept. Default: 'open' AllowedValues: - 'open' diff --git a/dev-portal/example-deployer.config.js b/dev-portal/example-deployer.config.js index 6064f6b35..473c37d00 100644 --- a/dev-portal/example-deployer.config.js +++ b/dev-portal/example-deployer.config.js @@ -1,48 +1,30 @@ -// 1. Replace your-lambda-artifacts-bucket-name with the name of the bucket you created in step 3 -// of the dev setup. -// 2. Then, replace 'custom-prefix-' in siteAssetsBucket and apiAssetsBucket with your name, your -// org name, or some other unique identifier. -// -// The resulting bucket names must be globally unique. +// Here's how you set this up: // -// Note: these configuration options do not always correlate to SAM template parameters, and many -// that do feature different casing and/or different names entirely. +// 1. Replace YOUR_LAMBDA_ARTIFACTS_BUCKET_NAME with the name of the bucket you created in step 3 of the dev setup. +// 2. Replace 'CUSTOM_PREFIX' in the properties that have it with your name, your org name, or some other unique identifier. For the S3 buckets and the Cognito user pool domain prefix, they must be globally unique. For the CloudFormation stack name, it need only be unique to all stacks deployed to your account. +// 3. Set any other optional parameters as desired. For the DynamoDB tables, their names must be unique to all DynamoDB tables within your account. +// 4. Save the file. +// +// Note: these configuration parameters are *not* the same as the SAM template parameters - the names differ and the behavior in many areas also differ. Furthermore, some SAM template parameters like `StaticAssetsRebuildToken` are handled automatically internally and cannot be configured. +// +// See the "Deployer configuration" section of `BUILDING.md` for documentation on each of the parameters. +"use strict" + module.exports = { - // Required, bucket must be pre-made + // Optional, but recommended if you have multiple active AWS CLI profiles. + // awsSamCliProfile: 'your-profile', + buildAssetsBucket: 'YOUR_LAMBDA_ARTIFACTS_BUCKET_NAME', - // Required, created by stack - stackName: 'dev-portal', + stackName: 'CUSTOM_PREFIX-dev-portal', siteAssetsBucket: 'CUSTOM_PREFIX-dev-portal-static-assets', apiAssetsBucket: 'CUSTOM_PREFIX-dev-portal-artifacts', - - // Required, turns on cognito hosted sign in/sign up UI cognitoDomainName: 'CUSTOM_PREFIX-auth', - // Optional values (uncomment and change values if you want to use them) - - // Change the name of the customers table. Useful for multiple stacks. Defaults to - // `'DevPortalCustomers'`. - // customersTableName: 'CustomPrefixDevPortalCustomers', - - // Change the name of the pre-login accounts table. Useful for multiple stacks. Defaults to - // `'DevPortalPreLoginAccounts'`. - // preLoginAccountsTableName: 'CustomPrefixDevPortalPreLoginAccounts', - - // Change the name of the pre-login accounts table. Useful for multiple stacks. Defaults to - // `'DevPortalFeedback'`. - // feedbackTableName: 'CustomPrefixDevPortalFeedback', - - // Set this to overwrite-content if you want to reset your custom content back to the defaults. - // Defaults to `''`. - // staticAssetRebuildMode: 'overwrite-content', // ONLY SET - - // AWS SAM CLI profile option: optional specific profile from your AWS credential file. Not used - // by default. - // awsSamCliProfile: 'my-profile', - - // Set this to `true` if you want to enable development mode. It's `false` by default, and unless - // you're actively developing on the developer portal itself locally, you should generally leave - // it unset as it disables most protections, including CORS. - // developmentMode: false, + // Optional, but highly encouraged if you have such a domain ready. Not all of these may apply. + // customDomainName: 'developer.domain.example', + // customDomainNameAcmCertArn: 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012', + // cognitoDomainAcmCertArn: 'arn:aws:acm:us-east-1:123456789012:certificate/98765432-9876-9876-9876-987654321098', + // useRoute53Nameservers: true, + // feedbackEmail: 'admin@domain.example', } \ No newline at end of file diff --git a/dev-portal/example-dev-deployer.config.js b/dev-portal/example-dev-deployer.config.js index aca00f898..2aa612723 100644 --- a/dev-portal/example-dev-deployer.config.js +++ b/dev-portal/example-dev-deployer.config.js @@ -1,41 +1,34 @@ -// See `example-deployer.config.js` in this directory for more detailed documentation of each of -// the relevant options. +// See `example-deployer.config.js` in this directory for setup instructions and the "Deployer +// configuration" section of `BUILDING.md` for documentation on each of the parameters. // -// It's recommended you track your live deployments here. You can change this -// any time you want to do a fresh deployment. +// It's recommended you track your live deployments here. You can change this any time you want to +// do a fresh deployment. // Live: 0 +"use strict" + const n = 0 module.exports = { - // Required, bucket must be pre-made buildAssetsBucket: 'YOUR_LAMBDA_ARTIFACTS_BUCKET_NAME', - // Required, created by stack - stackName: 'dev-portal', - siteAssetsBucket: 'CUSTOM_PREFIX-dev-portal-static-assets', - apiAssetsBucket: 'CUSTOM_PREFIX-dev-portal-artifacts', - - // Required, turns on cognito hosted sign in/sign up UI - cognitoDomainName: `YOUR_NAMESPACE-auth${n}`, - - // Optional, created by stack + // All of these are parametric over `n` so that if you need to have multiple stacks deployed + // during development or if you need to tear down a stack and don't want to wait for it to + // completely be torn down before deploying the replacement stack, you can just do it without + // much work. + stackName: `dev-portal${n}`, + siteAssetsBucket: `CUSTOM_PREFIX-dev-portal-static-assets${n}`, + apiAssetsBucket: `CUSTOM_PREFIX-dev-portal-artifacts${n}`, + cognitoDomainName: `CUSTOM_PREFIX-auth${n}`, customersTableName: `DevPortalCustomers${n}`, preLoginAccountsTableName: `DevPortalPreLoginAccounts${n}`, feedbackTableName: `DevPortalFeedback${n}`, - // optional, created by stack - // It's recommended you set this, though, for easier identification later. + // Optional, but highly recommended for easier identification. cognitoIdentityPoolName: `DevPortalIdentityPool${n}`, - // Always nuke and rebuild + // Optional, but highly recommended so you can keep the site in sync with what's in the repo. staticAssetRebuildMode: 'overwrite-content', - // AWS SAM CLI profile option: optional specific profile from your AWS credential file. Not used - // by default. - // awsSamCliProfile: 'my-profile', - - // Set this to `true` if you want to enable development mode. It's `false` by default, and unless - // you're actively developing on the developer portal itself locally, you should generally leave - // it unset as it disables most protections, including CORS. - // developmentMode: false, + // Set development mode for local use. + developmentMode: true, } \ No newline at end of file diff --git a/scripts/internal/deploy-template.js b/scripts/internal/deploy-template.js index 278f99141..ee826b096 100644 --- a/scripts/internal/deploy-template.js +++ b/scripts/internal/deploy-template.js @@ -2,45 +2,35 @@ // SPDX-License-Identifier: Apache-2.0 'use strict' -const { exec, p } = require('./util.js') -const deployerConfig = require('./get-deployer-config.js') +const { exec } = require('./util.js') module.exports = async () => { - const missing = [] + const deployerConfig = require('./get-deployer-config.js') + if (deployerConfig.error) throw deployerConfig.error - function getRequired (key) { - const value = deployerConfig[key] - if (value) return value - missing.push(key) - } - - function getOptional (key, orElse) { - return deployerConfig[key] || orElse - } - - // required inputs - const stackName = getRequired('stackName') - const buildAssetsBucket = getRequired('buildAssetsBucket') - const siteAssetsBucket = getRequired('siteAssetsBucket') - const apiAssetsBucket = getRequired('apiAssetsBucket') - const cognitoDomainName = getRequired('cognitoDomainName') - - // required (and defaulted) inputs - const samTemplate = getOptional('samTemplate', p('cloudformation/template.yaml')) - const packageConfig = getOptional('packageConfig', p('cloudformation/packaged.yaml')) - const customersTableName = getOptional('customersTableName') - const preLoginAccountsTableName = getOptional('preLoginAccountsTableName') - const feedbackTableName = getOptional('feedbackTableName') - const cognitoIdentityPoolName = getOptional('cognitoIdentityPoolName') - - // optional inputs - const staticAssetRebuildMode = getOptional('staticAssetRebuildMode', '') - const developmentMode = getOptional('developmentMode') - - // AWS SAM CLI configuration - const awsSamCliProfile = getOptional('awsSamCliProfile') - - if (missing.length) return missing + const { + stackName, + buildAssetsBucket, + siteAssetsBucket, + apiAssetsBucket, + cognitoDomainName, + samTemplate, + packageConfig, + customersTableName, + preLoginAccountsTableName, + feedbackTableName, + cognitoIdentityPoolName, + marketplaceSubscriptionTopic, + accountRegistrationMode, + feedbackEmail, + cognitoDomainAcmCertArn, + customDomainName, + customDomainNameAcmCertArn, + useRoute53Nameservers, + staticAssetRebuildMode, + developmentMode, + awsSamCliProfile + } = deployerConfig await exec('sam', [ 'package', @@ -64,7 +54,14 @@ module.exports = async () => { ...(feedbackTableName ? [`DevPortalFeedbackTableName=${feedbackTableName}`] : []), ...(cognitoIdentityPoolName ? [`CognitoIdentityPoolName=${cognitoIdentityPoolName}`] : []), ...(developmentMode ? [`LocalDevelopmentMode=${developmentMode}`] : []), - `CognitoDomainNameOrPrefix=${cognitoDomainName}`, + ...(cognitoDomainName ? [`CognitoDomainNameOrPrefix=${cognitoDomainName}`] : []), + ...(marketplaceSubscriptionTopic ? [`MarketplaceSubscriptionTopicProductCode=${marketplaceSubscriptionTopic}`] : []), + ...(accountRegistrationMode ? [`AccountRegistrationMode=${accountRegistrationMode}`] : []), + ...(feedbackEmail ? [`DevPortalAdminEmail=${feedbackEmail}`] : []), + ...(cognitoDomainAcmCertArn ? [`CognitoDomainAcmCertArn=${cognitoDomainAcmCertArn}`] : []), + ...(customDomainName ? [`CustomDomainName=${customDomainName}`] : []), + ...(customDomainNameAcmCertArn ? [`CustomDomainNameAcmCertArn=${customDomainNameAcmCertArn}`] : []), + ...(useRoute53Nameservers ? [`UseRoute53Nameservers=${useRoute53Nameservers}`] : []), '--s3-bucket', buildAssetsBucket, ...(awsSamCliProfile ? ['--profile', awsSamCliProfile] : []) ]) diff --git a/scripts/internal/get-deployer-config.js b/scripts/internal/get-deployer-config.js index bcba09648..6ac1366a2 100644 --- a/scripts/internal/get-deployer-config.js +++ b/scripts/internal/get-deployer-config.js @@ -1,11 +1,66 @@ 'use strict' +// Note: be sure to update `BUILDING.md` any time you add or remove options. + const path = require('path') +const { p } = require('./util.js') + +// Don't attempt to load anything in Travis. +if (process.env.TRAVIS) return + +const deployerConfigName = process.env.DEPLOYER_CONFIG + ? path.resolve(process.env.DEPLOYER_CONFIG) + : p('dev-portal/deployer.config.js') + +const deployerConfig = require(deployerConfigName) + +const missing = [] + +function getRequired (key) { + const value = deployerConfig[key] + if (value) return value + exports.missing.push(key) +} -if (process.env.DEPLOYER_CONFIG) { - module.exports = require(path.resolve(process.env.DEPLOYER_CONFIG)) -} else if (process.env.TRAVIS) { - // Don't attempt to load anything in Travis. -} else { - module.exports = require('../../dev-portal/deployer.config.js') +function getOptional (key, orElse) { + return deployerConfig[key] != null ? deployerConfig[key] : orElse } + +function getOptionalPath (key, orElse) { + return deployerConfig[key] != null + ? path.resolve(path.dirname(deployerConfigName), deployerConfig[key]) + : p(orElse) +} + +// required inputs +exports.stackName = getRequired('stackName') +exports.buildAssetsBucket = getRequired('buildAssetsBucket') +exports.siteAssetsBucket = getRequired('siteAssetsBucket') +exports.apiAssetsBucket = getRequired('apiAssetsBucket') +exports.cognitoDomainName = getRequired('cognitoDomainName') + +// required (and defaulted) inputs +exports.samTemplate = getOptionalPath('samTemplate', 'cloudformation/template.yaml') +exports.packageConfig = getOptionalPath('packageConfig', 'cloudformation/packaged.yaml') +exports.customersTableName = getOptional('customersTableName') +exports.preLoginAccountsTableName = getOptional('preLoginAccountsTableName') +exports.feedbackTableName = getOptional('feedbackTableName') +exports.cognitoIdentityPoolName = getOptional('cognitoIdentityPoolName') +exports.marketplaceSubscriptionTopic = getOptional('marketplaceSubscriptionTopic') +exports.accountRegistrationMode = getOptional('accountRegistrationMode') + +// optional inputs +exports.feedbackEmail = getOptional('feedbackEmail') +exports.cognitoDomainAcmCertArn = getOptional('cognitoDomainAcmCertArn') +exports.customDomainName = getOptional('customDomainName') +exports.customDomainNameAcmCertArn = getOptional('customDomainNameAcmCertArn') +exports.useRoute53Nameservers = getOptional('useRoute53Nameservers') +exports.staticAssetRebuildMode = getOptional('staticAssetRebuildMode') +exports.developmentMode = getOptional('developmentMode') + +// AWS SAM CLI configuration +exports.awsSamCliProfile = getOptional('awsSamCliProfile') + +exports.error = missing.length + ? new Error(missing.map(key => key + ' must be defined').join('\n')) + : null diff --git a/scripts/internal/write-config.js b/scripts/internal/write-config.js index 1a8de8206..1b39935b7 100644 --- a/scripts/internal/write-config.js +++ b/scripts/internal/write-config.js @@ -4,13 +4,15 @@ 'use strict' const { execPipe, p } = require('./util.js') -const deployerConfig = require('./get-deployer-config.js') module.exports = async () => { // Note: these might not necessarily be installed, so they can't be loaded globally. const fetch = require('node-fetch') const fse = require('fs-extra') + const deployerConfig = require('./get-deployer-config.js') + if (deployerConfig.error) throw deployerConfig.error + const result = await execPipe('aws', [ 'cloudformation', 'describe-stacks', '--stack-name', deployerConfig.stackName, diff --git a/scripts/run.js b/scripts/run.js index 252af095a..76b6c742f 100644 --- a/scripts/run.js +++ b/scripts/run.js @@ -11,15 +11,10 @@ const writeConfig = require('./internal/write-config.js') function runTask (task, args = []) { return run( 'npm', ['run', task, '--', ...args], - { action: '/dev-portal/ task', target: task, cwd: p('dev-portal') } + { action: 'dev-portal/ task', target: task, cwd: p('dev-portal') } ) } -async function deploy () { - const missing = await deployTemplate() - if (missing != null) throw new Error(missing.map(key => key + ' must be defined').join('\n')) -} - function printReady () { console.log() console.log(green('Process Complete! Run `node run start` to launch run the dev portal locally.')) @@ -71,13 +66,13 @@ require('./internal/execute-tasks.js')({ }, async deploy () { - await deploy() + await deployTemplate() printReady() }, async release () { await this.build() - await deploy() + await deployTemplate() await this['reset-assets']() printReady() }, From 0a508cce1414d427bb46d17dba8d693b902fbbac Mon Sep 17 00:00:00 2001 From: amazon-meaisiah Date: Thu, 4 Jun 2020 18:47:32 -0700 Subject: [PATCH 3/3] Document the test scripts --- BUILDING.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/BUILDING.md b/BUILDING.md index d839b7b16..aaec92a1d 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -10,7 +10,7 @@ - [Node](https://nodejs.org/en/download/) v12 or later - [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) - [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) - - [CloudFormation Linter](https://github.com/aws-cloudformation/cfn-python-lint) + - [CloudFormation Linter (`cfn-lint`)](https://github.com/aws-cloudformation/cfn-python-lint) 2. Clone this repo to your local drive. @@ -181,6 +181,29 @@ Synonymous with `node run build deploy reset-assets`, as that's a common operati Gets the output from the CFN stack, writes a local version of the config.js file, and starts up the local development server. +### `node run lint` + +Lint all code in the repo using ESLint and `cfn-lint`. + +### `node run test` + +Run all the unit tests. + +### `node run test --coverage=true` + +Run all the unit tests with coverage. + +### `node run test --integ=true` + +Run all the integration tests. + +## Notes on testing + +If you need to run the unit tests with a debugger, you'll need to run them manually using the relevant test runners. + +- For the unit tests in `dev-portal/`, run `npx react-scripts --inspect-brk test --runInBand --no-cache` in that directory. +- For the unit tests in `lambdas/`, run `npx -n=--inspect-brk jest --runInBand --no-cache` in that directory. + ## Notes on static assets The static assets are only re-uploaded on deployment if the previous deployment and the current deployment were provided different `StaticAssetRebuildToken` parameters. The `node run deploy` script automatically creates a unique `StaticAssetRebuildToken` for you based on the current date, so it updates on every deployment.