Repository: serverless/serverless (JavaScript)
Date: 2018-09-20 00:09:42+00:00
Task type: Bug Fix

Issue:
Consistent determination of servicePath
<!--
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

CWD is used as where to look for the serverless config (serverless.[json|yml|js|...]) in [validate](https://github.com/serverless/serverless/blob/master/lib/plugins/lib/validate.js#L8) but `servicePath` is used in [PluginManager](https://github.com/serverless/serverless/blob/master/lib/classes/PluginManager.js#L478).

This inconsistency is blowing up integration tests in serverless-artillery

Altering validate.js to read as follows (consistent with the PluginManager) resolves the matter but there is probably a better way to :
```
    const servicePath = this.serverless.config.servicePath || 'x';
    return getServerlessConfigFile(servicePath).then((result) => {
```

For bug reports:
* What went wrong?
We use:
```
    const serverless = new Serverless({
      interactive: false,
      servicePath: impl.findServicePath(),
    })
```
and as per the SLSART codebase, the service path (i.e. serverless.yml in this case) can be a central directory rather than the current working directory.  We therefore observe an error message stating that SLS has to be run in a service directory.

* What did you expect should have happened?

Continue the previous behavior of respecting the servicePath setting

* What was the config you used?

https://github.com/Nordstrom/serverless-artillery/blob/master/lib/lambda/serverless.yml
used via:
https://github.com/Nordstrom/serverless-artillery/blob/master/lib/index.js#L226
as a result of:
https://github.com/Nordstrom/serverless-artillery/blob/monitoring-mode/tests/integration/intro/intro.js#L5

* What stacktrace or error message from your provider did you see?

```
        Deploying Lambda to AWS...

Error: This command can only be run in a Serverless service directory
    at getServerlessConfigFile.then (.../node_modules/serverless/lib/plugins/lib/validate.js:12:23)
From previous event:
    at Deploy.validate (.../node_modules/serverless/lib/plugins/lib/validate.js:8:51)
From previous event:
    at Object.before:deploy:deploy [as hook] (.../node_modules/serverless/lib/plugins/deploy/deploy.js:112:10)
    at BbPromise.reduce (.../node_modules/serverless/lib/classes/PluginManager.js:372:55)
From previous event:
    at PluginManager.invoke (.../node_modules/serverless/lib/classes/PluginManager.js:372:22)
    at PluginManager.run (.../node_modules/serverless/lib/classes/PluginManager.js:403:17)
    at variables.populateService.then (.../node_modules/serverless/lib/Serverless.js:102:33)
    at runCallback (timers.js:672:20)
    at tryOnImmediate (timers.js:645:5)
    at processImmediate [as _immediateCallback] (timers.js:617:5)
From previous event:
    at Serverless.run (.../node_modules/serverless/lib/Serverless.js:89:74)
    at serverless.init.then.then (.../lib/index.js:639:30)
```

## Additional Data

* ***Serverless Framework Version you're using***: master
* ***Operating System***: osx
* ***Stack Trace***: above
* ***Provider Error messages***: n/a



Issue discussion:
@eahefnawy you introduced the `|| 'x'` logic in https://github.com/serverless/serverless/commit/e2cc1451a5da76d79236014ae413140e901928bc ; was there a specific importance to `'x'` or would `'.'` potentially be a valid replacement?  What requirements (if any) drove that code decision?  Thanks!
Perhaps even removing that defaulting from PluginManager and handing an undefined parameter in `getServerlessConfigFile`?

Solution patch:
diff --git a/lib/classes/PluginManager.js b/lib/classes/PluginManager.js
index 2e10cf0b080..ac97772e436 100644
--- a/lib/classes/PluginManager.js
+++ b/lib/classes/PluginManager.js
@@ -475,13 +475,12 @@ class PluginManager {
         .concat(Object.keys(command.commands));
     });
 
-    const servicePath = this.serverless.config.servicePath || 'x';
-    return getServerlessConfigFile(servicePath)
+    return getServerlessConfigFile(this.serverless.config.servicePath)
       .then((serverlessConfigFile) => {
         const serverlessConfigFileHash = crypto.createHash('sha256')
           .update(JSON.stringify(serverlessConfigFile)).digest('hex');
         cacheFile.validationHash = serverlessConfigFileHash;
-        const cacheFilePath = getCacheFilePath(servicePath);
+        const cacheFilePath = getCacheFilePath(this.serverless.config.servicePath);
         return writeFile(cacheFilePath, cacheFile);
       })
       .catch((e) => null);  // eslint-disable-line
diff --git a/lib/plugins/lib/validate.js b/lib/plugins/lib/validate.js
index 5d31d22bef5..11653caa26b 100644
--- a/lib/plugins/lib/validate.js
+++ b/lib/plugins/lib/validate.js
@@ -5,7 +5,7 @@ const getServerlessConfigFile = require('../../utils/getServerlessConfigFile');
 
 module.exports = {
   validate() {
-    return getServerlessConfigFile(process.cwd()).then((result) => {
+    return getServerlessConfigFile(this.serverless.config.servicePath).then((result) => {
       const isRunInService = !!result;
 
       if (!isRunInService) {
diff --git a/lib/plugins/print/print.js b/lib/plugins/print/print.js
index 9c146bdbc18..93ca74199b8 100644
--- a/lib/plugins/print/print.js
+++ b/lib/plugins/print/print.js
@@ -94,7 +94,7 @@ class Print {
     // the codebase.  Avoiding that, this method must read the serverless.yml file itself, adorn it
     // as the Service class would and then populate it, reversing the adornments thereafter in
     // preparation for printing the service for the user.
-    return getServerlessConfigFile(process.cwd())
+    return getServerlessConfigFile(this.serverless.config.servicePath)
       .then((svc) => {
         const service = svc;
         this.adorn(service);
diff --git a/lib/utils/autocomplete.js b/lib/utils/autocomplete.js
index 6b744aa8fe7..531de8bb9a4 100644
--- a/lib/utils/autocomplete.js
+++ b/lib/utils/autocomplete.js
@@ -40,27 +40,22 @@ const cacheFileValid = (serverlessConfigFile, validationHash) => {
 };
 
 const autocomplete = () => {
-  let servicePath = process.cwd();
+  const servicePath = process.cwd();
   return getServerlessConfigFile(servicePath)
-    .then((serverlessConfigFile) => {
-      if (!serverlessConfigFile) {
-        servicePath = 'x';
-      }
-      return getCacheFile(servicePath)
-        .then((cacheFile) => {
-          if (!cacheFile || !cacheFileValid(serverlessConfigFile, cacheFile.validationHash)) {
-            const serverless = new Serverless();
-            return serverless.init().then(() => getCacheFile(servicePath));
-          }
-          return cacheFile;
-        })
-        .then((cacheFile) => {
-          if (!cacheFile || !cacheFileValid(serverlessConfigFile, cacheFile.validationHash)) {
-            return;
-          }
-          return getSuggestions(cacheFile.commands); // eslint-disable-line consistent-return
-        });
-    });
+    .then((serverlessConfigFile) => getCacheFile(servicePath)
+      .then((cacheFile) => {
+        if (!cacheFile || !cacheFileValid(serverlessConfigFile, cacheFile.validationHash)) {
+          const serverless = new Serverless();
+          return serverless.init().then(() => getCacheFile(servicePath));
+        }
+        return cacheFile;
+      })
+      .then((cacheFile) => {
+        if (!cacheFile || !cacheFileValid(serverlessConfigFile, cacheFile.validationHash)) {
+          return;
+        }
+        return getSuggestions(cacheFile.commands); // eslint-disable-line consistent-return
+      }));
 };
 
 module.exports = autocomplete;
diff --git a/lib/utils/getCacheFilePath.js b/lib/utils/getCacheFilePath.js
index 523c7b428c8..adf6d5d259f 100644
--- a/lib/utils/getCacheFilePath.js
+++ b/lib/utils/getCacheFilePath.js
@@ -4,7 +4,8 @@ const homedir = require('os').homedir();
 const path = require('path');
 const crypto = require('crypto');
 
-const getCacheFilePath = function (servicePath) {
+const getCacheFilePath = function (srvcPath) {
+  const servicePath = srvcPath || process.cwd();
   const servicePathHash = crypto.createHash('sha256').update(servicePath).digest('hex');
   return path.join(homedir, '.serverless', 'cache', servicePathHash, 'autocomplete.json');
 };
diff --git a/lib/utils/getServerlessConfigFile.js b/lib/utils/getServerlessConfigFile.js
index a85a1b67b6f..5b201ace1cd 100644
--- a/lib/utils/getServerlessConfigFile.js
+++ b/lib/utils/getServerlessConfigFile.js
@@ -6,7 +6,8 @@ const path = require('path');
 const fileExists = require('./fs/fileExists');
 const readFile = require('./fs/readFile');
 
-const getServerlessConfigFile = _.memoize((servicePath) => {
+const getServerlessConfigFile = _.memoize((srvcPath) => {
+  const servicePath = srvcPath || process.cwd();
   const jsonPath = path.join(servicePath, 'serverless.json');
   const ymlPath = path.join(servicePath, 'serverless.yml');
   const yamlPath = path.join(servicePath, 'serverless.yaml');
diff --git a/package-lock.json b/package-lock.json
index fd40a8a5db9..ae270005187 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -106,7 +106,7 @@
       "dependencies": {
         "acorn": {
           "version": "3.3.0",
-          "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
           "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
           "dev": true
         }
@@ -780,7 +780,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -889,7 +889,7 @@
     },
     "babel-plugin-istanbul": {
       "version": "4.1.6",
-      "resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
       "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==",
       "dev": true,
       "requires": {
@@ -918,7 +918,7 @@
     },
     "babel-plugin-syntax-object-rest-spread": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
       "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
       "dev": true
     },
@@ -1571,7 +1571,7 @@
     },
     "combined-stream": {
       "version": "1.0.6",
-      "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
       "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
       "requires": {
         "delayed-stream": "~1.0.0"
@@ -1579,7 +1579,7 @@
     },
     "commander": {
       "version": "2.8.1",
-      "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
       "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
       "requires": {
         "graceful-readlink": ">= 1.0.0"
@@ -2425,7 +2425,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -2438,7 +2438,7 @@
         },
         "inquirer": {
           "version": "0.12.0",
-          "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
+          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
           "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=",
           "dev": true,
           "requires": {
@@ -2705,7 +2705,7 @@
     },
     "express": {
       "version": "4.16.3",
-      "resolved": "http://registry.npmjs.org/express/-/express-4.16.3.tgz",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
       "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
       "requires": {
         "accepts": "~1.3.5",
@@ -2836,7 +2836,7 @@
     },
     "external-editor": {
       "version": "1.1.1",
-      "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz",
       "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs=",
       "requires": {
         "extend": "^3.0.0",
@@ -3769,7 +3769,7 @@
     },
     "got": {
       "version": "6.7.1",
-      "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz",
+      "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
       "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
       "requires": {
         "create-error-class": "^3.0.0",
@@ -4036,7 +4036,7 @@
     },
     "http-errors": {
       "version": "1.6.3",
-      "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
       "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
       "requires": {
         "depd": "~1.1.2",
@@ -4172,7 +4172,7 @@
     },
     "inquirer": {
       "version": "1.2.3",
-      "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz",
       "integrity": "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg=",
       "requires": {
         "ansi-escapes": "^1.1.0",
@@ -4198,7 +4198,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "requires": {
             "ansi-styles": "^2.2.1",
@@ -4438,7 +4438,7 @@
     },
     "is-obj": {
       "version": "1.0.1",
-      "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
       "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
     },
     "is-object": {
@@ -5359,7 +5359,7 @@
     },
     "jsonfile": {
       "version": "2.4.0",
-      "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
       "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
       "requires": {
         "graceful-fs": "^4.1.6"
@@ -5416,7 +5416,7 @@
         },
         "es6-promise": {
           "version": "3.0.2",
-          "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
+          "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
           "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=",
           "dev": true
         },
@@ -5428,7 +5428,7 @@
         },
         "readable-stream": {
           "version": "2.0.6",
-          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
           "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
           "dev": true,
           "requires": {
@@ -5572,7 +5572,7 @@
     },
     "load-json-file": {
       "version": "1.1.0",
-      "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
       "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
       "dev": true,
       "requires": {
@@ -5680,7 +5680,7 @@
     },
     "lolex": {
       "version": "1.3.2",
-      "resolved": "http://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz",
+      "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz",
       "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=",
       "dev": true
     },
@@ -5927,7 +5927,7 @@
     },
     "minimist": {
       "version": "1.2.0",
-      "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
       "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
     },
     "mixin-deep": {
@@ -5953,7 +5953,7 @@
     },
     "mkdirp": {
       "version": "0.5.1",
-      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "requires": {
         "minimist": "0.0.8"
@@ -5961,7 +5961,7 @@
       "dependencies": {
         "minimist": {
           "version": "0.0.8",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
           "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
         }
       }
@@ -5987,7 +5987,7 @@
       "dependencies": {
         "commander": {
           "version": "2.15.1",
-          "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
           "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
           "dev": true
         },
@@ -6358,7 +6358,7 @@
     },
     "onetime": {
       "version": "1.1.0",
-      "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
       "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="
     },
     "opn": {
@@ -6381,7 +6381,7 @@
       "dependencies": {
         "minimist": {
           "version": "0.0.10",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
           "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
           "dev": true
         },
@@ -6878,7 +6878,7 @@
     },
     "readable-stream": {
       "version": "2.3.6",
-      "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
       "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
       "requires": {
         "core-util-is": "~1.0.0",
@@ -7511,7 +7511,7 @@
     },
     "sax": {
       "version": "1.2.1",
-      "resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
       "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
     },
     "seek-bzip": {
@@ -7658,7 +7658,7 @@
     },
     "sinon": {
       "version": "1.17.7",
-      "resolved": "http://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz",
+      "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz",
       "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=",
       "dev": true,
       "requires": {
@@ -8109,7 +8109,7 @@
     },
     "table": {
       "version": "3.8.3",
-      "resolved": "http://registry.npmjs.org/table/-/table-3.8.3.tgz",
+      "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz",
       "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=",
       "dev": true,
       "requires": {
@@ -8145,7 +8145,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -8277,7 +8277,7 @@
     },
     "through": {
       "version": "2.3.8",
-      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
     },
     "timed-out": {
@@ -8877,7 +8877,7 @@
     },
     "wrap-ansi": {
       "version": "2.1.0",
-      "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
       "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
       "dev": true,
       "requires": {


Test patch:
diff --git a/lib/plugins/lib/validate.test.js b/lib/plugins/lib/validate.test.js
index a88fb15f7c6..baad28f55db 100644
--- a/lib/plugins/lib/validate.test.js
+++ b/lib/plugins/lib/validate.test.js
@@ -39,7 +39,8 @@ describe('#validate()', () => {
 
     return expect(serverlessPlugin.validate()).to.be.fulfilled.then(() => {
       expect(getServerlessConfigFileStub).to.have.been.calledOnce;
-      expect(getServerlessConfigFileStub).to.have.been.calledWithExactly(process.cwd());
+      expect(getServerlessConfigFileStub).to.have.been
+        .calledWithExactly(serverless.config.servicePath);
     });
   });
 });
diff --git a/lib/utils/getServerlessConfigFile.test.js b/lib/utils/getServerlessConfigFile.test.js
index 2d6c0fa488e..40794ad23a7 100644
--- a/lib/utils/getServerlessConfigFile.test.js
+++ b/lib/utils/getServerlessConfigFile.test.js
@@ -73,4 +73,21 @@ describe('#getServerlessConfigFile()', () => {
     return expect(getServerlessConfigFile(tmpDirPath))
       .to.be.rejectedWith('serverless.js must export plain object');
   });
+
+  it('should look in the current working directory if servicePath is undefined', () => {
+    const serverlessFilePath = path.join(tmpDirPath, 'serverless.yml');
+
+    writeFileSync(serverlessFilePath, 'service: my-yml-service');
+    const cwd = process.cwd();
+    process.chdir(tmpDirPath);
+    return expect(getServerlessConfigFile()).to.be.fulfilled
+      .then(result => result)
+      .catch((ex) => {
+        process.chdir(cwd);
+        throw ex;
+      })
+      .then((result) => {
+        expect(result).to.deep.equal({ service: 'my-yml-service' });
+      });
+  });
 });