Skip to content

Commit

Permalink
feat(system): add os and version to System class (#602)
Browse files Browse the repository at this point in the history
no issue

- added a new getter to the System class, that returns the operating system as well as the version
- works for linux, mac, and windows. Everything else falls back to the native `os.platform()` fn.
- prints the os and the version in the debug information
- added tests
- updated issue template
  • Loading branch information
aileen authored and acburdine committed Feb 4, 2018
1 parent ca68049 commit bd24652
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE.md
Expand Up @@ -40,7 +40,7 @@ Paste log file here

This is automatically output by Ghost-CLI if an error occurs, please copy & paste:

* OS (add version):
* OS:
* Node Version:
* Ghost-CLI Version:
* Environment:
Expand Down
1 change: 1 addition & 0 deletions lib/commands/doctor/checks/system-stack.js
Expand Up @@ -12,6 +12,7 @@ function systemStack(ctx, task) {
if (!ctx.system.platform.linux) {
promise = Promise.reject({message: 'Operating system is not Linux'});
} else {
// TODO: refactor to use ctx.system.operatingSystem
promise = execa.shell('lsb_release -a').catch(
() => Promise.reject({message: 'Linux version is not Ubuntu 16'})
).then((result) => {
Expand Down
18 changes: 18 additions & 0 deletions lib/system.js
Expand Up @@ -73,6 +73,24 @@ class System {
return this._globalConfig;
}

/**
* Returns the running operating system
*
* @property operatingSystem
* @type Object
* @public
*/
get operatingSystem() {
if (!this._operatingSystem) {
const getOS = require('./utils/get-os');
this._operatingSystem = getOS(this.platform);

return this._operatingSystem;
}

return this._operatingSystem;
}

/**
* Constructs the System class
*
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/index.js
Expand Up @@ -400,14 +400,15 @@ class UI {
/**
* Helper method to format the debug information whenever an error occurs
*
* @param {Syste} system System instance
* @param {System} system System instance
* @return string Formated debug info
*
* @method _formatString
* @private
*/
_formatDebug(system) {
return 'Debug Information:\n' +
` OS: ${system.operatingSystem.os}, v${system.operatingSystem.version}\n` +
` Node Version: ${process.version}\n` +
` Ghost-CLI Version: ${system.cliVersion}\n` +
` Environment: ${system.environment}\n` +
Expand Down
41 changes: 41 additions & 0 deletions lib/utils/get-os.js
@@ -0,0 +1,41 @@
'use strict';

const os = require('os');
const execa = require('execa');

module.exports = function getOS(platform) {
const osInfo = {
os: os.platform(),
version: os.release()
};

if (platform.linux) {
try {
osInfo.os = execa.shellSync('lsb_release -i -s').stdout;
osInfo.version = execa.shellSync('lsb_release -r -s').stdout;
} catch (e) {
return osInfo;
}
} else if (platform.macos) {
// Darwin is Mac OS, use `sw_vers`
try {
osInfo.os = execa.shellSync('sw_vers -productName').stdout;
osInfo.version = execa.shellSync('sw_vers -productVersion').stdout;
} catch (e) {
return osInfo;
}
} else if (platform.windows) {
// for windows run `ver`
// should output something like this: Microsoft Windows XP [Version 5.1.2600]
try {
const winOutput = execa.shellSync('ver').stdout.split(/\[/i);

osInfo.os = winOutput[0].trim();
osInfo.version = /[0-9]+\.[0-9]+\.[0-9]+/.exec(winOutput[1])[0];
} catch (e) {
return osInfo;
}
}

return osInfo;
};
37 changes: 36 additions & 1 deletion test/unit/system-spec.js
Expand Up @@ -2,7 +2,6 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const proxyquire = require('proxyquire').noCallThru();

const os = require('os');
const modulePath = '../../lib/system';
const Instance = require('../../lib/instance');
Expand Down Expand Up @@ -116,6 +115,42 @@ describe('Unit: System', function () {
});
});

describe('operatingSystem getter', function () {
const sandbox = sinon.sandbox.create();

afterEach(function () {
sandbox.restore();
});

it('caches and returns the correct OS', function () {
const getOsStub = sinon.stub().returns({
os: 'Ubuntu',
version: '16'
});
const System = proxyquire(modulePath, {
'./utils/get-os': getOsStub
});

const instance = new System({}, []);
const platformStub = sandbox.stub(os, 'platform').returns('linux');
const operatingSystem = instance.operatingSystem;

expect(platformStub.calledOnce).to.be.true;
expect(getOsStub.calledOnce).to.be.true;
expect(operatingSystem).to.be.an('object');
expect(operatingSystem.os).to.equal('Ubuntu');
expect(operatingSystem.version).to.equal('16');

// do the second call to see that it gets cached
const newOperatingSystem = instance.operatingSystem;
expect(newOperatingSystem).to.be.an('object');
expect(newOperatingSystem.os).to.equal('Ubuntu');
expect(newOperatingSystem.version).to.equal('16');
expect(newOperatingSystem).to.deep.equal(operatingSystem);
expect(getOsStub.calledOnce).to.be.true;
});
});

describe('setEnvironment', function () {
it('sets things correctly in development', function () {
const System = require(modulePath);
Expand Down
7 changes: 6 additions & 1 deletion test/unit/ui/index-spec.js
Expand Up @@ -678,12 +678,17 @@ describe('Unit: UI', function () {
it('#_formatDebug returns a properly formatted value', function (done) {
const system = {
cliVersion: '0.9.1.8',
environment: 'Earth'
environment: 'Earth',
operatingSystem: {
os: 'Ubuntu',
version: '16'
}
};
const SPACES = ' ';
const UI = require(modulePath);
const ui = new UI();
const expected = ['Debug Information:',
`${SPACES}OS: Ubuntu, v16`,
`${SPACES}Node Version: ${process.version}`,
`${SPACES}Ghost-CLI Version: 0.9.1.8`,
`${SPACES}Environment: Earth`,
Expand Down
66 changes: 66 additions & 0 deletions test/unit/utils/get-os-spec.js
@@ -0,0 +1,66 @@
'use strict';
const expect = require('chai').expect;
const sinon = require('sinon');
const execa = require('execa');
const os = require('os');
const getOS = require('../../../lib/utils/get-os');

describe('Unit: Utils > getOS', function () {
const sandbox = sinon.sandbox.create();
let platformStub, versionStub, execaStub;

beforeEach(function () {
versionStub = sandbox.stub(os, 'release');
execaStub = sandbox.stub(execa, 'shellSync');
platformStub = sandbox.stub(os, 'platform');
});

afterEach(function () {
sandbox.restore();
});

it('and returns correct Linux OS', function () {
platformStub.returns('linux');
execaStub.withArgs('lsb_release -i -s').returns({stdout: 'Ubuntu'});
execaStub.withArgs('lsb_release -r -s').returns({stdout: '16'});

const osResult = getOS({linux: true});
expect(osResult.os).to.equal('Ubuntu');
expect(osResult.version).to.equal('16');
expect(execaStub.calledTwice).to.be.true;
});

it('and returns correct mac OS', function () {
platformStub.returns('darwin');
execaStub.withArgs('sw_vers -productName').returns({stdout: 'Mac OS X'});
execaStub.withArgs('sw_vers -productVersion').returns({stdout: '10.13.3'});

const osResult = getOS({macos: true});
expect(osResult.os).to.equal('Mac OS X');
expect(osResult.version).to.equal('10.13.3');
expect(execaStub.calledTwice).to.be.true;
});

it('and returns correct Windows OS', function () {
platformStub.returns('win32');
execaStub.withArgs('ver').returns({stdout: 'Microsoft Windows XP [Version 5.1.2600]'});

const osResult = getOS({windows: true});
expect(osResult.os).to.equal('Microsoft Windows XP');
expect(osResult.version).to.equal('5.1.2600');
expect(execaStub.calledOnce).to.be.true;
});

it('and returns default os.platform if OS is not Mac, Linux, or Windows', function () {
platformStub.returns('freebsd');
versionStub.returns('1.0.0')
const osResult = getOS({
linux: false,
macos: false,
windows: false
});
expect(osResult.os).to.equal('freebsd');
expect(osResult.version).to.equal('1.0.0');
expect(execaStub.calledOnce).to.be.false;
});
});

0 comments on commit bd24652

Please sign in to comment.