diff --git a/lib/classes/CLI.js b/lib/classes/CLI.js index 09c0daec371..665ab56ca00 100644 --- a/lib/classes/CLI.js +++ b/lib/classes/CLI.js @@ -1,8 +1,6 @@ 'use strict'; const version = require('../../package.json').version; -const enterpriseVersion = require('@serverless/enterprise-plugin/package.json').version; -const { sdkVersion } = require('@serverless/enterprise-plugin'); const _ = require('lodash'); const os = require('os'); const chalk = require('chalk'); @@ -89,10 +87,6 @@ class CLI { switch (commands.length) { case 0: - if (options.version || options.v) { - this.getVersionNumber(); - return true; - } if (options['help-interactive']) { this.generateInteractiveCliHelp(); return true; @@ -100,10 +94,6 @@ class CLI { this.generateMainHelp(); return true; case 1: - if (commands[0] === 'version') { - this.getVersionNumber(); - return true; - } if (commands[0] === 'help') { this.generateMainHelp(); return true; @@ -358,33 +348,6 @@ functionalities related to given service or current environment.` return null; } - getVersionNumber() { - const installationModePostfix = (() => { - if (this.serverless.isStandaloneExecutable) return ' (standalone)'; - if (this.serverless.isLocallyInstalled) return ' (local)'; - return ''; - })(); - - this.consoleLog( - `Framework Core: ${version}${installationModePostfix}\n` + - `Plugin: ${enterpriseVersion}\n` + - `SDK: ${sdkVersion}` - ); - - const userNodeVersion = Number(process.version.split('.')[0].slice(1)); - // only show components version if user is running Node 8+ - if (userNodeVersion >= 8) { - const componentsVersion = (() => { - try { - return require('@serverless/components/package').version; - } catch (error) { - return 'Unavailable'; - } - })(); - this.consoleLog(`Components: ${componentsVersion}`); - } - } - asciiGreeting() { let art = ''; art = `${art} _______ __${os.EOL}`; diff --git a/lib/cli/eventually-list-version.js b/lib/cli/eventually-list-version.js new file mode 100644 index 00000000000..aa629cf2a44 --- /dev/null +++ b/lib/cli/eventually-list-version.js @@ -0,0 +1,39 @@ +'use strict'; + +const path = require('path'); +const { version } = require('../../package'); +const { version: dashboardPluginVersion } = require('@serverless/enterprise-plugin/package'); +const { version: componentsVersion } = require('@serverless/components/package'); +const { sdkVersion } = require('@serverless/enterprise-plugin'); +const isStandaloneExecutable = require('../utils/isStandaloneExecutable'); +const resolveLocalServerlessPath = require('./resolve-local-serverless-path'); + +const serverlessPath = path.resolve(__dirname, '../Serverless.js'); + +module.exports = async () => { + const cliParams = new Set(process.argv.slice(2)); + if (!cliParams.has('--version')) { + // Ideally we should output version info in whatever context "--version" or "-v" params + // are used. Still "-v" is defined also as a "--verbose" alias in some commands. + // Support for "--verbose" is expected to go away with + // https://github.com/serverless/serverless/issues/1720 + // Until that's addressed we can recognize "-v" only as top-level param + if (cliParams.size !== 1) return false; + if (!cliParams.has('-v')) return false; + } + + const installationModePostfix = await (async () => { + if (isStandaloneExecutable) return ' (standalone)'; + if (serverlessPath === (await resolveLocalServerlessPath())) return ' (local)'; + return ''; + })(); + + process.stdout.write( + `Framework Core: ${version}${installationModePostfix}\n` + + `Plugin: ${dashboardPluginVersion}\n` + + `SDK: ${sdkVersion}\n` + + `Components: ${componentsVersion}\n` + ); + + return true; +}; diff --git a/scripts/serverless.js b/scripts/serverless.js index 60dc613fc85..c17deaabb9b 100755 --- a/scripts/serverless.js +++ b/scripts/serverless.js @@ -32,6 +32,8 @@ const processSpanPromise = (async () => { serverlessExecutionSpan: processSpanPromise, }); + if (await require('../lib/cli/eventually-list-version')()) return; + const uuid = require('uuid'); const invocationId = uuid.v4(); diff --git a/test/unit/lib/classes/CLI.test.js b/test/unit/lib/classes/CLI.test.js index f86b8d55ad0..ff5855f90e7 100644 --- a/test/unit/lib/classes/CLI.test.js +++ b/test/unit/lib/classes/CLI.test.js @@ -230,30 +230,6 @@ describe('CLI', () => { expect(helpDisplayed).to.equal(true); }); - it('should return true when the "version" parameter is given', () => { - cli = new CLI(serverless, ['version']); - const processedInput = cli.processInput(); - const helpDisplayed = cli.displayHelp(processedInput); - - expect(helpDisplayed).to.equal(true); - }); - - it('should return true when the "--version" parameter is given', () => { - cli = new CLI(serverless, ['--version']); - const processedInput = cli.processInput(); - const helpDisplayed = cli.displayHelp(processedInput); - - expect(helpDisplayed).to.equal(true); - }); - - it('should return true when the "-v" parameter is given', () => { - cli = new CLI(serverless, ['-v']); - const processedInput = cli.processInput(); - const helpDisplayed = cli.displayHelp(processedInput); - - expect(helpDisplayed).to.equal(true); - }); - it('should return true when the "-h" parameter is given with a command', () => { cli = new CLI(serverless, ['test', '-h']); serverless.cli = cli; @@ -332,7 +308,7 @@ describe('CLI', () => { expect(helpDisplayed).to.equal(true); }); - it('should return false if no "help" or "version" related command / option is given', () => { + it('should return false if no "help" related command / option is given', () => { cli = new CLI(serverless, ['test']); serverless.cli = cli; class PluginMock { @@ -430,32 +406,6 @@ describe('CLI', () => { }); }); - describe('#getVersionNumber()', () => { - let consoleLogSpy; - - beforeEach(() => { - cli = new CLI(serverless); - consoleLogSpy = sinon.spy(cli, 'consoleLog'); - }); - - afterEach(() => { - cli.consoleLog.restore(); - }); - - it('should log the version numbers', () => { - cli.getVersionNumber(); - - expect(consoleLogSpy.args[0][0]).to.include('Framework Core'); - expect(consoleLogSpy.args[0][0]).to.include('Plugin'); - expect(consoleLogSpy.args[0][0]).to.include('SDK'); - - const userNodeVersion = Number(process.version.split('.')[0].slice(1)); - if (userNodeVersion >= 8) { - expect(consoleLogSpy.args[1][0]).to.include('Components'); - } - }); - }); - describe('#processInput()', () => { it('should only return the commands when only commands are given', () => { cli = new CLI(serverless, ['deploy', 'functions']); @@ -669,30 +619,6 @@ describe('CLI [new tests]', () => { expect(stdoutData).to.include('Documentation: http://slss.io/docs'); })); - it('Should show version when requested and no commands are used', () => - runServerless({ - fixture: 'function', - cliArgs: ['-v'], - }).then(({ stdoutData }) => { - expect(stdoutData).to.include('Framework Core: '); - })); - - it('Should not show version with command', () => - runServerless({ - fixture: 'customProvider', - cliArgs: ['info', '-v'], - }) - .then(({ stdoutData }) => { - expect(stdoutData).to.not.include('Framework Core: '); - return runServerless({ - fixture: 'customProvider', - cliArgs: ['info', '--version'], - }); - }) - .then(({ stdoutData }) => { - expect(stdoutData).to.not.include('Framework Core: '); - })); - it('Should handle incomplete command configurations', async () => { const { stdoutData } = await runServerless({ fixture: 'plugin', diff --git a/test/unit/lib/cli/eventually-list-version.test.js b/test/unit/lib/cli/eventually-list-version.test.js new file mode 100644 index 00000000000..066fecff3b3 --- /dev/null +++ b/test/unit/lib/cli/eventually-list-version.test.js @@ -0,0 +1,81 @@ +'use strict'; + +const { expect } = require('chai'); +const overrideStdoutWrite = require('process-utils/override-stdout-write'); +const overrideArgv = require('process-utils/override-argv'); +const eventuallyListVersion = require('../../../../lib/cli/eventually-list-version'); + +describe('test/unit/lib/cli/eventually-list-version.test.js', () => { + it('should log version on top level --version param', async () => { + let stdoutData = ''; + expect( + await overrideArgv({ args: ['serverless', '--version'] }, () => + overrideStdoutWrite( + (data) => (stdoutData += data), + () => eventuallyListVersion() + ) + ) + ).to.equal(true); + expect(stdoutData).to.have.string('Framework Core: '); + }); + it('should log version on deep --version param', async () => { + let stdoutData = ''; + expect( + await overrideArgv({ args: ['serverless', 'deploy', 'function', '--version'] }, () => + overrideStdoutWrite( + (data) => (stdoutData += data), + () => eventuallyListVersion() + ) + ) + ).to.equal(true); + expect(stdoutData).to.have.string('Framework Core: '); + }); + it('should log version on top level -v param', async () => { + let stdoutData = ''; + expect( + await overrideArgv({ args: ['serverless', '-v'] }, () => + overrideStdoutWrite( + (data) => (stdoutData += data), + () => eventuallyListVersion() + ) + ) + ).to.equal(true); + expect(stdoutData).to.have.string('Framework Core: '); + }); + it('should not log version on deep -v param', async () => { + let stdoutData = ''; + expect( + await overrideArgv({ args: ['serverless', 'deploy', 'function', '-v'] }, () => + overrideStdoutWrite( + (data) => (stdoutData += data), + () => eventuallyListVersion() + ) + ) + ).to.equal(false); + expect(stdoutData).to.equal(''); + }); + it('should not log version when no params', async () => { + let stdoutData = ''; + expect( + await overrideArgv({ args: ['serverless'] }, () => + overrideStdoutWrite( + (data) => (stdoutData += data), + () => eventuallyListVersion() + ) + ) + ).to.equal(false); + expect(stdoutData).to.equal(''); + }); + it('should not log version when no version params', async () => { + let stdoutData = ''; + expect( + await overrideArgv({ args: ['serverless', 'deploy', 'function'] }, () => + overrideStdoutWrite( + (data) => (stdoutData += data), + () => eventuallyListVersion() + ) + ) + ).to.equal(false); + expect(stdoutData).to.equal(''); + }); +});