Skip to content

Commit 08438f9

Browse files
author
amazon-meaisiah
committed
Fix dev portal setup scripts + docs, list generated assets as binary
1 parent 051b423 commit 08438f9

16 files changed

+123
-95
lines changed

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/lambdas/static-asset-uploader/build/** binary
2+
package-lock.json binary

dev-portal/README.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
## Development guide
22

33
### Getting Started
4-
1. Navigate to the `/dev-portal/` folder, and run `npm install`
4+
1. Make sure you have the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) and the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) installed - these are required for `npm run deploy` to work.
55

6-
2. 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)
6+
2. Navigate to the `/dev-portal/` folder, and run `npm install`
77

8-
3. Create a `deployer.config.js` file inside `/dev-portal/` with the structure below. We recommend using the same values you used during the initial deployment.
8+
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)
9+
10+
4. Create a `deployer.config.js` file inside `/dev-portal/` with the structure below. We recommend using the same values you used during the initial deployment.
911
```js
1012
// replace your-lambda-artifacts-bucket-name with the name of the bucket you created in step 1
1113
// then, replace 'custom-prefix-' in siteAssetsBucket and apiAssetsBucket with your name / your org name / some unique identifier
@@ -20,13 +22,13 @@ module.exports = {
2022
siteAssetsBucket: `CUSTOM_PREFIX-dev-portal-static-assets`,
2123
apiAssetsBucket: `CUSTOM_PREFIX-dev-portal-artifacts`,
2224

25+
// required; Turns on cognito hosted sign in / sign up UI
26+
cognitoDomainName: `CUSTOM_PREFIX-auth`,
27+
2328
// optional values (uncomment and change values if you want to use them)
2429

2530
// Change the name of the customer's table. Useful for multiple stacks. Defaults to `DevPortalCustomers`
2631
// customersTableName: `DevPortalCustomers`,
27-
28-
// Turns on cognito hosted sign in / sign up UI; Defaults to `` (blank string)
29-
// cognitoDomainName: `auth-url`,
3032

3133
// Set this to overwrite-content if you want to reset your custom content back to the defaults. Defaults to ``
3234
// staticAssetRebuildMode: `overwrite-content` // ONLY SET
@@ -35,11 +37,11 @@ module.exports = {
3537
//awsSamCliProfile: "my-profile"
3638
}
3739
```
38-
4. Run `npm run release`. This will build the static assets, deploy them, and generate the `dev-portal/public/config.js` file needed for local development. Take note of the bucket names you use
40+
5. Run `npm run release`. This will build the static assets, deploy them, and generate the `dev-portal/public/config.js` file needed for local development. Take note of the bucket names you use
3941

40-
5. Run `npm run start` to start the local development server at `localhost:3000`.
42+
6. Run `npm run start` to start the local development server at `localhost:3000`.
4143

42-
6. Make changes locally, test them at `localhost:3000`, and, when satisfied, run `npm run release` to build and upload the changes to your cloud dev portal.
44+
7. Make changes locally, test them at `localhost:3000`, and, when satisfied, run `npm run release` to build and upload the changes to your cloud dev portal.
4345

4446
### npm Scripts
4547

dev-portal/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"start": "react-scripts start",
2727
"build": "react-scripts build; rm -rf ../lambdas/static-asset-uploader/build; cp -r ./build ../lambdas/static-asset-uploader",
2828
"deploy": "node ./scripts/deploy-stack.js",
29-
"write-config": "node -e 'require(\"./scripts/write-config.js\")(true)'",
29+
"write-config": "node ./scripts/write-config.js",
3030
"release": "npm run build && npm run deploy",
3131
"test": "react-scripts test",
3232
"cover": "react-scripts test --coverage",
@@ -47,4 +47,4 @@
4747
"node-fetch": "^2.3.0",
4848
"react-scripts": "^3.0.1"
4949
}
50-
}
50+
}

dev-portal/scripts/deploy-stack.js

+54-30
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,72 @@
11
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
const { execute, r } = require('./utils.js')
4+
const { execute, r, red, green } = require('./utils.js')
55

66
const deployerConfig = require('../deployer.config.js')
77
const writeConfig = require('./write-config.js')
88

9+
const errors = []
10+
11+
function getRequired(key) {
12+
const value = deployerConfig[key]
13+
if (value) return value
14+
errors.push(key + ' must be defined')
15+
}
16+
17+
function getOptional(key, orElse) {
18+
return deployerConfig[key] || orElse
19+
}
20+
921
// required inputs
10-
const stackName = deployerConfig.stackName
11-
const buildAssetsBucket = deployerConfig.buildAssetsBucket
12-
const siteAssetsBucket = deployerConfig.siteAssetsBucket
13-
const apiAssetsBucket = deployerConfig.apiAssetsBucket
22+
const stackName = getRequired('stackName')
23+
const buildAssetsBucket = getRequired('buildAssetsBucket')
24+
const siteAssetsBucket = getRequired('siteAssetsBucket')
25+
const apiAssetsBucket = getRequired('apiAssetsBucket')
26+
const cognitoDomainName = getRequired('cognitoDomainName')
1427

1528
// required (and defaulted) inputs
16-
const samTemplate = deployerConfig.samTemplate || r(`../../cloudformation/template.yaml`)
17-
const packageConfig = deployerConfig.packageConfig || r(`../../cloudformation/packaged.yaml`)
18-
const customersTableName = deployerConfig.customersTableName || 'DevPortalCustomers'
29+
const samTemplate = getOptional('samTemplate', r(`../../cloudformation/template.yaml`))
30+
const packageConfig = getOptional('packageConfig', r(`../../cloudformation/packaged.yaml`))
31+
const customersTableName = getOptional('customersTableName', 'DevPortalCustomers')
1932

2033
// optional inputs
21-
const cognitoDomainName = deployerConfig.cognitoDomainName || ''
22-
const staticAssetRebuildMode = deployerConfig.staticAssetRebuildMode || ''
34+
const staticAssetRebuildMode = getOptional('staticAssetRebuildMode', '')
2335

2436
// AWS SAM CLI configuration
25-
const awsSamCliProfile = deployerConfig.awsSamCliProfile;
26-
const profileOption = awsSamCliProfile ? `--profile ${awsSamCliProfile}` : ''
27-
28-
function main() {
29-
Promise.resolve()
30-
.then(() => execute(`sam package --template-file ${samTemplate} --output-template-file ${packageConfig} --s3-bucket ${buildAssetsBucket} ${profileOption}`, true))
31-
.then(() => execute(`sam deploy --template-file ${packageConfig} --stack-name ${stackName} --capabilities CAPABILITY_NAMED_IAM --parameter-overrides StaticAssetRebuildToken="${Date.now()}" StaticAssetRebuildMode="${staticAssetRebuildMode}" DevPortalSiteS3BucketName="${siteAssetsBucket}" ArtifactsS3BucketName="${apiAssetsBucket}" DevPortalCustomersTableName="${customersTableName}" CognitoDomainNameOrPrefix="${cognitoDomainName}" --s3-bucket ${buildAssetsBucket} ${profileOption}`, true))
32-
.then(() => writeConfig(true))
33-
.then(() => console.log('\n' + 'Process Complete! Run `npm run start` to launch run the dev portal locally.\n'.green()))
34-
.catch(err => {
35-
console.log(("" + err).red())
36-
})
37+
const awsSamCliProfile = getOptional('awsSamCliProfile')
38+
39+
async function main() {
40+
execute('sam', [
41+
'package',
42+
'--template-file', samTemplate,
43+
'--output-template-file', packageConfig,
44+
'--s3-bucket', buildAssetsBucket,
45+
...(awsSamCliProfile ? ['--profile', awsSamCliProfile] : [])
46+
])
47+
execute('sam', [
48+
'deploy',
49+
'--template-file', packageConfig,
50+
'--stack-name', stackName,
51+
'--capabilities', 'CAPABILITY_NAMED_IAM',
52+
'--parameter-overrides',
53+
`StaticAssetRebuildToken=${Date.now()}`,
54+
...(staticAssetRebuildMode ? [`StaticAssetRebuildMode=${staticAssetRebuildMode}`] : []),
55+
`DevPortalSiteS3BucketName=${siteAssetsBucket}`,
56+
`ArtifactsS3BucketName=${apiAssetsBucket}`,
57+
`DevPortalCustomersTableName=${customersTableName}`,
58+
`CognitoDomainNameOrPrefix=${cognitoDomainName}`,
59+
'--s3-bucket', buildAssetsBucket,
60+
...(awsSamCliProfile ? ['--profile', awsSamCliProfile] : [])
61+
])
62+
await writeConfig()
63+
console.log()
64+
console.log(green('Process Complete! Run `npm run start` to launch run the dev portal locally.'))
65+
console.log()
3766
}
3867

39-
if (samTemplate && packageConfig && stackName && buildAssetsBucket && siteAssetsBucket && apiAssetsBucket && customersTableName) {
40-
main()
68+
if (errors.length) {
69+
for (const error of errors) console.error(red(error))
4170
} else {
42-
!samTemplate && console.log('samTemplate must be defined')
43-
!packageConfig && console.log('packageConfig must be defined')
44-
!stackName && console.log('stackName must be defined')
45-
!buildAssetsBucket && console.log('buildAssetsBucket must be defined')
46-
!siteAssetsBucket && console.log('siteAssetsBucket must be defined')
47-
!apiAssetsBucket && console.log('apiAssetsBucket must be defined')
71+
main().catch(err => console.error(red(err)))
4872
}

dev-portal/scripts/utils.js

+13-16
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
11
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
const util = require('util');
54
const { relative, resolve } = require('path')
6-
const exec = util.promisify(require('child_process').exec);
5+
const execFile = require('child_process').execFileSync
76

8-
function execute(cmd, swallowOutput) {
9-
console.log(('[ run cmd ] ' + cmd).blue())
10-
return exec(cmd).then(result => {
11-
!swallowOutput && result.stdout && console.log(result.stdout)
12-
!swallowOutput && result.stderr && console.log(result.stderr.yellow())
13-
return result
14-
})
7+
function execute(cmd, args = []) {
8+
console.log(blue('[ run cmd ] ' + [cmd, ...args].join(' ')))
9+
return execFile(cmd, args, { stdio: 'pipe' })
1510
}
1611

1712
const r = (path) => relative(process.cwd(), resolve(__dirname, path)) || '.'
1813

19-
const setToColor = (color) => function() { return color + this + "\x1b[0m" }
20-
21-
String.prototype.red = setToColor("\x1b[31m") // eslint-disable-line
22-
String.prototype.blue = setToColor("\x1b[34m") // eslint-disable-line
23-
String.prototype.green = setToColor("\x1b[32m") // eslint-disable-line
24-
String.prototype.yellow = setToColor("\x1b[33m") // eslint-disable-line
14+
const red = (text) => { return "\x1b[31m" + text + "\x1b[0m" }
15+
const blue = (text) => { return "\x1b[34m" + text + "\x1b[0m" }
16+
const green = (text) => { return "\x1b[32m" + text + "\x1b[0m" }
17+
const yellow = (text) => { return "\x1b[33m" + text + "\x1b[0m" }
2518

2619
module.exports = {
2720
execute,
28-
r
21+
r,
22+
red,
23+
blue,
24+
green,
25+
yellow
2926
}

dev-portal/scripts/write-config.js

+21-18
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
const util = require('util');
54
const fetch = require('node-fetch')
6-
const writeFile = util.promisify(require('fs').writeFile)
5+
const writeFile = require('fs').writeFileSync
76

8-
const { execute, r } = require('./utils.js')
7+
const { execute, r, red } = require('./utils.js')
98

10-
const buildConfig = require('../deployer.config.js')
11-
const stackName = buildConfig.stackName
9+
const deployerConfig = require('../deployer.config.js')
10+
const stackName = deployerConfig.stackName
1211

1312
// AWS SAM CLI configuration
14-
const awsSamCliProfile = buildConfig.awsSamCliProfile;
15-
const profileOption = awsSamCliProfile ? `--profile ${awsSamCliProfile}` : ''
13+
const awsSamCliProfile = deployerConfig.awsSamCliProfile
1614

17-
function writeConfig (swallowOutput) {
18-
return execute(`aws cloudformation describe-stacks --stack-name ${stackName} ${profileOption}`, swallowOutput)
19-
.then((result) => {
20-
const websiteUrl = (JSON.parse(result.stdout).Stacks[0].Outputs)
21-
.find(output => output.OutputKey === "WebsiteURL").OutputValue
22-
23-
return fetch(`${websiteUrl}/config.js`).then(response => response.text())
24-
})
25-
.then(output => writeFile(r(`../public/config.js`), output))
26-
.catch(console.error)
15+
async function writeConfig () {
16+
const result = execute('aws', [
17+
'cloudformation', 'describe-stacks',
18+
'--stack-name', stackName,
19+
...(awsSamCliProfile ? ['--profile', awsSamCliProfile] : [])
20+
])
21+
const websiteUrl = JSON.parse(result.toString('utf-8')).Stacks[0].Outputs
22+
.find(output => output.OutputKey === "WebsiteURL").OutputValue
23+
const response = await fetch(`${websiteUrl}/config.js`)
24+
const output = await response.text()
25+
writeFile(r(`../public/config.js`), output, 'utf-8')
2726
}
2827

29-
module.exports = writeConfig
28+
module.exports = writeConfig
29+
30+
if (require.main === module) {
31+
writeConfig().catch(err => console.error(red(err)))
32+
}

lambdas/static-asset-uploader/build/asset-manifest.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"files": {
33
"main.css": "/static/css/main.4ae54ac6.chunk.css",
4-
"main.js": "/static/js/main.7266b749.chunk.js",
5-
"main.js.map": "/static/js/main.7266b749.chunk.js.map",
4+
"main.js": "/static/js/main.d8afcf50.chunk.js",
5+
"main.js.map": "/static/js/main.d8afcf50.chunk.js.map",
66
"runtime~main.js": "/static/js/runtime~main.a8a9905a.js",
77
"runtime~main.js.map": "/static/js/runtime~main.a8a9905a.js.map",
88
"static/css/2.1eb883ec.chunk.css": "/static/css/2.1eb883ec.chunk.css",
9-
"static/js/2.a41b16cf.chunk.js": "/static/js/2.a41b16cf.chunk.js",
10-
"static/js/2.a41b16cf.chunk.js.map": "/static/js/2.a41b16cf.chunk.js.map",
9+
"static/js/2.73aa822c.chunk.js": "/static/js/2.73aa822c.chunk.js",
10+
"static/js/2.73aa822c.chunk.js.map": "/static/js/2.73aa822c.chunk.js.map",
1111
"index.html": "/index.html",
12-
"precache-manifest.a34f6f07da0e4c9969330f1c0db2bbca.js": "/precache-manifest.a34f6f07da0e4c9969330f1c0db2bbca.js",
12+
"precache-manifest.ec275c1f0e82d91d12e8e0176d1955ad.js": "/precache-manifest.ec275c1f0e82d91d12e8e0176d1955ad.js",
1313
"service-worker.js": "/service-worker.js",
1414
"static/css/2.1eb883ec.chunk.css.map": "/static/css/2.1eb883ec.chunk.css.map",
1515
"static/css/main.4ae54ac6.chunk.css.map": "/static/css/main.4ae54ac6.chunk.css.map",
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<!doctype html><html lang="en"><head><meta charset="utf-8"><link rel="shortcut icon" href="/custom-content/favicon.ico"><script type="text/javascript" src="/config.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/axios/dist/axios.standalone.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/rollups/hmac-sha256.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/rollups/sha256.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/components/hmac.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/components/enc-base64.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/url-template/url-template.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/sigV4Client.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/apiGatewayClient.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/simpleHttpClient.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/utils.js"></script><script type="text/javascript" src="/apigateway-js-sdk/apigClient.js"></script><link rel="stylesheet" href="/custom-content/styles.css"><title>Developer Portal</title><link href="/static/css/2.1eb883ec.chunk.css" rel="stylesheet"><link href="/static/css/main.4ae54ac6.chunk.css" rel="stylesheet"></head><body><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={1:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/2.a41b16cf.chunk.js"></script><script src="/static/js/main.7266b749.chunk.js"></script></body></html>
1+
<!doctype html><html lang="en"><head><meta charset="utf-8"><link rel="shortcut icon" href="/custom-content/favicon.ico"><script type="text/javascript" src="/config.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/axios/dist/axios.standalone.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/rollups/hmac-sha256.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/rollups/sha256.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/components/hmac.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/CryptoJS/components/enc-base64.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/url-template/url-template.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/sigV4Client.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/apiGatewayClient.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/simpleHttpClient.js"></script><script type="text/javascript" src="/apigateway-js-sdk/lib/apiGatewayCore/utils.js"></script><script type="text/javascript" src="/apigateway-js-sdk/apigClient.js"></script><link rel="stylesheet" href="/custom-content/styles.css"><title>Developer Portal</title><link href="/static/css/2.1eb883ec.chunk.css" rel="stylesheet"><link href="/static/css/main.4ae54ac6.chunk.css" rel="stylesheet"></head><body><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={1:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/2.73aa822c.chunk.js"></script><script src="/static/js/main.d8afcf50.chunk.js"></script></body></html>

0 commit comments

Comments
 (0)