refactor!: drop q (#395)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index f2e63b6..f2c3a07 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -17,10 +17,18 @@
 
 extends: '@cordova/eslint-config/node'
 
+# FIXME avoid rule exceptions
+rules:
+  prefer-promise-reject-errors: off
+
 overrides:
   - files: [spec/**/*.js]
     extends: '@cordova/eslint-config/node-tests'
 
+    # FIXME avoid rule exceptions
+    rules:
+      prefer-promise-reject-errors: off
+
   - files: [cordova-js-src/**/*.js]
     extends: '@cordova/eslint-config/browser'
 
diff --git a/bin/check_all b/bin/check_all
index 853051e..ba6a896 100644
--- a/bin/check_all
+++ b/bin/check_all
@@ -25,7 +25,7 @@
 if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) > -1) {
     check_reqs.help();
 } else {
-    check_reqs.check_all().done(function success (result) {
+    check_reqs.check_all().then(function success (result) {
         console.log('check_all', result);
     }, function (err) {
         console.error('Error: ' + err);
diff --git a/bin/check_reqs b/bin/check_reqs
index ddc2eaf..e75ea33 100755
--- a/bin/check_reqs
+++ b/bin/check_reqs
@@ -25,7 +25,7 @@
 if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) > -1) {
     check_reqs.help();
 } else {
-    check_reqs.run().done(function success (msbuild) {
+    check_reqs.run().then(function success (msbuild) {
         console.log('Environment is supported; found MSBuild Tools version ' + msbuild.version + ' at ' + msbuild.path);
     }, function (err) {
         console.error('Environment is not supported: ' + err);
diff --git a/bin/create b/bin/create
index c0b229f..d8499ed 100755
--- a/bin/create
+++ b/bin/create
@@ -56,4 +56,7 @@
 
 require('../template/cordova/lib/loggingHelper').adjustLoggerLevel(options);
 
-Api.createPlatform(argv.argv.remain[0], config, options).done();
+Api.createPlatform(argv.argv.remain[0], config, options).catch(err => {
+    console.error(err);
+    process.exit(2);
+});
diff --git a/bin/lib/check_reqs.js b/bin/lib/check_reqs.js
index e3d9b5e..7ef2697 100644
--- a/bin/lib/check_reqs.js
+++ b/bin/lib/check_reqs.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var os = require('os');
 var path = require('path');
 var shell = require('shelljs');
@@ -107,7 +106,7 @@
     return spawn('ver').then(function (output) {
         var match = /\[Version (.*)\]\s*$/.exec(output);
         return Version.fromString(match[1]);
-    }).fail(function () {
+    }).catch(function () {
         return Version.fromString(os.release());
     });
 }
@@ -122,7 +121,7 @@
     // Query all keys with Install value equal to 1, then filter out
     // those, which are not related to VS itself
     return spawn('reg', ['query', 'HKLM\\SOFTWARE\\Microsoft\\DevDiv\\vs\\Servicing', '/s', '/v', 'Install', '/f', '1', '/d', '/e', '/reg:32'])
-        .fail(function () { return ''; })
+        .catch(function () { return ''; })
         .then(function (output) {
             return output.split('\n')
                 .reduce(function (installedVersions, line) {
@@ -139,9 +138,9 @@
                 .then(function (output) {
                     var updateVer = Version.fromString(/PackageVersion\s+REG_SZ\s+(.*)/i.exec(output)[1]);
                     // if update version is lover than Update2, reject the promise
-                    if (VS2013_UPDATE2_RC.gte(updateVer)) return Q.reject();
+                    if (VS2013_UPDATE2_RC.gte(updateVer)) return Promise.reject();
                     return installedVersions;
-                }).fail(function () {
+                }).catch(function () {
                     // if we got any errors on previous steps, we're assuming that
                     // required VS update is not installed.
                     installedVersions.splice(installedVersions.indexOf('12.0'), 1);
@@ -164,7 +163,7 @@
 function getInstalledWindowsSdks () {
     var installedSdks = [];
     return spawn('reg', ['query', 'HKLM\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows', '/s', '/v', 'InstallationFolder', '/reg:32'])
-        .fail(function () { return ''; })
+        .catch(function () { return ''; })
         .then(function (output) {
             var re = /\\Microsoft SDKs\\Windows\\v(\d+\.\d+)\s*InstallationFolder\s+REG_SZ\s+(.*)/gim;
             var match;
@@ -175,7 +174,7 @@
                     installedSdks.push(Version.tryParse(match[1]));
                 }
             }
-        }).thenResolve(installedSdks);
+        }).then(() => installedSdks);
 }
 
 /**
@@ -188,7 +187,7 @@
 function getInstalledPhoneSdks () {
     var installedSdks = [];
     return spawn('reg', ['query', 'HKLM\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows Phone\\v8.1', '/v', 'InstallationFolder', '/reg:32'])
-        .fail(function () { return ''; })
+        .catch(function () { return ''; })
         .then(function (output) {
             var match = /\\Microsoft SDKs\\Windows Phone\\v(\d+\.\d+)\s*InstallationFolder\s+REG_SZ\s+(.*)/gim.exec(output);
             if (match && shell.test('-e', path.join(match[2], 'SDKManifest.xml'))) {
@@ -196,14 +195,14 @@
             }
         }).then(function () {
             return spawn('reg', ['query', 'HKLM\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v10.0', '/v', 'InstallationFolder', '/reg:32']);
-        }).fail(function () {
+        }).catch(function () {
             return '';
         }).then(function (output) {
             var match = /\\Microsoft SDKs\\Windows\\v(\d+\.\d+)\s*InstallationFolder\s+REG_SZ\s+(.*)/gim.exec(output);
             if (match && shell.test('-e', path.join(match[2], 'SDKManifest.xml'))) {
                 installedSdks.push(Version.tryParse(match[1]));
             }
-        }).thenResolve(installedSdks);
+        }).then(() => installedSdks);
 }
 
 /**
@@ -245,7 +244,7 @@
 var checkOS = function (windowsTargetVersion, windowsPhoneTargetVersion) {
     if (process.platform !== 'win32') {
         // Build Universal windows apps available for windows platform only, so we reject on others platforms
-        return Q.reject('Cordova tooling for Windows requires Windows OS to build project');
+        return Promise.reject('Cordova tooling for Windows requires Windows OS to build project');
     }
 
     return getWindowsVersion().then(function (actualVersion) {
@@ -256,7 +255,7 @@
             return mapWindowsVersionToName(actualVersion);
         }
 
-        return Q.reject('Current Windows version doesn\'t support building this project. ' +
+        return Promise.reject('Current Windows version doesn\'t support building this project. ' +
             'Consider upgrading your OS to ' + mapWindowsVersionToName(requiredOsVersion));
     });
 };
@@ -281,7 +280,7 @@
             // console.log('appropriateVersion', appropriateVersion);
             return appropriateVersion
                 ? shortenVersion(appropriateVersion)
-                : Q.reject('MSBuild tools v.' + shortenVersion(msbuildRequiredVersion) + ' not found. ' +
+                : Promise.reject('MSBuild tools v.' + shortenVersion(msbuildRequiredVersion) + ' not found. ' +
                     'Please install Visual Studio ' + mapVSVersionToName(getMinimalRequiredVersionFor('visualstudio', windowsTargetVersion, windowsPhoneTargetVersion)) +
                     ' or higher from https://www.visualstudio.com/downloads/download-visual-studio-vs');
         });
@@ -291,14 +290,14 @@
     var vsRequiredVersion = getMinimalRequiredVersionFor('visualstudio', windowsTargetVersion, windowsPhoneTargetVersion);
 
     if (process.env.VSINSTALLDIR) {
-        return Q('(user-specified via VSINSTALLDIR)');
+        return Promise.resolve('(user-specified via VSINSTALLDIR)');
     }
     return getInstalledVSVersions()
         .then(function (installedVersions) {
             var appropriateVersion = getHighestAppropriateVersion(installedVersions, vsRequiredVersion);
             return appropriateVersion
                 ? shortenVersion(appropriateVersion)
-                : Q.reject('Required version of Visual Studio not found. Please install Visual Studio ' +
+                : Promise.reject('Required version of Visual Studio not found. Please install Visual Studio ' +
                     mapVSVersionToName(vsRequiredVersion) +
                     ' or higher from https://www.visualstudio.com/downloads/download-visual-studio-vs');
         });
@@ -312,7 +311,7 @@
                 return installedSdk.eq(requiredVersion);
             });
             if (!hasSdkInstalled) {
-                return Q.reject('Windows SDK not found. Ensure that you have installed ' +
+                return Promise.reject('Windows SDK not found. Ensure that you have installed ' +
                     'Windows ' + shortenVersion(requiredVersion) + ' SDK along with Visual Studio or install ' +
                     'Windows ' + shortenVersion(requiredVersion) + ' SDK separately from ' +
                     'https://dev.windows.com/en-us/downloads');
@@ -332,10 +331,10 @@
 
             return hasSdkInstalled
                 ? shortenVersion(requiredVersion)
-                : Q.reject();
+                : Promise.reject();
         })
-        .fail(function () {
-            return Q.reject('Windows Phone SDK not found. Ensure that you have installed ' +
+        .catch(function () {
+            return Promise.reject('Windows Phone SDK not found. Ensure that you have installed ' +
                 'Windows Phone ' + shortenVersion(requiredVersion) + ' SDK along with Visual Studio or install ' +
                 'Windows Phone ' + shortenVersion(requiredVersion) + ' SDK separately from ' +
                 'https://dev.windows.com/develop/download-phone-sdk');
@@ -390,15 +389,15 @@
 function getConfig () {
     try {
         config = config || new ConfigParser(path.join(__dirname, '../../config.xml'));
-        return Q(config);
+        return Promise.resolve(config);
     } catch (e) {
         // try again to cover case of being called from command line
         try {
             config = config || new ConfigParser(path.join(__dirname, '../../template/config.xml'));
-            return Q(config);
+            return Promise.resolve(config);
         } catch (e) {
             // yeah, really no config.xml
-            return Q.reject(new CordovaError('Can\'t check requirements for Windows platform.' +
+            return Promise.reject(new CordovaError('Can\'t check requirements for Windows platform.' +
                 'The config.xml file is either missing or malformed.'));
         }
     }
@@ -418,7 +417,7 @@
         return promise.then(function () {
             // If fatal requirement is failed,
             // we don't need to check others
-            if (fatalIsHit) return Q();
+            if (fatalIsHit) return;
             var requirement = requirements[idx];
             return getConfig()
                 .then(function (config) {
@@ -434,7 +433,7 @@
                         });
                 });
         });
-    }, Q())
+    }, Promise.resolve())
         .then(function () {
             // When chain is completed, return requirements array to upstream API
             return result;
diff --git a/bin/lib/create.js b/bin/lib/create.js
index ccbd33c..b0ee027 100644
--- a/bin/lib/create.js
+++ b/bin/lib/create.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var fs = require('fs');
 var path = require('path');
 var shell = require('shelljs');
@@ -29,11 +28,11 @@
 
 // Creates cordova-windows project at specified path with specified namespace, app name and GUID
 module.exports.create = function (destinationDir, config, options) {
-    if (!destinationDir) return Q.reject('No destination directory specified.');
+    if (!destinationDir) return Promise.reject('No destination directory specified.');
 
     var projectPath = path.resolve(destinationDir);
     if (fs.existsSync(projectPath)) {
-        return Q.reject(new CordovaError('Project directory already exists:\n\t' + projectPath));
+        return Promise.reject(new CordovaError('Project directory already exists:\n\t' + projectPath));
     }
 
     // Set parameters/defaults for create
@@ -120,7 +119,7 @@
     });
 
     events.emit('log', 'Windows project created with ' + pkg.name + '@' + pkg.version);
-    return Q.resolve();
+    return Promise.resolve();
 };
 
 function recursiveCreateDirectory (targetPath, previousPath) {
diff --git a/bin/lib/update.js b/bin/lib/update.js
index 2372703..4126aab 100644
--- a/bin/lib/update.js
+++ b/bin/lib/update.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var fs = require('fs');
 var path = require('path');
 var shell = require('shelljs');
@@ -31,12 +30,12 @@
 module.exports.update = function (destinationDir, options) {
     if (!fs.existsSync(destinationDir)) {
         // if specified project path is not valid then reject promise
-        return Q.reject(new CordovaError('The given path to the project does not exist: ' + destinationDir));
+        return Promise.reject(new CordovaError('The given path to the project does not exist: ' + destinationDir));
     }
 
     var projectConfig = path.join(destinationDir, 'config.xml');
     if (!fs.existsSync(projectConfig)) {
-        return Q.reject(new CordovaError('Can\'t update project at ' + destinationDir +
+        return Promise.reject(new CordovaError('Can\'t update project at ' + destinationDir +
             '. config.xml does not exist in destination directory'));
     }
 
diff --git a/bin/update b/bin/update
index 0133ce9..90a83bc 100755
--- a/bin/update
+++ b/bin/update
@@ -37,4 +37,7 @@
 
 require('../template/cordova/lib/loggingHelper').adjustLoggerLevel(args);
 
-Api.updatePlatform(args.argv.remain[0]).done();
+Api.updatePlatform(args.argv.remain[0]).catch(err => {
+    console.error(err);
+    process.exit(2);
+});
diff --git a/package.json b/package.json
index cc85299..9b9ccfa 100644
--- a/package.json
+++ b/package.json
@@ -24,7 +24,6 @@
     "fs-extra": "^9.0.0",
     "node-uuid": "^1.4.8",
     "nopt": "^4.0.1",
-    "q": "^1.5.1",
     "semver": "^5.5.0",
     "shelljs": "^0.5.3",
     "winjs": "^4.4.3"
diff --git a/spec/unit/MSBuildTools.spec.js b/spec/unit/MSBuildTools.spec.js
index 47ee796..835756c 100644
--- a/spec/unit/MSBuildTools.spec.js
+++ b/spec/unit/MSBuildTools.spec.js
@@ -16,7 +16,6 @@
     specific language governing permissions and limitations
     under the License.
 */
-var Q = require('q');
 var shell = require('shelljs');
 var rewire = require('rewire');
 var platformRoot = '../../template';
@@ -33,7 +32,7 @@
 
     var checkMSBuildVersionFake = function (availableVersions, version) {
         var MSBuildTools = buildTools.__get__('MSBuildTools');
-        return (availableVersions.indexOf(version) >= 0) ? Q.resolve(new MSBuildTools(version, fakeToolsPath(version))) : Q.resolve(null);
+        return (availableVersions.indexOf(version) >= 0) ? Promise.resolve(new MSBuildTools(version, fakeToolsPath(version))) : Promise.resolve(null);
     };
 
     var versionTest = function (availableVersions, version) {
@@ -97,7 +96,7 @@
     it('spec.6 should return valid version and path', function () {
         var version = '14.0';
 
-        spawnSpy.and.returnValue(Q.resolve(
+        spawnSpy.and.returnValue(Promise.resolve(
             '\r\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\12.0\r\n\t' +
             'MSBuildToolsPath\tREG_SZ\t' + fakeToolsPath(version) + '\r\n\r\n')
         );
@@ -109,7 +108,7 @@
     });
 
     it('spec.7 should return null if no tools found for version', function () {
-        spawnSpy.and.returnValue(Q.resolve('ERROR: The system was unable to find the specified registry key or value.'));
+        spawnSpy.and.returnValue(Promise.resolve('ERROR: The system was unable to find the specified registry key or value.'));
 
         return checkMSBuildVersion('14.0').then(function (actual) {
             expect(actual).not.toBeDefined();
@@ -117,7 +116,7 @@
     });
 
     it('spec.8 should return null on internal error', function () {
-        spawnSpy.and.returnValue(Q.reject());
+        spawnSpy.and.returnValue(Promise.reject());
 
         return checkMSBuildVersion('14.0').then(function (actual) {
             expect(actual).not.toBeDefined();
@@ -208,7 +207,7 @@
     });
 
     it('should return MSBuildTools instance', function () {
-        spawnSpy.and.returnValue(Q(fakeVersion));
+        spawnSpy.and.returnValue(Promise.resolve(fakeVersion));
 
         return buildTools.getMSBuildToolsAt(fakePath)
             .then(function (tools) {
@@ -219,7 +218,7 @@
     });
 
     it('should reject promise if no msbuild found', function () {
-        spawnSpy.and.returnValue(Q.reject());
+        spawnSpy.and.returnValue(Promise.reject());
 
         return buildTools.getMSBuildToolsAt(messyPath).then(
             () => fail('Expected promise to be rejected'),
diff --git a/spec/unit/build.spec.js b/spec/unit/build.spec.js
index b703c9a..36020e7 100644
--- a/spec/unit/build.spec.js
+++ b/spec/unit/build.spec.js
@@ -16,7 +16,6 @@
     specific language governing permissions and limitations
     under the License.
 */
-var Q = require('q');
 var fs = require('fs');
 var path = require('path');
 var rewire = require('rewire');
@@ -33,14 +32,14 @@
 
 function createFindAvailableVersionMock (version, path, buildSpy) {
     build.__set__('MSBuildTools.findAvailableVersion', function () {
-        return Q.resolve({
+        return Promise.resolve({
             version: version,
             path: path,
             buildProject: function (solutionFile, buildType, buildArch) {
                 if (typeof buildSpy === 'function') {
                     buildSpy(solutionFile, buildType, buildArch);
                 }
-                return Q.reject(); // rejecting here to stop build process
+                return Promise.reject(); // rejecting here to stop build process
             }
         });
     });
@@ -48,7 +47,7 @@
 
 function createFindAllAvailableVersionsMock (versionSet) {
     build.__set__('MSBuildTools.findAllAvailableVersions', function () {
-        return Q.resolve(versionSet);
+        return Promise.resolve(versionSet);
     });
 }
 
@@ -92,7 +91,7 @@
         spyOn(utils, 'isCordovaProject').and.returnValue(true);
         spyOn(prepare, 'applyPlatformConfig');
         spyOn(prepare, 'updateBuildConfig');
-        spyOn(pkg, 'getPackage').and.returnValue(Q({}));
+        spyOn(pkg, 'getPackage').and.returnValue(Promise.resolve({}));
 
         spyOn(AppxManifest, 'get').and.returnValue({
             getIdentity: function () {
@@ -215,19 +214,19 @@
                     switch (buildArch) {
                     case 'arm':
                         armBuild();
-                        return Q();
+                        return Promise.resolve();
                     case 'x86':
                         x86Build();
-                        return Q();
+                        return Promise.resolve();
                     case 'anycpu':
                     case 'any cpu':
                         anyCpuBuild();
-                        return Q();
+                        return Promise.resolve();
                     case 'x64':
                         x64Build();
-                        return Q();
+                        return Promise.resolve();
                     default:
-                        return Q.reject();
+                        return Promise.reject();
                     }
                 }
             }]);
@@ -352,10 +351,10 @@
         delete process.env.MSBUILDDIR;
 
         spyOn(MSBuildTools, 'getMSBuildToolsAt')
-            .and.returnValue(Q({
+            .and.returnValue(Promise.resolve({
                 path: customMSBuildPath,
                 version: customMSBuildVersion,
-                buildProject: jasmine.createSpy('buildProject').and.returnValue(Q())
+                buildProject: jasmine.createSpy('buildProject').and.returnValue(Promise.resolve())
             }));
 
         return build.run({})
@@ -377,10 +376,10 @@
         delete process.env.VSINSTALLDIR;
 
         spyOn(MSBuildTools, 'getMSBuildToolsAt')
-            .and.returnValue(Q({
+            .and.returnValue(Promise.resolve({
                 path: msBuildBinPath,
                 version: customMSBuildVersion,
-                buildProject: jasmine.createSpy('buildProject').and.returnValue(Q())
+                buildProject: jasmine.createSpy('buildProject').and.returnValue(Promise.resolve())
             }));
 
         return build.run({})
@@ -448,7 +447,7 @@
             spyOn(utils, 'isCordovaProject').and.returnValue(true);
             spyOn(prepare, 'applyPlatformConfig');
             spyOn(prepare, 'updateBuildConfig');
-            spyOn(pkg, 'getPackage').and.returnValue(Q({}));
+            spyOn(pkg, 'getPackage').and.returnValue(Promise.resolve({}));
 
             spyOn(AppxManifest, 'get').and.returnValue({
                 getIdentity: function () {
@@ -459,7 +458,7 @@
         });
 
         it('should pass buildFlags directly to MSBuild', function () {
-            var buildTools = { version: '14.0', buildProject: jasmine.createSpy('buildProject').and.returnValue(Q()), path: testPath };
+            var buildTools = { version: '14.0', buildProject: jasmine.createSpy('buildProject').and.returnValue(Promise.resolve()), path: testPath };
             var buildOptions = {
                 argv: ['--buildFlag', 'foo=bar']
             };
diff --git a/spec/unit/check_reqs.spec.js b/spec/unit/check_reqs.spec.js
index e288406..5cf8914 100644
--- a/spec/unit/check_reqs.spec.js
+++ b/spec/unit/check_reqs.spec.js
@@ -17,7 +17,6 @@
     under the License.
 */
 
-var Q = require('q');
 var path = require('path');
 var rewire = require('rewire');
 var binPath = '../../bin';
@@ -74,9 +73,9 @@
 
             checkSpy = jasmine.createSpy('checkSpy');
             fakeCheckFns = [
-                checkSpy.and.returnValue(Q('1.0')),
-                checkSpy.and.returnValue(Q('2.0')),
-                checkSpy.and.returnValue(Q('3.0'))
+                checkSpy.and.returnValue(Promise.resolve('1.0')),
+                checkSpy.and.returnValue(Promise.resolve('2.0')),
+                checkSpy.and.returnValue(Promise.resolve('3.0'))
             ];
             spyOn(xml, 'parseElementtreeSync').and.returnValue(new et.ElementTree(et.XML(TEST_XML)));
             fakeConfig = new ConfigParser('/some/file');
@@ -92,9 +91,7 @@
             check_reqs.__set__('requirements', fakeRequirements);
             check_reqs.__set__('checkFns', fakeCheckFns);
             check_reqs.__set__('config', fakeConfig);
-            var checkResult = check_reqs.check_all();
-            expect(Q.isPromise(checkResult)).toBeTruthy();
-            return checkResult.then(function (result) {
+            return check_reqs.check_all().then(function (result) {
                 expect(result instanceof Array).toBeTruthy();
                 expect(result.length).toBe(3);
                 result.forEach(function (resultItem) {
@@ -106,7 +103,7 @@
 
         it('Test #003 : that should not reject if one of requirements is not installed', function () {
             check_reqs.__set__('requirements', fakeRequirements);
-            fakeCheckFns[0] = function () { return Q.reject('Error message'); };
+            fakeCheckFns[0] = function () { return Promise.reject('Error message'); };
             check_reqs.__set__('checkFns', fakeCheckFns);
             check_reqs.__set__('config', fakeConfig);
 
@@ -132,7 +129,7 @@
         it('Test #005 : that should not run other requirements checks if `fatal` requirement isn\'t installed', function () {
             check_reqs.__set__('requirements', fakeRequirements);
             // The second requirement is fatal, so we're setting up second check to fail
-            fakeCheckFns[1] = checkSpy.and.returnValue(Q.reject('Error message'));
+            fakeCheckFns[1] = checkSpy.and.returnValue(Promise.reject('Error message'));
             check_reqs.__set__('checkFns', fakeCheckFns);
             check_reqs.__set__('config', fakeConfig);
 
diff --git a/spec/unit/deployment.spec.js b/spec/unit/deployment.spec.js
index 8c4517a..f613a2f 100644
--- a/spec/unit/deployment.spec.js
+++ b/spec/unit/deployment.spec.js
@@ -19,7 +19,6 @@
 
 var rewire = require('rewire');
 var deployment = rewire('../../template/cordova/lib/deployment');
-var Q = require('q');
 var path = require('path');
 var AppDeployCmdTool = deployment.__get__('AppDeployCmdTool');
 var WinAppDeployCmdTool = deployment.__get__('WinAppDeployCmdTool');
@@ -59,18 +58,18 @@
         switch (args[0]) {
         case 'devices':
             var output = 'Windows App Deployment Tool\r\nVersion 10.0.0.0\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\n\r\nDiscovering devices...\r\nIP Address      GUID                                    Model/Name\r\n127.0.0.1   00000015-b21e-0da9-0000-000000000000    Lumia 1520 (RM-940)\r\n10.120.70.172   00000000-0000-0000-0000-00155d619532    00155D619532\r\n10.120.68.150   00000000-0000-0000-0000-00155d011765    00155D011765\r\nDone.';
-            return Q(output);
+            return Promise.resolve(output);
 
         case 'update':
         case 'install':
             expect(args[2]).toBe(TEST_APP_PACKAGE_NAME);
             expect(args[4]).toBe('127.0.0.1');
-            return Q('');
+            return Promise.resolve('');
 
         case 'uninstall':
             expect(args[2]).toBe(TEST_APP_PACKAGE_ID);
             expect(args[4]).toBe('10.120.68.150');
-            return Q('');
+            return Promise.resolve('');
         }
     }
 
@@ -133,7 +132,7 @@
         switch (args[0]) {
         case '/EnumerateDevices':
             var output = '\r\nDevice Index    Device Name\r\n------------    -------------------------------\r\n 0              Device\r\n 1              Mobile Emulator 10.0.10150.0 WVGA 4 inch 512MB\r\n 2              Mobile Emulator 10.0.10150.0 WVGA 4 inch 1GB\r\n 3              Mobile Emulator 10.0.10150.0 WXGA 4.5 inch 1GB\r\n 4              Mobile Emulator 10.0.10150.0 720p 5 inch 1GB\r\n 5              Mobile Emulator 10.0.10150.0 1080p 6 inch 2GB\r\n 6              Emulator 8.1 WVGA 4 inch 512MB\r\n 7              Emulator 8.1 WVGA 4 inch\r\n 8              Emulator 8.1 WXGA 4.5 inch\r\n 9              Emulator 8.1 720P 4.7 inch\r\n 10             Emulator 8.1 1080P 5.5 inch\r\n 11             Emulator 8.1 1080P 6 inch\r\nDone.\r\n';
-            return Q(output);
+            return Promise.resolve(output);
 
         case '/update':
         case '/install':
@@ -141,12 +140,12 @@
         case '/installlaunch':
             expect(args[1]).toBe(TEST_APP_PACKAGE_NAME);
             expect(args[2]).toBe('/targetdevice:de');
-            return Q('');
+            return Promise.resolve('');
 
         case '/uninstall':
             expect(args[1]).toBe(TEST_APP_PACKAGE_ID);
             expect(args[2]).toBe('/targetdevice:5');
-            return Q('');
+            return Promise.resolve('');
 
         default:
             throw new Error('Unrecognized AppDeployCmd parameter "' + args[0] + '"');
diff --git a/spec/unit/run.spec.js b/spec/unit/run.spec.js
index c8c729f..9a886f8 100644
--- a/spec/unit/run.spec.js
+++ b/spec/unit/run.spec.js
@@ -17,7 +17,6 @@
     under the License.
 */
 
-var Q = require('q');
 var path = require('path');
 var rewire = require('rewire');
 var platformRoot = '../../template';
@@ -74,7 +73,7 @@
         run.__set__('utils.isCordovaProject', isCordovaProjectFalse);
         run.__set__('build.run', function () {
             buildRun();
-            return Q.reject(); // rejecting to break run chain
+            return Promise.reject(); // rejecting to break run chain
         });
 
         return run.run(['node', buildPath]).then(
@@ -89,7 +88,7 @@
         run.__set__('utils.isCordovaProject', isCordovaProjectTrue);
         run.__set__('build.run', function () {
             buildRun();
-            return Q.reject(); // rejecting to break run chain
+            return Promise.reject(); // rejecting to break run chain
         });
 
         return run.run({ release: true, debug: true }).then(
@@ -104,7 +103,7 @@
         run.__set__('utils.isCordovaProject', isCordovaProjectTrue);
         run.__set__('build.run', function () {
             buildRun();
-            return Q.reject(); // rejecting to break run chain
+            return Promise.reject(); // rejecting to break run chain
         });
 
         return run.run({ device: true, emulator: true }).then(
@@ -119,7 +118,7 @@
         run.__set__('utils.isCordovaProject', isCordovaProjectTrue);
         run.__set__('build.run', function () {
             buildRun();
-            return Q.reject(); // rejecting to break run chain
+            return Promise.reject(); // rejecting to break run chain
         });
 
         return run.run({ device: true, target: 'sometargethere' }).then(
@@ -145,21 +144,21 @@
                 script: 'testfile.ps1',
                 phoneId: 'undefined'
             };
-            return Q(buildResult);
+            return Promise.resolve(buildResult);
         });
         run.__set__('packages.getPackage', function () {
-            return Q({
+            return Promise.resolve({
                 type: 'phone',
                 file: 'testfile'
             });
         });
         run.__set__('packages.deployToPhone', function () {
             deployToPhone();
-            return Q();
+            return Promise.resolve();
         });
         run.__set__('packages.deployToDesktop', function () {
             deployToDesktop();
-            return Q();
+            return Promise.resolve();
         });
 
         return run.run(['node', buildPath, '--phone', '--break'])
@@ -187,21 +186,21 @@
                 script: 'testfile.ps1',
                 phoneId: 'undefined'
             };
-            return Q(buildResult);
+            return Promise.resolve(buildResult);
         });
         run.__set__('packages.getPackage', function () {
-            return Q({
+            return Promise.resolve({
                 type: 'windows',
                 file: 'testfile'
             });
         });
         run.__set__('packages.deployToPhone', function () {
             deployToPhone();
-            return Q();
+            return Promise.resolve();
         });
         run.__set__('packages.deployToDesktop', function () {
             deployToDesktop();
-            return Q();
+            return Promise.resolve();
         });
 
         return run.run(['node', buildPath])
@@ -219,17 +218,17 @@
         run.__set__('utils.isCordovaProject', isCordovaProjectTrue);
         run.__set__('build.run', function () {
             build();
-            return Q.reject(); // rejecting to break run chain
+            return Promise.reject(); // rejecting to break run chain
         });
         run.__set__('packages.getPackage', function () {
-            return Q({
+            return Promise.resolve({
                 type: 'windows',
                 file: 'testfile'
             });
         });
         run.__set__('packages.deployToDesktop', function () {
             deployToDesktop();
-            return Q();
+            return Promise.resolve();
         });
 
         return run.run({ nobuild: true })
@@ -241,8 +240,8 @@
 
     it('spec.8 should accept --archs parameter either as cli or as platform arg', function () {
         spyOn(utils, 'isCordovaProject').and.returnValue(true);
-        spyOn(packages, 'getPackage').and.returnValue(Q({ arch: 'arm' }));
-        spyOn(packages, 'deployToDesktop').and.returnValue(Q());
+        spyOn(packages, 'getPackage').and.returnValue(Promise.resolve({ arch: 'arm' }));
+        spyOn(packages, 'deployToDesktop').and.returnValue(Promise.resolve());
 
         var anyString = jasmine.any(String);
         var expectedDeployOptions = jasmine.objectContaining({ arch: 'arm' });
@@ -263,8 +262,8 @@
 
     it('spec.9 should fall back to anycpu if --archs parameter is not specified', function () {
         spyOn(utils, 'isCordovaProject').and.returnValue(true);
-        spyOn(packages, 'getPackage').and.returnValue(Q({ arch: 'anycpu' }));
-        spyOn(packages, 'deployToDesktop').and.returnValue(Q());
+        spyOn(packages, 'getPackage').and.returnValue(Promise.resolve({ arch: 'anycpu' }));
+        spyOn(packages, 'deployToDesktop').and.returnValue(Promise.resolve());
 
         var anyString = jasmine.any(String);
         var expectedDeployOptions = jasmine.objectContaining({ arch: 'anycpu' });
diff --git a/template/cordova/Api.js b/template/cordova/Api.js
index c316444..98d3c53 100644
--- a/template/cordova/Api.js
+++ b/template/cordova/Api.js
@@ -223,7 +223,7 @@
         })
         // CB-11022 return non-falsy value to indicate
         // that there is no need to run prepare after
-        .thenResolve(true);
+        .then(() => true);
 };
 
 /**
@@ -260,7 +260,7 @@
         })
         // CB-11022 return non-falsy value to indicate
         // that there is no need to run prepare after
-        .thenResolve(true);
+        .then(() => true);
 };
 
 /**
diff --git a/template/cordova/build b/template/cordova/build
index 0d5137c..2d2a508 100644
--- a/template/cordova/build
+++ b/template/cordova/build
@@ -82,4 +82,7 @@
 
 require('./lib/loggingHelper').adjustLoggerLevel(buildOpts);
 
-new Api().build(buildOpts).done();
+new Api().build(buildOpts).catch(err => {
+    console.error(err);
+    process.exit(2);
+});
diff --git a/template/cordova/lib/MSBuildTools.js b/template/cordova/lib/MSBuildTools.js
index 625379d..d4d9320 100644
--- a/template/cordova/lib/MSBuildTools.js
+++ b/template/cordova/lib/MSBuildTools.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var path = require('path');
 var fs = require('fs');
 var shell = require('shelljs');
@@ -116,7 +115,7 @@
     var versions = ['15.9', '15.5', '15.0', '14.0', '12.0', '4.0'];
     events.emit('verbose', 'Searching for available MSBuild versions...');
 
-    return Q.all(versions.map(checkMSBuildVersion)).then(function (unprocessedResults) {
+    return Promise.all(versions.map(checkMSBuildVersion)).then(function (unprocessedResults) {
         return unprocessedResults.filter(function (item) {
             return !!item;
         });
@@ -128,12 +127,12 @@
 module.exports.findAvailableVersion = function () {
     var versions = ['15.5', '15.0', '14.0', '12.0', '4.0'];
 
-    return Q.all(versions.map(checkMSBuildVersion)).then(function (versions) {
+    return Promise.all(versions.map(checkMSBuildVersion)).then(function (versions) {
         // console.log('findAvailableVersion', versions);
         // select first msbuild version available, and resolve promise with it
         var msbuildTools = versions[0] || versions[1] || versions[2] || versions[3] || versions[4];
 
-        return msbuildTools ? Q.resolve(msbuildTools) : Q.reject('MSBuild tools not found');
+        return msbuildTools ? Promise.resolve(msbuildTools) : Promise.reject('MSBuild tools not found');
     });
 };
 
diff --git a/template/cordova/lib/build.js b/template/cordova/lib/build.js
index e40deda..22c89b9 100644
--- a/template/cordova/lib/build.js
+++ b/template/cordova/lib/build.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var path = require('path');
 var nopt = require('nopt');
 var shell = require('shelljs');
@@ -51,7 +50,7 @@
     ROOT = this.root || ROOT;
 
     if (!utils.isCordovaProject(this.root)) {
-        return Q.reject(new CordovaError('Could not find project at ' + this.root));
+        return Promise.reject(new CordovaError('Could not find project at ' + this.root));
     }
 
     var buildConfig = parseAndValidateArgs(buildOptions);
@@ -78,7 +77,7 @@
             events.emit('verbose', ' BUILD OUTPUT: ' + pkg.appx);
             return pkg;
         }).catch(function (error) {
-            return Q.reject(new CordovaError('Build failed', error));
+            return Promise.reject(new CordovaError('Build failed', error));
         });
 };
 
@@ -385,7 +384,7 @@
 
             return msbuild.buildProject(path.join(ROOT, build.target), config.buildType, build.arch, otherProperties);
         });
-    }, Q());
+    }, Promise.resolve());
 
     if (shouldBundle) {
         return buildsCompleted.then(function () {
@@ -453,5 +452,5 @@
         .forEach(function (dir) {
             shell.rm('-rf', path.join(projectPath, dir));
         });
-    return Q.resolve();
+    return Promise.resolve();
 };
diff --git a/template/cordova/lib/clean.js b/template/cordova/lib/clean.js
index 12fa06d..ee9fc0e 100644
--- a/template/cordova/lib/clean.js
+++ b/template/cordova/lib/clean.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var path = require('path');
 var shell = require('shelljs');
 
@@ -29,5 +28,5 @@
     ['AppPackages', 'build'].forEach(function (dir) {
         shell.rm('-rf', path.join(projectPath, dir));
     });
-    return Q.resolve();
+    return Promise.resolve();
 };
diff --git a/template/cordova/lib/deployment.js b/template/cordova/lib/deployment.js
index ba9ace0..8f4b989 100644
--- a/template/cordova/lib/deployment.js
+++ b/template/cordova/lib/deployment.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var fs = require('fs');
 var path = require('path');
 var spawn = require('cordova-common').superspawn.spawn;
@@ -44,7 +43,7 @@
  *    specific to the deployment tool which created them and are likely used internally.
  */
 DeploymentTool.prototype.enumerateDevices = function () {
-    return Q.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
+    return Promise.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
 };
 
 /**
@@ -57,7 +56,7 @@
  * @pin Optionally provided if the device requires pairing for deployment.
  */
 DeploymentTool.prototype.installAppPackage = function (pathToAppxPackage, targetDevice, shouldLaunch, shouldUpdate, pin) {
-    return Q.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
+    return Promise.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
 };
 
 /**
@@ -67,7 +66,7 @@
  * @param targetDevice An object returned from a successful call to enumerateDevices.
  */
 DeploymentTool.prototype.uninstallAppPackage = function (packageInfo, targetDevice) {
-    return Q.reject('Unable to uninstall any app packages because that feature is not supported.');
+    return Promise.reject('Unable to uninstall any app packages because that feature is not supported.');
 };
 
 /**
@@ -77,7 +76,7 @@
  * @returns A Promise for an array of app names.
  */
 DeploymentTool.prototype.getInstalledApps = function (targetDevice) {
-    return Q.reject('Unable to get installed apps because that feature is not supported.');
+    return Promise.reject('Unable to get installed apps because that feature is not supported.');
 };
 
 /**
@@ -87,7 +86,7 @@
  * @returns A Promise for when the app is launched.
  */
 DeploymentTool.prototype.launchApp = function (packageInfo, targetDevice) {
-    return Q.reject('Unable to launch an app because that feature is not supported.');
+    return Promise.reject('Unable to launch an app because that feature is not supported.');
 };
 
 /**
diff --git a/template/cordova/lib/package.js b/template/cordova/lib/package.js
index a097884..fd3306e 100644
--- a/template/cordova/lib/package.js
+++ b/template/cordova/lib/package.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var fs = require('fs');
 var path = require('path');
 var utils = require('./utils');
@@ -32,7 +31,7 @@
     var appPackages = path.resolve(path.join(__dirname, '..', '..', 'AppPackages'));
     // reject promise if AppPackages folder doesn't exist
     if (!fs.existsSync(appPackages)) {
-        return Q.reject('AppPackages folder doesn\'t exist');
+        return Promise.reject('AppPackages folder doesn\'t exist');
     }
     // find out and resolve paths for all folders inside AppPackages
     var pkgDirs = fs.readdirSync(appPackages).map(function (relative) {
@@ -62,13 +61,13 @@
                 (pkgInfo.archs && pkgInfo.archs.indexOf(buildArch) > -1))) {
                 // if package's properties match properties provided
                 // resolve the promise with this package's info
-                return Q.resolve(pkgInfo);
+                return Promise.resolve(pkgInfo);
             }
         }
     }
 
     // reject because seems that no corresponding packages found
-    return Q.reject('Package with specified parameters not found in AppPackages folder');
+    return Promise.reject('Package with specified parameters not found in AppPackages folder');
 };
 
 function getPackagePhoneProductId (packageFile) {
@@ -117,10 +116,10 @@
     // because the function is only used for desktop deployment, which always has the same
     // package name when uninstalling / reinstalling
     try {
-        return Q.when(AppxManifest.get(path.join(platformPath, 'package.windows.appxmanifest'))
+        return Promise.resolve(AppxManifest.get(path.join(platformPath, 'package.windows.appxmanifest'))
             .getIdentity().getName());
     } catch (e) {
-        return Q.reject('Can\'t read package name from manifest ' + e);
+        return Promise.reject('Can\'t read package name from manifest ' + e);
     }
 }
 
@@ -140,11 +139,11 @@
             for (var idx in sortedList) {
                 if (sortedList[idx].toString().toLowerCase().indexOf(target) > -1) {
                     // we should return index based on original list
-                    return Q.resolve(sortedList[idx]);
+                    return Promise.resolve(sortedList[idx]);
                 }
             }
         } else if (target === 'device') {
-            return Q.resolve(deviceList[0]);
+            return Promise.resolve(deviceList[0]);
         } else {
             var candidateList = deviceList.filter(function (device) {
                 if (device.index === parseInt(target, 10)) {
@@ -160,7 +159,7 @@
                 return candidateList[0];
             }
         }
-        return Q.reject('Specified device not found');
+        return Promise.reject('Specified device not found');
     });
 };
 
@@ -184,7 +183,7 @@
 module.exports.deployToPhone = function (pkg, deployTarget, targetWindows10, deploymentTool) {
     var deployment;
     if (deploymentTool) {
-        deployment = Q(deploymentTool);
+        deployment = Promise.resolve(deploymentTool);
     } else {
         deployment = utils.getAppDeployUtils(targetWindows10);
     }
@@ -216,7 +215,7 @@
 // deploys specified package to desktop
 module.exports.deployToDesktop = function (pkg, deployTarget) {
     if (deployTarget !== 'device' && deployTarget !== 'emulator') {
-        return Q.reject('Deploying desktop apps to specific target not supported');
+        return Promise.reject('Deploying desktop apps to specific target not supported');
     }
 
     return utils.getAppStoreUtils().then(function (appStoreUtils) {
diff --git a/template/cordova/lib/prepare.js b/template/cordova/lib/prepare.js
index 1538848..5dca0c4 100644
--- a/template/cordova/lib/prepare.js
+++ b/template/cordova/lib/prepare.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var fs = require('fs');
 var path = require('path');
 var shell = require('shelljs');
@@ -606,7 +605,7 @@
     AppxManifest.purgeCache();
 
     // Update own www dir with project's www assets and plugins' assets and js-files
-    return Q.when(updateWww(cordovaProject, this.locations))
+    return Promise.resolve(updateWww(cordovaProject, this.locations))
         .then(function () {
             // update project according to config.xml changes.
             return updateProjectAccordingTo(self._config, self.locations);
@@ -636,13 +635,13 @@
     var projectConfigFile = path.join(projectRoot, 'config.xml');
     if ((options && options.noPrepare) || !fs.existsSync(projectConfigFile) ||
             !fs.existsSync(this.locations.configXml)) {
-        return Q();
+        return Promise.resolve();
     }
 
     var projectConfig = new ConfigParser(this.locations.configXml);
 
     var self = this;
-    return Q().then(function () {
+    return Promise.resolve().then(function () {
         cleanWww(projectRoot, self.locations);
         cleanImages(projectRoot, projectConfig, self.locations);
     });
diff --git a/template/cordova/lib/run.js b/template/cordova/lib/run.js
index 5e7f148..4859420 100644
--- a/template/cordova/lib/run.js
+++ b/template/cordova/lib/run.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var nopt = require('nopt');
 var build = require('./build');
 var utils = require('./utils');
@@ -28,13 +27,13 @@
 
 module.exports.run = function (options) {
     if (!utils.isCordovaProject(this.root)) {
-        return Q.reject(new CordovaError('Could not find project at ' + this.root));
+        return Promise.reject(new CordovaError('Could not find project at ' + this.root));
     }
 
     // Check if ran from admin prompt and fail quickly if CLI has administrative permissions
     // http://stackoverflow.com/a/11995662/64949
     if (ranWithElevatedPermissions()) {
-        return Q.reject(new CordovaError('Can not run this platform with administrative ' +
+        return Promise.reject(new CordovaError('Can not run this platform with administrative ' +
             'permissions. Must be run from a non-admin prompt.'));
     }
 
@@ -49,13 +48,13 @@
 
     // Validate args
     if (options.debug && options.release) {
-        return Q.reject(new CordovaError('Only one of "debug"/"release" options should be specified'));
+        return Promise.reject(new CordovaError('Only one of "debug"/"release" options should be specified'));
     }
     if ((options.device && options.emulator) || ((options.device || options.emulator) && options.target)) {
-        return Q.reject(new CordovaError('Only one of "device"/"emulator"/"target" options should be specified'));
+        return Promise.reject(new CordovaError('Only one of "device"/"emulator"/"target" options should be specified'));
     }
     if (args.phone && args.win) {
-        return Q.reject(new CordovaError('Only one of "phone"/"win" options should be specified'));
+        return Promise.reject(new CordovaError('Only one of "phone"/"win" options should be specified'));
     }
 
     // Get build/deploy options
@@ -71,7 +70,7 @@
     var buildTargets = build.getBuildTargets(args.win, args.phone, args.appx);
 
     if (!buildTargets || buildTargets.length <= 0) {
-        return Q.reject(new CordovaError('Unable to determine deploy target.'));
+        return Promise.reject(new CordovaError('Unable to determine deploy target.'));
     }
 
     // we deploy the first build target so we use buildTargets[0] to determine
@@ -90,7 +89,7 @@
                 return packages.deployToPhone(pkg, deployTarget, args.win10tools)
                     .catch(function (e) {
                         if (options.target || options.emulator || options.device) {
-                            return Q.reject(e); // Explicit target, carry on
+                            return Promise.reject(e); // Explicit target, carry on
                         }
                         // 'device' was inferred initially, because no target was specified
                         return packages.deployToPhone(pkg, 'emulator', args.win10tools);
diff --git a/template/cordova/lib/utils.js b/template/cordova/lib/utils.js
index 8c9b400..20d144e 100644
--- a/template/cordova/lib/utils.js
+++ b/template/cordova/lib/utils.js
@@ -17,7 +17,6 @@
        under the License.
 */
 
-var Q = require('q');
 var fs = require('fs');
 var path = require('path');
 var spawn = require('cordova-common').superspawn.spawn;
@@ -28,10 +27,10 @@
 module.exports.getAppStoreUtils = function () {
     var appStoreUtils = path.join(__dirname, 'WindowsStoreAppUtils.ps1');
     if (!fs.existsSync(appStoreUtils)) {
-        return Q.reject('Can\'t unblock AppStoreUtils script');
+        return Promise.reject('Can\'t unblock AppStoreUtils script');
     }
     return spawn('powershell', ['Unblock-File', module.exports.quote(appStoreUtils)], { stdio: 'ignore' })
-        .thenResolve(appStoreUtils);
+        .then(() => appStoreUtils);
 };
 
 // returns path to AppDeploy util from Windows Phone 8.1 SDK
@@ -40,10 +39,10 @@
     var tool = DeploymentTool.getDeploymentTool(version);
 
     if (!tool.isAvailable()) {
-        return Q.reject('App deployment utilities: "' + tool.path + '", not found.  Ensure the Windows SDK is installed.');
+        return Promise.reject('App deployment utilities: "' + tool.path + '", not found.  Ensure the Windows SDK is installed.');
     }
 
-    return Q.resolve(tool);
+    return Promise.resolve(tool);
 };
 
 // checks to see if a .jsproj file exists in the project root
diff --git a/template/cordova/log b/template/cordova/log
index 9eefa2d..07f9877 100644
--- a/template/cordova/log
+++ b/template/cordova/log
@@ -20,11 +20,10 @@
 */
 
 var log = require('./lib/log');
-var Q = require('q');
 var args = process.argv;
 
 // Usage support for when args are given
-Q().then(function () {
+Promise.resolve().then(function () {
     var argsToPass = [];
     if (args.length > 2) {
         argsToPass = args.slice(2);
diff --git a/template/cordova/run b/template/cordova/run
index 52cdcd5..308ec8d 100644
--- a/template/cordova/run
+++ b/template/cordova/run
@@ -79,4 +79,7 @@
 
 require('./lib/loggingHelper').adjustLoggerLevel(runOpts);
 
-new Api().run(runOpts).done();
+new Api().run(runOpts).catch(err => {
+    console.error(err);
+    process.exit(2);
+});