-
Notifications
You must be signed in to change notification settings - Fork 1
Deploy cmd #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Deploy cmd #42
Conversation
juancarlosfarah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to promisify? The function is already a promise. Just double-checking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be ./test.sh after compiling inside the lib folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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
juancarlosfarah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/deploy.js
Outdated
| @@ -1,15 +1,85 @@ | |||
| import { spawn } from './utils'; | |||
| import AWS from 'aws-sdk'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's stick to either aws or Aws.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to aws
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, I don't see the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use require and not import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed it.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need NODE_ENV?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you using this? Maybe promisify in order not to have to shove everything inside the callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, I don't see the change.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that I haven't checked if it's JS compliant. Might be good to add some basic tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, please consider this comment.
.eslintrc
Outdated
| } | ||
| ], | ||
| "import/no-named-as-default": 0 | ||
| "no-console": "off", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Answered here #42 (comment)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is dev default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, please consider this comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for info.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always use {} for if statements, especially with else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, put comments above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, please consider this comment.
src/deploy.js
Outdated
| ); | ||
|
|
||
| // configure the deployment | ||
| AWS.config.getCredentials((err) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to promisify and await here, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be done. You can always create helper functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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...'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aborting deployment...
juancarlosfarah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also a _.isUndefined function that you could use from lodash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, please consider this comment.
src/deploy.js
Outdated
|
|
||
| // validate command options | ||
| if (!validateTag(tag) || !validateEnv(env) || !validateBuild(build)) { | ||
| console.error('Abort...'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, please consider this comment.
src/deploy.js
Outdated
|
|
||
| // configure the deployment | ||
| AWS.config.getCredentials((err) => { | ||
| aws.config.getCredentials((err) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ugGit, you forgot to remove the error: bit.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.