Skip to content
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

Enables service installation with a name #2616

Merged
merged 20 commits into from Jan 2, 2017

Conversation

laardee
Copy link
Member

@laardee laardee commented Nov 3, 2016

What did you implement:

This PR enables to rename the service when installing from GitHub, for example serverless install --name new-service-name --url https://github.com/SC5/serverless-messenger-boilerplate will install serverless-messenger-boilerplate to folder new-service-name and change service value in serverless.yml to new-service-name.

Closes #2626

How did you implement it:

Added new parameter name to install class and renameService helper function for renaming service in yaml file.

How can we verify it:

serverless install --name new-service-name --url https://github.com/SC5/serverless-messenger-boilerplate should install service to new-service-name folder and change service name to new-service-name.

Todos:

  • Write tests
  • Write documentation
  • Fix linting errors
  • Make sure code coverage hasn't dropped
  • Provide verification config/commands/resources
  • Change ready for review message below

Is this ready for review?: YES

@laardee
Copy link
Member Author

laardee commented Nov 3, 2016

@pmuens, I noticed that you wrote the original download test, what kind of a test should I write for this? The current installation test just seems to mock download or something like that (the url is invalid).

@laardee laardee changed the title Enables service installation with a new name Enables service installation with a name Nov 4, 2016
@pmuens
Copy link
Contributor

pmuens commented Nov 4, 2016

Hey @laardee. Great addition to the install command! I like it 👍 💯

Hmm. Couldn't you stub the download again and return something there (pretending the download succeeds). And after that test if the renameService function is called.
Furthermore you can unit test the renameService in isolation.

Maybe @eahefnawy and @flomotlik can add some thoughts here.

Today I stumbled upon an improvement for the proxyquire usage. I've implemented it here:
https://github.com/serverless/serverless/blob/master/lib/classes/Utils.test.js#L21-L29

Basically it should be moved in the beforeEach() so that you get a fresh stub every time.

Let me know if you need any help!

@laardee
Copy link
Member Author

laardee commented Nov 4, 2016

@pmuens thanks, I wrote unit test for renameService af53bcb, it creates serverless.yml and package.json files (only service and name keys), then it uses renameService to change those and verifies that.

I also moved downloadStub to beforeEach as you suggested and added one expect to check that the path that is created contains the new name for service df499e7.

@pmuens
Copy link
Contributor

pmuens commented Nov 4, 2016

Hey @laardee thank you. Sounds good! 👍

Will review and take a deep dive ASAP.

@laardee
Copy link
Member Author

laardee commented Nov 5, 2016

I changed yml read/write in renameService function to use plain fs module with string replace to preserve comments in serverless.yml, js-yaml module doesn't seem to support comments nodeca/js-yaml#305.

Copy link
Contributor

@pmuens pmuens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @laardee thanks for your work on this one and the requested updates 💯 ! Great job 👍 Really like the functionality!

I added a few comments.

Pinging @eahefnawy and @flomotlik for feedback as well!

```

This example will download the .zip file of the `authentication` service from GitHub, create a new directory with the name `my-authentication` in the current working directory, unzips the files in this directory and renames service to `my-authentication` if `serverless.yml` exists in the service root.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"... and renames the service"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -22,6 +24,11 @@ class Install {
required: true,
shortcut: 'u',
},
name: {
usage: 'Name for the service',
required: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be left out as it means that same as require: false (AFAIK we don't follow this pattern in other plugins).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

.then(contents => this.serverless.utils.writeFile(packageFile, contents)),
])
.then(() => resolve(` as "${name}"`))
.catch((error) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be enhanced following this pattern we use throughout the codebase (

const errorMessage = [
`Invalid http event in function "${functionName}"`,
' in serverless.yml.',
' If you define an http event, make sure you pass a valid value for it,',
' either as string syntax, or object syntax.',
' Please check the docs for more options.',
].join('');
throw new this.serverless.classes.Error(errorMessage);
).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or you could let Serverless catch the error and remove the catch block altogether.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored this to be synchronous and used this.serverless.classes.Error for throwing error. Error message could still be better.

@@ -77,5 +129,18 @@ describe('Install', () => {
expect(downloadStub.args[0][0]).to.equal(`${install.options.url}/archive/master.zip`);
});
});

it('should download and rename the service based on the GitHub URL', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we enhance this test somehow that the call to the renaming method is tested as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pmuens, so basically either serverless.yml should be created to the download folder beforehand or downloadStub should pass zip containing serverless.yml as a payload. The first one might not work, because file should be created to folder before running the install function, which checks if the folder exists and if so it won't install the package. I'll check if I can pass the zip as a payload.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the downloadStub mocks the zip loading and saves serverless.yml, then installation process renames the service value and finally the result is tested.

readFile(serviceFile, 'utf-8')
.then(contents =>
contents.replace(/service\s*:.+/gi, (match) => {
const fractions = match.split('#');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are commented out parts in a serverless.yml file that common?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about others, but at least we have some comments on our workshop boilerplates and other similar project templates.

return fractions.join(' #');
}))
.then(contents => writeFile(serviceFile, contents)),
this.serverless.utils.readFile(packageFile)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does a service always have a package.json file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, fixed.

@laardee
Copy link
Member Author

laardee commented Nov 8, 2016

@pmuens, ready for review round two 😅

@pmuens
Copy link
Contributor

pmuens commented Nov 9, 2016

Hey @laardee
Thank you very much for the updates to this PR! 👍
I followed this PR the other days and it looks really promising!

I take a deep dive later again because we're currently focused on 1.2 (https://github.com/serverless/serverless/milestone/16) to get this out of the door next week.

Again. Thanks for working on this really good addition! 👍 💃

@laardee
Copy link
Member Author

laardee commented Nov 26, 2016

@pmuens, have you already had time to look into this? I know this is not the first priority PR so I don't mind waiting and rebasing 😄

@pmuens
Copy link
Contributor

pmuens commented Nov 27, 2016

@laardee thanks for getting back. 👍

Unfortunately I didn't have any time yet 😞 . But we'll plan the next milestones soon and will prioritize this PR soon. Sorry for the inconveniences.

@laardee
Copy link
Member Author

laardee commented Dec 10, 2016

@pmuens, I fixed the code to work with #2816. Unit tests are passing but the lint fails because of the metrics plugin. Is someone fixing that already?

@laardee
Copy link
Member Author

laardee commented Dec 11, 2016

rebased, tests are now passing 👌

@laardee
Copy link
Member Author

laardee commented Dec 19, 2016

I wonder if 🎅 comes before next review round. 😀

Copy link
Contributor

@pmuens pmuens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @laardee sorry for the slow response / review on our end!

🎅 is finally here 😆 ! I looked over the code today and tested it. Works great! Good job 👍

I just pushed some minor changes on top of your PR. Basically the tests are now side-effect free and more predictable.

GTM from my side. Waiting for another Approval and then we can merge it! 👍

@pmuens pmuens added this to the 1.5 milestone Dec 22, 2016
Copy link
Member

@eahefnawy eahefnawy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @laardee & @pmuens for your work here. Works as expected!

@eahefnawy eahefnawy merged commit 99f9073 into serverless:master Jan 2, 2017
@laardee laardee deleted the install-with-name branch January 2, 2017 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants