-
-
Notifications
You must be signed in to change notification settings - Fork 228
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(pre-checks): add ~/.config folder ownership to pre-run checks
closes #675 - convert update check to a listr task set - add ~/.config directory check to list of prechecks
- Loading branch information
Showing
10 changed files
with
214 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
'use strict'; | ||
const fs = require('fs-extra'); | ||
const os = require('os'); | ||
const path = require('path'); | ||
const semver = require('semver'); | ||
const latestVersion = require('latest-version'); | ||
const pkg = require('../../package.json'); | ||
|
||
/** | ||
* Checks if a version update is available | ||
* @param {UI} ui ui instance | ||
* @param {System} system System instance | ||
*/ | ||
module.exports = function preChecks(ui, system) { | ||
const tasks = [{ | ||
title: 'Checking for Ghost-CLI updates', | ||
task: () => latestVersion(pkg.name).then((latest) => { | ||
if (semver.lt(pkg.version, latest)) { | ||
const chalk = require('chalk'); | ||
|
||
ui.log( | ||
'You are running an outdated version of Ghost-CLI.\n' + | ||
'It is recommended that you upgrade before continuing.\n' + | ||
`Run ${chalk.cyan('`npm install -g ghost-cli@latest`')} to upgrade.\n`, | ||
'yellow' | ||
); | ||
} | ||
}) | ||
}, { | ||
title: 'Ensuring correct ~/.config folder ownership', | ||
task: () => { | ||
const configstore = path.join(os.homedir(), '.config'); | ||
|
||
return fs.lstat(configstore).then((stats) => { | ||
if (stats.uid === process.getuid() && stats.gid === process.getgid()) { | ||
return; | ||
} | ||
|
||
const {USER} = process.env; | ||
|
||
return ui.sudo(`chown -R ${USER}:${USER} ${configstore}`); | ||
}); | ||
}, | ||
isEnabled: () => system.platform.linux | ||
}]; | ||
|
||
return ui.listr(tasks, {}, {clearOnSuccess: true}); | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
'use strict'; | ||
const {expect} = require('chai'); | ||
const proxyquire = require('proxyquire').noCallThru(); | ||
const sinon = require('sinon'); | ||
const stripAnsi = require('strip-ansi'); | ||
const os = require('os'); | ||
const fs = require('fs-extra'); | ||
|
||
function fake(stubs = {}) { | ||
return proxyquire('../../../lib/utils/pre-checks', stubs); | ||
} | ||
|
||
function getTasks(stubs = {}, ui = {}, system = {}) { | ||
const preChecks = fake(stubs); | ||
const listr = sinon.stub().resolves(); | ||
|
||
return preChecks(Object.assign({listr}, ui), system).then(() => { | ||
expect(listr.calledOnce).to.be.true; | ||
return listr.args[0][0]; | ||
}); | ||
} | ||
|
||
describe('Unit: Utils > pre-checks', function () { | ||
describe('update check', function () { | ||
it('rejects error if latestVersion has an error', function (done) { | ||
const pkg = {name: 'ghost', version: '1.0.0'}; | ||
const testError = new Error('update check'); | ||
const latestVersion = sinon.stub().rejects(testError); | ||
|
||
getTasks({ | ||
'../../package.json': pkg, | ||
'latest-version': latestVersion | ||
}).then(([task]) => { | ||
expect(task.title).to.equal('Checking for Ghost-CLI updates'); | ||
|
||
return task.task(); | ||
}).catch((err) => { | ||
expect(err.message).to.equal(testError.message); | ||
expect(latestVersion.calledOnce).to.be.true; | ||
expect(latestVersion.calledWithExactly('ghost')).to.be.true; | ||
done(); | ||
}); | ||
}); | ||
|
||
it('doesn\'t do anything if there are no updates', function () { | ||
const pkg = {name: 'ghost', version: '1.0.0'}; | ||
const latestVersion = sinon.stub().resolves('1.0.0'); | ||
const log = sinon.stub(); | ||
|
||
return getTasks({ | ||
'../../package.json': pkg, | ||
'latest-version': latestVersion | ||
}, {log}).then(([task]) => task.task()).then(() => { | ||
expect(log.called).to.be.false; | ||
expect(latestVersion.calledOnce).to.be.true; | ||
expect(latestVersion.calledWithExactly('ghost')).to.be.true; | ||
}); | ||
}); | ||
|
||
it('logs a message if an update is available', function () { | ||
const pkg = {name: 'ghost', version: '1.0.0'}; | ||
const latestVersion = sinon.stub().resolves('1.1.0'); | ||
const log = sinon.stub(); | ||
|
||
return getTasks({ | ||
'../../package.json': pkg, | ||
'latest-version': latestVersion | ||
}, {log}).then(([task]) => task.task()).then(() => { | ||
expect(log.calledOnce).to.be.true; | ||
const msg = log.args[0][0]; | ||
|
||
expect(stripAnsi(msg)).to.match(/You are running an outdated version of Ghost-CLI/); | ||
|
||
expect(latestVersion.calledOnce).to.be.true; | ||
expect(latestVersion.calledWithExactly('ghost')).to.be.true; | ||
}); | ||
}); | ||
}); | ||
|
||
describe('~/.config folder ownership', function () { | ||
afterEach(() => { | ||
sinon.restore(); | ||
delete process.env.USER; | ||
}); | ||
|
||
it('rejects error if fs.lstat errors', function (done) { | ||
const homedir = sinon.stub(os, 'homedir').returns('/home/ghost'); | ||
const lstat = sinon.stub(fs, 'lstat').rejects(new Error('test error')); | ||
|
||
getTasks({}, {}, {platform: {linux: true}}).then(([,task]) => { | ||
expect(task.title).to.equal('Ensuring correct ~/.config folder ownership'); | ||
expect(task.isEnabled()).to.be.true; | ||
return task.task(); | ||
}).catch((error) => { | ||
expect(error.message).to.equal('test error'); | ||
expect(homedir.calledOnce).to.be.true; | ||
expect(lstat.calledOnce).to.be.true; | ||
expect(lstat.calledWithExactly('/home/ghost/.config')).to.be.true; | ||
done(); | ||
}); | ||
}); | ||
|
||
it('doesn\'t do anything if directory ownership if fine', function () { | ||
sinon.stub(os, 'homedir').returns('/home/ghost'); | ||
sinon.stub(fs, 'lstat').resolves({uid: 1, gid: 1}); | ||
const uid = sinon.stub(process, 'getuid').returns(1); | ||
const gid = sinon.stub(process, 'getgid').returns(1); | ||
const sudo = sinon.stub().resolves(); | ||
|
||
return getTasks({}, {sudo}, {platform: {linux: false}}).then(([,task]) => { | ||
expect(task.isEnabled()).to.be.false; | ||
return task.task(); | ||
}).then(() => { | ||
expect(uid.calledOnce).to.be.true; | ||
expect(gid.calledOnce).to.be.true; | ||
expect(sudo.called).to.be.false; | ||
}); | ||
}); | ||
|
||
it('calls chown if directory owner is not correct', function () { | ||
sinon.stub(os, 'homedir').returns('/home/ghost'); | ||
sinon.stub(fs, 'lstat').resolves({uid: 1, gid: 1}); | ||
const uid = sinon.stub(process, 'getuid').returns(2); | ||
const gid = sinon.stub(process, 'getgid').returns(2); | ||
const sudo = sinon.stub().resolves(); | ||
process.env.USER = 'ghostuser'; | ||
|
||
return getTasks({}, {sudo}).then(([,task]) => task.task()).then(() => { | ||
expect(uid.calledOnce).to.be.true; | ||
expect(gid.called).to.be.false; | ||
expect(sudo.calledOnce).to.be.true; | ||
|
||
expect(sudo.args[0][0]).to.equal('chown -R ghostuser:ghostuser /home/ghost/.config'); | ||
}); | ||
}); | ||
|
||
it('calls chown if directory group is not correct', function () { | ||
sinon.stub(os, 'homedir').returns('/home/ghost'); | ||
sinon.stub(fs, 'lstat').resolves({uid: 2, gid: 1}); | ||
const uid = sinon.stub(process, 'getuid').returns(2); | ||
const gid = sinon.stub(process, 'getgid').returns(2); | ||
const sudo = sinon.stub().resolves(); | ||
process.env.USER = 'ghostuser'; | ||
|
||
return getTasks({}, {sudo}).then(([,task]) => task.task()).then(() => { | ||
expect(uid.calledOnce).to.be.true; | ||
expect(gid.calledOnce).to.be.true; | ||
expect(sudo.calledOnce).to.be.true; | ||
|
||
expect(sudo.args[0][0]).to.equal('chown -R ghostuser:ghostuser /home/ghost/.config'); | ||
}); | ||
}); | ||
}); | ||
}); |
This file was deleted.
Oops, something went wrong.