Conversation
juancarlosfarah
left a comment
There was a problem hiding this comment.
Nice PR @ugGit. Please have a look at my feedback.
src/createCli.js
Outdated
| type: 'string', | ||
| describe: 'Path to the Graasp app that shall be deployed', | ||
| }), | ||
| handler: promisify(deploy), |
There was a problem hiding this comment.
Do you need to promisify? The function is already a promise. Just double-checking.
There was a problem hiding this comment.
@juancarlosfarah I'm actually not sure. This is inspired by the implementation of the new command. But I tested now and the promisify() could be omitted in both cases. Please let me know if I'm missing a point here, otherwise I'll remove it in the next PR.
There was a problem hiding this comment.
Maybe originally the function was not a promise, thus promisify was needed. Looks like it's not needed anymore.
src/deploy.js
Outdated
| console.error(`path passed '${path}'`); | ||
| console.log(process.cwd()); | ||
| try { | ||
| await spawn('./src/test.sh'); |
There was a problem hiding this comment.
This should be ./test.sh after compiling inside the lib folder.
There was a problem hiding this comment.
@juancarlosfarah the test.sh file is not copied into the lib folder. I suppose babel is only considering .js file during compilation.
But even if I move the file manually, the command is executed at the location of the terminal and the path interpreted as relative path. Hence, the file would only be found when the command is executed in the lib folder
src/deploy.js
Outdated
| @@ -1,15 +1,85 @@ | |||
| import { spawn } from './utils'; | |||
| import AWS from 'aws-sdk'; | |||
There was a problem hiding this comment.
Let's stick to either aws or Aws.
There was a problem hiding this comment.
I just pushed the latest changes. Please check again
src/deploy.js
Outdated
| import s3 from 's3-node-client'; | ||
| import dotenv from 'dotenv'; | ||
|
|
||
| const path = require('path'); |
There was a problem hiding this comment.
Why use require and not import?
There was a problem hiding this comment.
pathis not used anymore in the latest changes.
src/deploy.js
Outdated
| } | ||
| // const { path } = opts; | ||
|
|
||
| const usageMessage = console.log( |
There was a problem hiding this comment.
I don't think we need this anymore.
src/deploy.sh
Outdated
| @@ -0,0 +1,125 @@ | |||
| #!/bin/bash | |||
There was a problem hiding this comment.
Do we still need this file?
src/utils.js
Outdated
| @@ -1,5 +1,7 @@ | |||
| import execa from 'execa'; | |||
|
|
|||
| // TODO: this is not optimal naming since it may cause confusion with 'spawn()' from 'child_process' module; | |||
There was a problem hiding this comment.
Refactor if needed to something like spawnProcess in a future commit.
src/deploy.js
Outdated
| const path = require('path'); | ||
|
|
||
| // default build directory | ||
| const BUILD = 'build/'; |
There was a problem hiding this comment.
Two options:
- Make default
-pbe./buildand-pbe described aspath/to/build/folder that will be deployed. - Leave
-pas is and allow for overriding this with a-b.
I think that 1 might be cleaner, but I'm up for discussing this.
There was a problem hiding this comment.
Good point. Currently I changed it to -b. This keeps the syntax from the original deploy script which might be appreciated by users of the script. Furthermore, i factored the default value out into the config.js file.
As the changes are easy to make, let me know if you prefer the -p variant.
src/deploy.js
Outdated
| ); | ||
|
|
||
| console.log(`Exectued with path: ${opts.path}`); | ||
| console.log(usageMessage); |
There was a problem hiding this comment.
I don't think we need this.
src/deploy.js
Outdated
| 'usage: $0 [-e <path/to/file>] [-v <version string>] [-b <path/to/build>]', | ||
| ); | ||
|
|
||
| console.log(`Exectued with path: ${opts.path}`); |
There was a problem hiding this comment.
Typo in executed. Also, we use all small caps in logs. I would suggest:
deploying app in {...} directory
or something similar.
src/deploy.js
Outdated
| REACT_APP_HOST, | ||
| REACT_APP_VERSION, | ||
| REACT_APP_BASE, | ||
| NODE_ENV, |
There was a problem hiding this comment.
I wasn't sure yet. It's removed now.
src/deploy.js
Outdated
| } = process.env; | ||
| /* eslint-enable no-unused-vars */ | ||
|
|
||
| AWS.config.getCredentials(function (err) { |
There was a problem hiding this comment.
Are you using this? Maybe promisify in order not to have to shove everything inside the callback.
There was a problem hiding this comment.
Yes. This reloads the credentials from the .env.xxx set before. Hence, the below dev note in the sdk doc does not apply.
Note: If you configure the SDK with static or environment credentials, the credential data should already be present in credentials attribute. This method is primarily necessary to load credentials from asynchronous sources, or sources that can refresh credentials periodically.
However, I'm still looking for a proper way to refactor this parts and maybe promisify will help me to do so. The challenge thereby is to check for the error and stop the further promise chain execution properly...
There was a problem hiding this comment.
By rethinking the look we already assure that the configuration can be loaded since we're manually checking that the env variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) exist. I will implement a first draft that we might discuss during the next meeting.
@juancarlosfarah Just checked the PR! thanks for copying me. |
juancarlosfarah
left a comment
There was a problem hiding this comment.
Hi @ugGit, thanks for the changes. We're almost there! Some minor comments below. Also, I didn't see some of the changes you mentioned, like the aws change. Please have a look.
src/deploy.js
Outdated
| @@ -1,15 +1,85 @@ | |||
| import { spawn } from './utils'; | |||
| import AWS from 'aws-sdk'; | |||
src/deploy.js
Outdated
| // Both compilation hints because of backslashes used in RegExp but unecessary by conception in JS Strings | ||
| // prettier-ignore | ||
| // eslint-disable-next-line no-useless-escape | ||
| const pattern = new RegExp('v\\d+(\.\\d+){0,2}$'); |
There was a problem hiding this comment.
Not sure this patter is the same as the one in the bash file. Consider this one:
// matches v<major>.<minor>.<patch>[-<meta>] version format
^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\-[0-9A-Za-z]*)?$
There was a problem hiding this comment.
Note that I haven't checked if it's JS compliant. Might be good to add some basic tests.
.eslintrc
Outdated
| } | ||
| ], | ||
| "import/no-named-as-default": 0 | ||
| "no-console": "off", |
There was a problem hiding this comment.
You don't need to turn this off, as it is a warning. I like to keep this on b/c it reminds me that we should use a logger, but for now it's fine. There are very nice loggers for CLIs, but you can leave it off for now if you want.
src/config.js
Outdated
| // deploy settings | ||
| export const DEFAULT_BUILD_DIR = 'build/'; | ||
| export const DEFAULT_APP_VERSION = 'latest'; | ||
| export const DEFAULT_ENV = '.env.dev'; |
There was a problem hiding this comment.
@juancarlosfarah Good question. As this was not the case in the previous deploy.sh script, I will remove this default option. Should I make the flag required as a consequence?
There was a problem hiding this comment.
I just saw that this can't be enforced. So, I suggest to simply let the validation error to pop up.
src/deploy.js
Outdated
|
|
||
| console.log( | ||
| `published app to https://${REACT_APP_HOST}/${APP_PATH}/index.html`, | ||
| `info: published app to https://${REACT_APP_HOST}/${APP_PATH}/index.html`, |
src/deploy.js
Outdated
| }; | ||
| const cloudfront = new AWS.CloudFront(); | ||
| cloudfront.createInvalidation(invalidationParams, (err, data) => { | ||
| if (err) console.log(err, err.stack); |
There was a problem hiding this comment.
Always use {} for if statements, especially with else.
There was a problem hiding this comment.
Also, put comments above.
src/deploy.js
Outdated
| ); | ||
|
|
||
| // configure the deployment | ||
| AWS.config.getCredentials((err) => { |
There was a problem hiding this comment.
I think you need to promisify and await here, no?
There was a problem hiding this comment.
@juancarlosfarah Absolutely correct. But currently not enough time to include it in this PR. Consequently, the commands risk not to be executed in the correct chronological order.
| console.log('done uploading'); | ||
| uploader.on('end', () => { | ||
| progressBar.stop(); | ||
| // TODO: insert here code that should be executed once the upload is done |
There was a problem hiding this comment.
This should be done. You can always create helper functions.
There was a problem hiding this comment.
@juancarlosfarah Yes, you are right. But I would require more time to do this. Might consider implementing this when finalizing the deploy command.
src/deploy.js
Outdated
| console.log(usageMessage); | ||
| // Validate command options | ||
| if (!validateTag(tag) || !validateEnv(env) || !validateBuild(build)) { | ||
| console.error('Abort...'); |
juancarlosfarah
left a comment
There was a problem hiding this comment.
Thanks @ugGit for the changes. I think a bunch of my comments from the previous commits got overridden b/w when I made them and when you made the changes. I have tagged you in some. Please have a look at them. Also, no need to prefix logs with error: or info:. That was for Bash's echo function. Here you can use console.info or console.error, or eventually use a fancier logging tool.
src/utils.js
Outdated
| return execa(file, args, opts); | ||
| }; | ||
|
|
||
| export const isDefined = (variable) => { |
There was a problem hiding this comment.
There is also a _.isUndefined function that you could use from lodash.
There was a problem hiding this comment.
I wasn't aware that this function existed. I have replaced it.
src/config.js
Outdated
| // deploy settings | ||
| export const DEFAULT_BUILD_DIR = 'build/'; | ||
| export const DEFAULT_APP_VERSION = 'latest'; | ||
| export const DEFAULT_ENV = '.env.dev'; |
src/deploy.js
Outdated
|
|
||
| // validate command options | ||
| if (!validateTag(tag) || !validateEnv(env) || !validateBuild(build)) { | ||
| console.error('Abort...'); |
There was a problem hiding this comment.
In previous comment I suggest you change this message to aborting deployment.
src/deploy.js
Outdated
| }; | ||
| const cloudfront = new AWS.CloudFront(); | ||
| cloudfront.createInvalidation(invalidationParams, (err, data) => { | ||
| if (err) console.log(err, err.stack); |
src/deploy.js
Outdated
|
|
||
| // configure the deployment | ||
| AWS.config.getCredentials((err) => { | ||
| aws.config.getCredentials((err) => { |
There was a problem hiding this comment.
Even if you guarantee that the correct variables are present, don't you need to wait for the setup to be done?
There was a problem hiding this comment.
Indeed the execution relies currently on a fast execution of this async method. A next PR must handle this problematic and properly chain the execution.
|
@ugGit, did you manage to look into the requested changes? |
|
@juancarlosfarah Yes. Apart of the handling for the |
juancarlosfarah
left a comment
There was a problem hiding this comment.
Hey @ugGit, I did some more research, and the node S3 client that you have used is pretty outdated:
https://github.com/shreyawhiz/node-s3-client#readme
We should be using everything from AWS where possible and use the promises in order to avoid getting stuck in complex callback situations.
Let me know if you want to discuss this.
src/deploy.js
Outdated
| !isDefined(REACT_APP_GRAASP_DEVELOPER_ID) || | ||
| !isDefined(REACT_APP_GRAASP_APP_ID) | ||
| ) { | ||
| console.error( |
src/deploy.js
Outdated
| `publishing app ${REACT_APP_GRAASP_APP_ID} version ${REACT_APP_VERSION}`, | ||
| ); | ||
|
|
||
| // configure the deployment |
There was a problem hiding this comment.
@ugGit, I think that you can use this promise version of getting the credentials.
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Credentials.html#getPromise-property
|
|
||
| // ensure the correct distribution variables are defined | ||
| if (!isDefined(DISTRIBUTION)) { | ||
| if (_.isUndefined(DISTRIBUTION)) { |
There was a problem hiding this comment.
everything after line 159 should be inside the on('end', () => { call in order to work. Preferably you can use the promises version of the native s3 client from AWS.
Promisify
Which works fine if the command is executed in the project roots directory. E.g.