Repository: serverless/serverless (JavaScript)
Date: 2018-06-27 14:19:23+00:00
Task type: Bug Fix

Issue:
Create command didn't use service name given as -n option.
<!--
1. If you have a question and not a bug/feature request please ask it at http://forum.serverless.com
2. Please check if an issue already exists so there are no duplicates
3. Check out and follow our Guidelines: https://github.com/serverless/serverless/blob/master/CONTRIBUTING.md
4. Fill out the whole template so we have a good overview on the issue
5. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the Issue
6. Please follow the template, otherwise we'll have to ask you to update it
-->

# This is a Bug Report

## Description
Create command works fine with template likes below:
```
service: example-service
~~~
```
But likes below, It didn't rename service name.
```
service: 
  name: example-service
~~~
```

It's dengerous becouse if I deployed multiple projects, firsrt project will be overriten by second one.

I flushed one service's all data in DynamoDB by "aws-nodejs-typescript" template. 

:cry: 


Similar or dependent issues:
* I coudn't find it.

## Additional Data
* ***Serverless Framework Version you're using***:
```
hiromi@hiromi-Matebook:~/git$ sls -v
1.27.3
```
* ***Operating System***:
```
hiromi@hiromi-Matebook:~/git$ uname -a
Linux hiromi-Matebook 4.15.0-23-generic #25-Ubuntu SMP Wed May 23 18:02:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
hiromi@hiromi-Matebook:~/git$ lsb_release  -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04 LTS
Release:	18.04
Codename:	bionic
hiromi@hiromi-Matebook:~/git$ 
```
* ***Stack Trace***:
n/a
* ***Provider Error messages***:
n/a

p.s. Many of my services made with serverless FW. It's GREAT project. Thank you.



Issue discussion:

Solution patch:
diff --git a/lib/plugins/create/create.js b/lib/plugins/create/create.js
index d1aeb1cbe2d..1a3f152db72 100644
--- a/lib/plugins/create/create.js
+++ b/lib/plugins/create/create.js
@@ -224,16 +224,8 @@ class Create {
     // rename the service if the user has provided a path via options and is creating a service
     if ((boilerplatePath || serviceName) && notPlugin) {
       const newServiceName = serviceName || boilerplatePath.split(path.sep).pop();
-      const serverlessYmlFilePath = path
-        .join(this.serverless.config.servicePath, 'serverless.yml');
 
-      let serverlessYmlFileContent = fse
-        .readFileSync(serverlessYmlFilePath).toString();
-
-      serverlessYmlFileContent = serverlessYmlFileContent
-        .replace(/service: .+/, `service: ${newServiceName}`);
-
-      fse.writeFileSync(serverlessYmlFilePath, serverlessYmlFileContent);
+      renameService(newServiceName, this.serverless.config.servicePath);
     }
 
     userStats.track('service_created', {
diff --git a/lib/utils/renameService.js b/lib/utils/renameService.js
index c0da76f91e7..ecb853c07be 100644
--- a/lib/utils/renameService.js
+++ b/lib/utils/renameService.js
@@ -24,6 +24,11 @@ function renameService(name, servicePath) {
         const fractions = match.split('#');
         fractions[0] = `service: ${name}`;
         return fractions.join(' #');
+      })
+      .replace(/service\s*:\n {2}name:.+/gi, (match) => {
+        const fractions = match.split('#');
+        fractions[0] = `service:\n  name: ${name}`;
+        return fractions.join(' #');
       });
 
   fse.writeFileSync(serviceFile, serverlessYml);


Test patch:
diff --git a/lib/plugins/create/create.test.js b/lib/plugins/create/create.test.js
index a6e10f2a1ca..00db1ce7228 100644
--- a/lib/plugins/create/create.test.js
+++ b/lib/plugins/create/create.test.js
@@ -115,6 +115,28 @@ describe('Create', () => {
         expect(dirContent).to.include('.gitignore');
       });
     });
+    it('should generate scaffolding for "aws-nodejs-typescript" ' +
+      'template and override service name if user passed', () => {
+      process.chdir(tmpDir);
+      create.options.template = 'aws-nodejs-typescript';
+      create.options.name = 'my-awesome-service';
+
+      return create.create().then(() => {
+        const dirContent = fs.readdirSync(tmpDir);
+        expect(dirContent).to.include('serverless.yml');
+        expect(dirContent).to.include('handler.ts');
+        expect(dirContent).to.include('tsconfig.json');
+        expect(dirContent).to.include('package.json');
+        expect(dirContent).to.include('webpack.config.js');
+        expect(dirContent).to.include('.gitignore');
+
+        // check if the service was renamed
+        const serverlessYmlfileContent = fse
+          .readFileSync(path.join(tmpDir, 'serverless.yml')).toString();
+        expect((/service:\n {2}name: my-awesome-service/)
+          .test(serverlessYmlfileContent)).to.equal(true);
+      });
+    });
 
     it('should generate scaffolding for "aws-nodejs-ecma-script" template', () => {
       process.chdir(tmpDir);
diff --git a/lib/utils/renameService.test.js b/lib/utils/renameService.test.js
index 0eecc66cdbe..7fb600f9b47 100644
--- a/lib/utils/renameService.test.js
+++ b/lib/utils/renameService.test.js
@@ -92,6 +92,50 @@ describe('renameService', () => {
     expect(serviceYml).to.equal(newServiceYml);
   });
 
+  it('should set new name of service in serverless.yml and name in package.json', () => {
+    const defaultServiceYml =
+      'service:\n  name: service-name\n\nprovider:\n  name: aws\n';
+    const newServiceYml =
+      'service:\n  name: new-service-name\n\nprovider:\n  name: aws\n';
+
+    const defaultServiceName = 'service-name';
+    const newServiceName = 'new-service-name';
+
+    const packageFile = path.join(servicePath, 'package.json');
+    const serviceFile = path.join(servicePath, 'serverless.yml');
+
+    serverless.utils.writeFileSync(packageFile, { name: defaultServiceName });
+    fse.writeFileSync(serviceFile, defaultServiceYml);
+
+    renameService(newServiceName, servicePath);
+    const serviceYml = fse.readFileSync(serviceFile, 'utf-8');
+    const packageJson = serverless.utils.readFileSync(packageFile);
+    expect(serviceYml).to.equal(newServiceYml);
+    expect(packageJson.name).to.equal(newServiceName);
+  });
+
+  it('should set new name of service in commented serverless.yml and name in package.json', () => {
+    const defaultServiceYml =
+      '# comment\nservice:\n  name: service-name #comment\n\nprovider:\n  name: aws\n# comment';
+    const newServiceYml =
+      '# comment\nservice:\n  name: new-service-name #comment\n\nprovider:\n  name: aws\n# comment';
+
+    const defaultServiceName = 'service-name';
+    const newServiceName = 'new-service-name';
+
+    const packageFile = path.join(servicePath, 'package.json');
+    const serviceFile = path.join(servicePath, 'serverless.yml');
+
+    serverless.utils.writeFileSync(packageFile, { name: defaultServiceName });
+    fse.writeFileSync(serviceFile, defaultServiceYml);
+
+    renameService(newServiceName, servicePath);
+    const serviceYml = fse.readFileSync(serviceFile, 'utf-8');
+    const packageJson = serverless.utils.readFileSync(packageFile);
+    expect(serviceYml).to.equal(newServiceYml);
+    expect(packageJson.name).to.equal(newServiceName);
+  });
+
   it('should fail to set new service name in serverless.yml', () => {
     const defaultServiceYml =
       '# comment\nservice: service-name #comment\n\nprovider:\n  name: aws\n# comment';