speculate
Advanced tools
Comparing version 1.7.4 to 2.0.0-alpha.1
#! /usr/bin/env node | ||
'use strict'; | ||
var path = require('path'); | ||
var program = require('commander'); | ||
const path = require('path'); | ||
const program = require('commander'); | ||
var validator = require('../lib/validator'); | ||
var generate = require('../lib/generate'); | ||
var clean = require('../lib/clean'); | ||
var commandPkg = require('../package'); | ||
const validator = require('../lib/validator'); | ||
const generate = require('../lib/generate'); | ||
const clean = require('../lib/clean'); | ||
const commandPkg = require('../package'); | ||
var cwd = process.cwd(); | ||
var isValid = validator(cwd); | ||
const cwd = process.cwd(); | ||
const isValid = validator(cwd); | ||
if (!isValid) { | ||
// eslint-disable-next-line no-console | ||
console.error('Please run speculate from within a valid Node.js project'); | ||
@@ -19,3 +21,3 @@ process.exit(1); | ||
var projectPkg = require(path.resolve(cwd, './package.json')); | ||
const projectPkg = require(path.resolve(cwd, './package.json')); | ||
@@ -28,16 +30,22 @@ program | ||
// Commander has a magic property called name when not overriden by a parameter | ||
var name = program.name instanceof Function ? undefined : program.name; | ||
// Commander has a magic property called name when not overridden by a parameter | ||
const name = program.name instanceof Function ? undefined : program.name; | ||
clean(cwd, projectPkg); | ||
generate(cwd, projectPkg, program.release, name, function (err, generated) { | ||
if (err) { | ||
async function runTasks() { | ||
clean(cwd, projectPkg); | ||
try { | ||
const files = await generate(cwd, projectPkg, program.release, name); | ||
files.forEach((file) => { | ||
// eslint-disable-next-line no-console | ||
console.log('Created ./%s', file); | ||
}); | ||
process.exit(0); | ||
} catch (err) { | ||
// eslint-disable-next-line no-console | ||
console.error('Error:', err.message); | ||
process.exit(1); | ||
} | ||
} | ||
generated.forEach(function (file) { | ||
console.log('Created ./%s', file); | ||
}); | ||
process.exit(0); | ||
}); | ||
runTasks(); |
@@ -1,22 +0,51 @@ | ||
var tar = require('tar-fs'); | ||
var fs = require('fs'); | ||
var zlib = require('zlib'); | ||
var path = require('path'); | ||
'use strict'; | ||
var IGNORE_REGEX = /SOURCES|SPECS|RPMS|SRPMS|\.git/; | ||
const _ = require('lodash'); | ||
const tar = require('tar-fs'); | ||
const fs = require('fs'); | ||
const zlib = require('zlib'); | ||
const path = require('path'); | ||
module.exports.compress = function (source, target, cb) { | ||
var gzip = zlib.createGzip(); | ||
var ws = fs.createWriteStream(target); | ||
var rs = tar.pack(source, { | ||
const IGNORE_REGEX = /SOURCES|SPECS|RPMS|SRPMS|\.git/; | ||
const REQUIRED_ENTRIES = [ | ||
'package.json', | ||
'node_modules' | ||
]; | ||
function getEntries(whitelist) { | ||
if (whitelist.files) { | ||
const whitelistSections = _.pick(whitelist, ['main', 'files']); | ||
const whitelistFromSections = _.reduce(whitelistSections, (whitelist, current) => { | ||
if (current) { | ||
return _.concat(whitelist, current); | ||
} | ||
return whitelist; | ||
}, []); | ||
if (!whitelistFromSections.length) { | ||
return; | ||
} | ||
return _.concat(REQUIRED_ENTRIES, whitelistFromSections); | ||
} | ||
} | ||
module.exports.compress = async function (source, target, whitelist) { | ||
const gzip = zlib.createGzip(); | ||
const ws = fs.createWriteStream(target); | ||
const rs = tar.pack(source, { | ||
ignore: function (name) { | ||
return IGNORE_REGEX.test(path.relative(source, name)); | ||
} | ||
}, | ||
entries: getEntries(whitelist) | ||
}); | ||
rs.on('error', cb); | ||
ws.on('error', cb); | ||
ws.on('close', cb); | ||
return new Promise((resolve, reject) => { | ||
rs.on('error', reject); | ||
ws.on('error', reject); | ||
ws.on('close', resolve); | ||
rs.pipe(gzip).pipe(ws); | ||
rs.pipe(gzip).pipe(ws); | ||
}); | ||
}; |
@@ -1,9 +0,11 @@ | ||
var rimraf = require('rimraf'); | ||
'use strict'; | ||
var files = require('./files'); | ||
const rimraf = require('rimraf'); | ||
const files = require('./files'); | ||
module.exports = function (root, pkg) { | ||
var serviceFilePath = files.serviceFile(root, pkg); | ||
var specsDirectory = files.specsDirectory(root); | ||
var sourcesDirectory = files.sourcesDirectory(root); | ||
const serviceFilePath = files.serviceFile(root, pkg); | ||
const specsDirectory = files.specsDirectory(root); | ||
const sourcesDirectory = files.sourcesDirectory(root); | ||
@@ -10,0 +12,0 @@ rimraf.sync(serviceFilePath); |
@@ -1,3 +0,5 @@ | ||
var path = require('path'); | ||
'use strict'; | ||
const path = require('path'); | ||
module.exports = { | ||
@@ -17,3 +19,3 @@ serviceFile: function (root, pkg) { | ||
sourcesArchive: function (root, pkg) { | ||
var sourcesDirectory = this.sourcesDirectory(root); | ||
const sourcesDirectory = this.sourcesDirectory(root); | ||
@@ -20,0 +22,0 @@ return path.resolve(sourcesDirectory, pkg.name + '.tar.gz'); |
@@ -1,13 +0,14 @@ | ||
var _ = require('lodash'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
'use strict'; | ||
var archiver = require('./archiver'); | ||
var createServiceFile = require('./service'); | ||
var createSpecFile = require('./spec'); | ||
var files = require('./files'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const archiver = require('./archiver'); | ||
const createServiceFile = require('./service'); | ||
const createSpecFile = require('./spec'); | ||
const files = require('./files'); | ||
function generateServiceFile(root, pkg) { | ||
var serviceFileContents = createServiceFile(pkg); | ||
var serviceFilePath = files.serviceFile(root, pkg); | ||
const serviceFileContents = createServiceFile(pkg); | ||
const serviceFilePath = files.serviceFile(root, pkg); | ||
@@ -20,4 +21,4 @@ fs.writeFileSync(serviceFilePath, serviceFileContents); | ||
function generateSpecFile(root, pkg, release) { | ||
var specFileContents = createSpecFile(pkg, release); | ||
var specFilePath = files.specFile(root, pkg); | ||
const specFileContents = createSpecFile(pkg, release); | ||
const specFilePath = files.specFile(root, pkg); | ||
@@ -31,3 +32,3 @@ fs.writeFileSync(specFilePath, specFileContents); | ||
if (customName) { | ||
return _.extend({}, pkg, { name: customName }); | ||
return Object.assign({}, pkg, { name: customName }); | ||
} | ||
@@ -39,3 +40,3 @@ | ||
function relativeToRoot(root, files) { | ||
return files.map(function (file) { | ||
return files.map((file) => { | ||
return path.relative(root, file); | ||
@@ -45,24 +46,26 @@ }); | ||
module.exports = function (root, pkg, release, customName, cb) { | ||
var customPackage = addCustomFieldsToPackage(pkg, customName); | ||
var specsDirectory = files.specsDirectory(root); | ||
var sourcesDirectory = files.sourcesDirectory(root); | ||
var sourcesArchive = files.sourcesArchive(root, customPackage); | ||
function getArchiveWhitelist({ main, files }) { | ||
return { main, files }; | ||
} | ||
module.exports = async (root, pkg, release, customName) => { | ||
const customPackage = addCustomFieldsToPackage(pkg, customName); | ||
const specsDirectory = files.specsDirectory(root); | ||
const sourcesDirectory = files.sourcesDirectory(root); | ||
const sourcesArchive = files.sourcesArchive(root, customPackage); | ||
fs.mkdirSync(specsDirectory); | ||
fs.mkdirSync(sourcesDirectory); | ||
var serviceFile = generateServiceFile(root, customPackage); | ||
var specFile = generateSpecFile(specsDirectory, customPackage, release); | ||
archiver.compress(root, sourcesArchive, function (err) { | ||
if (err) { | ||
return cb(err); | ||
} | ||
const serviceFile = generateServiceFile(root, customPackage); | ||
const specFile = generateSpecFile(specsDirectory, customPackage, release); | ||
const archiveWhitelist = getArchiveWhitelist(pkg); | ||
cb(null, relativeToRoot(root, [ | ||
specFile, | ||
sourcesArchive, | ||
serviceFile | ||
])); | ||
}); | ||
await archiver.compress(root, sourcesArchive, archiveWhitelist); | ||
return relativeToRoot(root, [ | ||
specFile, | ||
sourcesArchive, | ||
serviceFile | ||
]); | ||
}; |
@@ -1,13 +0,15 @@ | ||
var hogan = require('hogan.js'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var getServiceProperties = require('./serviceProperties'); | ||
'use strict'; | ||
var templateFile = fs.readFileSync(path.resolve(__dirname, '../templates/service.mustache'), 'utf-8'); | ||
var template = hogan.compile(templateFile); | ||
const hogan = require('hogan.js'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const getServiceProperties = require('./serviceProperties'); | ||
const templateFile = fs.readFileSync(path.resolve(__dirname, '../templates/service.mustache'), 'utf-8'); | ||
const template = hogan.compile(templateFile); | ||
module.exports = function (pkg) { | ||
var serviceProperties = getServiceProperties(pkg); | ||
const serviceProperties = getServiceProperties(pkg); | ||
return template.render(serviceProperties); | ||
}; |
@@ -1,26 +0,23 @@ | ||
var truncate = require('./truncate'); | ||
var _ = require('lodash'); | ||
'use strict'; | ||
function getEnvironment(pkg) { | ||
var environment = _.get(pkg, 'spec.environment', {}); | ||
return Object.keys(environment).map(function(key) { | ||
return { key: key, value: environment[key]}; | ||
}); | ||
} | ||
const truncate = require('./truncate'); | ||
function getServiceOptions(pkg) { | ||
var serviceOptions = _.get(pkg, 'spec.serviceOptions', {}); | ||
return Object.keys(serviceOptions).map(function(key) { | ||
return { key: key, value: serviceOptions[key]}; | ||
}); | ||
function convertToKeyValueFromSpec(spec, prop) { | ||
if (spec && prop in spec) { | ||
return Object.keys(spec[prop]).map((key) => { | ||
return { key, value: spec[prop][key] }; | ||
}); | ||
} | ||
} | ||
module.exports = function (pkg) { | ||
return { | ||
name: pkg.name, | ||
username: truncate(pkg.name), | ||
description: pkg.description, | ||
environment: getEnvironment(pkg), | ||
serviceOptions: getServiceOptions(pkg) | ||
}; | ||
return Object.assign( | ||
{ | ||
name: pkg.name, | ||
username: truncate(pkg.name), | ||
description: pkg.description, | ||
environment: convertToKeyValueFromSpec(pkg.spec, 'environment'), | ||
serviceOptions: convertToKeyValueFromSpec(pkg.spec, 'serviceOptions') | ||
} | ||
); | ||
}; |
@@ -1,12 +0,13 @@ | ||
var hogan = require('hogan.js'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var _ = require('lodash'); | ||
var getServiceProperties = require('./serviceProperties'); | ||
'use strict'; | ||
var templateFile = fs.readFileSync(path.resolve(__dirname, '../templates/spec.mustache'), 'utf-8'); | ||
var template = hogan.compile(templateFile); | ||
const hogan = require('hogan.js'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const getServiceProperties = require('./serviceProperties'); | ||
var defaultRelease = 1; | ||
const templateFile = fs.readFileSync(path.resolve(__dirname, '../templates/spec.mustache'), 'utf-8'); | ||
const template = hogan.compile(templateFile); | ||
const defaultRelease = 1; | ||
function getReleaseNumber(release) { | ||
@@ -20,17 +21,13 @@ if (release) { | ||
function getRequiredBuildPackages(pkg) { | ||
return _.get(pkg, 'spec.buildRequires', []); | ||
} | ||
function getValueFromSpec(spec, key, fallback) { | ||
if (spec && key in spec) { | ||
return spec[key]; | ||
} | ||
function getRequiredPackages(pkg) { | ||
return _.get(pkg, 'spec.requires', []); | ||
return fallback; | ||
} | ||
function getNodeVersion(pkg) { | ||
return _.get(pkg, 'spec.nodeVersion'); | ||
} | ||
function getExecutableFiles(pkg) { | ||
var name = pkg.name; | ||
var executableFiles = _.get(pkg, 'spec.executable', []).map(function (file) { | ||
const name = pkg.name; | ||
const executableFiles = getValueFromSpec(pkg.spec, 'executable', []).map((file) => { | ||
return path.join('/usr/lib/', name, file); | ||
@@ -40,3 +37,3 @@ }); | ||
return { | ||
executableFiles: executableFiles, | ||
executableFiles, | ||
hasExecutableFiles: executableFiles.length !== 0 | ||
@@ -46,20 +43,13 @@ }; | ||
function getPostInstallCommands(pkg) { | ||
return _.get(pkg, 'spec.post', []); | ||
} | ||
function shouldPrune(pkg) { | ||
return _.get(pkg, 'spec.prune', true); | ||
} | ||
module.exports = function (pkg, release) { | ||
var serviceProperties = _.assign({ | ||
const serviceProperties = Object.assign( | ||
{ | ||
release: getReleaseNumber(release), | ||
requires: getRequiredPackages(pkg), | ||
buildRequires: getRequiredBuildPackages(pkg), | ||
postInstallCommands: getPostInstallCommands(pkg), | ||
nodeVersion: getNodeVersion(pkg), | ||
requires: getValueFromSpec(pkg.spec, 'requires', []), | ||
buildRequires: getValueFromSpec(pkg.spec, 'buildRequires', []), | ||
postInstallCommands: getValueFromSpec(pkg.spec, 'post', []), | ||
nodeVersion: getValueFromSpec(pkg.spec, 'nodeVersion'), | ||
version: pkg.version, | ||
license: pkg.license, | ||
prune: shouldPrune(pkg) | ||
prune: getValueFromSpec(pkg.spec, 'prune', true) | ||
}, | ||
@@ -66,0 +56,0 @@ getExecutableFiles(pkg), |
@@ -1,5 +0,7 @@ | ||
var linuxUsernameLimit = 32; | ||
'use strict'; | ||
const linuxUsernameLimit = 32; | ||
module.exports = function (name) { | ||
return name.substring(0, linuxUsernameLimit); | ||
}; |
@@ -1,3 +0,5 @@ | ||
var path = require('path'); | ||
'use strict'; | ||
const path = require('path'); | ||
module.exports = function (projectDirectory) { | ||
@@ -4,0 +6,0 @@ try { |
{ | ||
"name": "speculate", | ||
"version": "1.7.4", | ||
"version": "2.0.0-alpha.1", | ||
"description": "Automatically generates an RPM Spec file for your Node.js project", | ||
@@ -24,3 +24,3 @@ "main": "index.js", | ||
"author": "ibl-team@lists.forge.bbc.co.uk", | ||
"license": "MIT", | ||
"license": "Apache-2.0", | ||
"bugs": { | ||
@@ -36,3 +36,2 @@ "url": "https://github.com/bbc/speculate/issues" | ||
"hogan.js": "^3.0.2", | ||
"lodash": "^4.6.1", | ||
"rimraf": "^2.5.2", | ||
@@ -42,19 +41,15 @@ "tar-fs": "^1.11.1" | ||
"eslintConfig": { | ||
"extends": "eslint:recommended", | ||
"env": { | ||
"node": true, | ||
"mocha": true | ||
}, | ||
"rules": { | ||
"semi": 2, | ||
"no-console": 0 | ||
"extends": "iplayer-es6", | ||
"parserOptions": { | ||
"ecmaVersion": 8 | ||
} | ||
}, | ||
"devDependencies": { | ||
"codeclimate-test-reporter": "^0.3.1", | ||
"eslint": "^2.4.0", | ||
"codeclimate-test-reporter": "^0.5.0", | ||
"eslint": "^4.19.1", | ||
"eslint-config-iplayer-es6": "^4.0.1", | ||
"istanbul": "^0.4.2", | ||
"mocha": "^2.4.5", | ||
"sinon": "^1.17.3" | ||
"mocha": "^5.0.4", | ||
"sinon": "^4.4.8" | ||
} | ||
} |
@@ -121,3 +121,3 @@ # speculate | ||
"spec": { | ||
"prune": false | ||
"prune": false | ||
} | ||
@@ -139,2 +139,31 @@ } | ||
### Including only certain files | ||
Similar to `npm`, if you specify a `files` directive in your `package.json` then `speculate` will only include those files or directories plus `package.json` and `node_modules` in the source tarball: | ||
```json | ||
{ | ||
"files": [ | ||
"lib", | ||
"routes", | ||
"index.js" | ||
] | ||
} | ||
``` | ||
Alongside this, the `main` attribute is also included in the `files` listing, although the service is still started using `npm start`: | ||
```json | ||
{ | ||
"main": "server.js", | ||
"files": [ | ||
"lib", | ||
"routes", | ||
"index.js" | ||
] | ||
} | ||
``` | ||
If you have only a `main` directive, speculate will assume you are using it for its original purpose and not create an archive only including that one file. | ||
### Node versions | ||
@@ -141,0 +170,0 @@ |
@@ -1,18 +0,21 @@ | ||
var _ = require('lodash'); | ||
var fs = require('fs'); | ||
var tar = require('tar-fs'); | ||
var zlib = require('zlib'); | ||
var stream = require('stream'); | ||
var assert = require('assert'); | ||
var sinon = require('sinon'); | ||
var sandbox = sinon.sandbox.create(); | ||
'use strict'; | ||
var archiver = require('../lib/archiver'); | ||
const fs = require('fs'); | ||
const tar = require('tar-fs'); | ||
const zlib = require('zlib'); | ||
const stream = require('stream'); | ||
const assert = require('assert'); | ||
const sinon = require('sinon'); | ||
const sandbox = sinon.sandbox.create(); | ||
describe('archiver', function () { | ||
var writeStream; | ||
var readStream; | ||
var transformStream; | ||
const archiver = require('../lib/archiver'); | ||
beforeEach(function () { | ||
function noop() {} | ||
describe('archiver', () => { | ||
let writeStream; | ||
let readStream; | ||
let transformStream; | ||
beforeEach(() =>{ | ||
writeStream = new stream.Writable(); | ||
@@ -22,4 +25,4 @@ readStream = new stream.Readable(); | ||
readStream._read = _.noop; | ||
transformStream._read = _.noop; | ||
readStream._read = noop; | ||
transformStream._read = noop; | ||
@@ -31,50 +34,119 @@ sandbox.stub(fs, 'createWriteStream').returns(writeStream); | ||
afterEach(function () { | ||
afterEach(() =>{ | ||
sandbox.restore(); | ||
}); | ||
it('creates a tar.gz archive', function (done) { | ||
archiver.compress('tmp', 'tmp.tar.gz', function (err) { | ||
assert.ifError(err); | ||
done(); | ||
}); | ||
it('creates a tar.gz archive', async () => { | ||
const result = archiver.compress('tmp', 'tmp.tar.gz', {}); | ||
writeStream.emit('close'); | ||
await result; | ||
}); | ||
it('returns an error when the archive cannot be written', function (done) { | ||
archiver.compress('tmp', 'tmp.tar.gz', function (err) { | ||
it('returns an error when the archive cannot be written', async () => { | ||
const result = archiver.compress('tmp', 'tmp.tar.gz', {}); | ||
writeStream.emit('error', new Error('An error occured')); | ||
try { | ||
await result; | ||
assert.fail(); | ||
} catch (err) { | ||
assert.ok(err); | ||
done(); | ||
}); | ||
} | ||
}); | ||
writeStream.emit('error', new Error('An error occured')); | ||
it('ignores build artifacts', async () => { | ||
const result = archiver.compress('tmp', 'tmp.tar.gz', {}); | ||
writeStream.emit('close'); | ||
await result; | ||
sinon.assert.calledWith(tar.pack, 'tmp', sinon.match.object); | ||
const ignore = tar.pack.getCall(0).args[1].ignore; | ||
assert.equal(ignore('SPECS'), true); | ||
assert.equal(ignore('SOURCES'), true); | ||
assert.equal(ignore('RPMS'), true); | ||
assert.equal(ignore('SRPMS'), true); | ||
assert.equal(ignore('.git/objects/00'), true); | ||
}); | ||
it('ignores build artifacts', function (done) { | ||
archiver.compress('tmp', 'tmp.tar.gz', function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith(tar.pack, 'tmp', sinon.match.object); | ||
var ignore = tar.pack.getCall(0).args[1].ignore; | ||
assert.equal(ignore('SPECS'), true); | ||
assert.equal(ignore('SOURCES'), true); | ||
assert.equal(ignore('RPMS'), true); | ||
assert.equal(ignore('SRPMS'), true); | ||
assert.equal(ignore('.git/objects/00'), true); | ||
done(); | ||
}); | ||
it('does not ignore all artifacts because of full path name', async () => { | ||
const result = archiver.compress('/tmp/SOURCES', 'tmp.tar.gz', {}); | ||
writeStream.emit('close'); | ||
await result; | ||
const ignore = tar.pack.getCall(0).args[1].ignore; | ||
assert.equal(ignore('/tmp/SOURCES/cake/real_file_here'), false); | ||
}); | ||
it('archives files on a whitelist if specified alongside required files', async () => { | ||
const files = [ | ||
'lib', | ||
'routes', | ||
'index.js' | ||
]; | ||
const result = archiver.compress('/tmp/SOURCES', 'tmp.tar.gz', { files }); | ||
writeStream.emit('close'); | ||
await result; | ||
sandbox.assert.calledWith(tar.pack, '/tmp/SOURCES', sinon.match({ | ||
entries: [ | ||
'package.json', | ||
'node_modules', | ||
'lib', | ||
'routes', | ||
'index.js' | ||
] | ||
})); | ||
}); | ||
it('does not ignore all artifacts because of full path name', function (done) { | ||
archiver.compress('/tmp/SOURCES', 'tmp.tar.gz', function (err) { | ||
assert.ifError(err); | ||
var ignore = tar.pack.getCall(0).args[1].ignore; | ||
assert.equal(ignore('/tmp/SOURCES/cake/real_file_here'), false); | ||
done(); | ||
}); | ||
it('does not include whitelist if none specified', async () => { | ||
const result = archiver.compress('/tmp/SOURCES', 'tmp.tar.gz', {}); | ||
writeStream.emit('close'); | ||
await result; | ||
sandbox.assert.calledWith(tar.pack, '/tmp/SOURCES', sinon.match({ | ||
entries: undefined | ||
})); | ||
}); | ||
it('adds the "main" file to the archive alongside "files" if specified', async () => { | ||
const main = 'server.js'; | ||
const files = [ | ||
'lib', | ||
'routes', | ||
'index.js' | ||
]; | ||
const result = archiver.compress('/tmp/SOURCES', 'tmp.tar.gz', { main, files }); | ||
writeStream.emit('close'); | ||
await result; | ||
sandbox.assert.neverCalledWith(tar.pack, sinon.match({ ignore: sinon.match.func })); | ||
sandbox.assert.calledWith(tar.pack, '/tmp/SOURCES', sinon.match({ | ||
entries: [ | ||
'package.json', | ||
'node_modules', | ||
'server.js', | ||
'lib', | ||
'routes', | ||
'index.js' | ||
] | ||
})); | ||
}); | ||
it('archives everything if only the "main" is specified', async () => { | ||
const main = 'server.js'; | ||
const result = archiver.compress('/tmp/SOURCES', 'tmp.tar.gz', { main }); | ||
writeStream.emit('close'); | ||
await result; | ||
sandbox.assert.neverCalledWith(tar.pack, sinon.match({ ignore: sinon.match.func })); | ||
sandbox.assert.calledWith(tar.pack, '/tmp/SOURCES', sinon.match({ | ||
entries: undefined | ||
})); | ||
}); | ||
}); |
@@ -1,18 +0,20 @@ | ||
var sinon = require('sinon'); | ||
var rimraf = require('rimraf'); | ||
var clean = require('../lib/clean'); | ||
'use strict'; | ||
var pkg = require('./fixtures/my-cool-api'); | ||
var sandbox = sinon.sandbox.create(); | ||
const sinon = require('sinon'); | ||
const rimraf = require('rimraf'); | ||
const clean = require('../lib/clean'); | ||
describe('clean', function () { | ||
beforeEach(function () { | ||
const pkg = require('./fixtures/my-cool-api'); | ||
const sandbox = sinon.sandbox.create(); | ||
describe('clean', () => { | ||
beforeEach(() => { | ||
sandbox.stub(rimraf, 'sync'); | ||
}); | ||
afterEach(function () { | ||
afterEach(() => { | ||
sandbox.restore(); | ||
}); | ||
it('removes the existing service file', function () { | ||
it('removes the existing service file', () => { | ||
clean('/path/to/project', pkg); | ||
@@ -25,3 +27,3 @@ sinon.assert.calledWith( | ||
it('removes the SPECS directory', function () { | ||
it('removes the SPECS directory', () => { | ||
clean('/path/to/project', pkg); | ||
@@ -34,3 +36,3 @@ sinon.assert.calledWith( | ||
it('removes the SOURCES directory', function () { | ||
it('removes the SOURCES directory', () => { | ||
clean('/path/to/project', pkg); | ||
@@ -37,0 +39,0 @@ sinon.assert.calledWith( |
@@ -1,129 +0,170 @@ | ||
var sinon = require('sinon'); | ||
var fs = require('fs'); | ||
var assert = require('assert'); | ||
var generate = require('../lib/generate'); | ||
var archiver = require('../lib/archiver'); | ||
'use strict'; | ||
var pkg = require('./fixtures/my-cool-api'); | ||
var sandbox = sinon.sandbox.create(); | ||
const pkg = require('./fixtures/my-cool-api'); | ||
const pkgWithWhitelist = require('./fixtures/my-cool-api-with-whitelist'); | ||
const sandbox = require('sinon').sandbox.create(); | ||
const fs = require('fs'); | ||
const assert = require('assert'); | ||
const generate = require('../lib/generate'); | ||
const archiver = require('../lib/archiver'); | ||
describe('generate', function () { | ||
beforeEach(function () { | ||
describe('generate', () => { | ||
beforeEach(() =>{ | ||
sandbox.stub(fs, 'writeFileSync'); | ||
sandbox.stub(fs, 'mkdirSync'); | ||
sandbox.stub(archiver, 'compress').yields(); | ||
sandbox.stub(archiver, 'compress').returns(Promise.resolve()); | ||
}); | ||
afterEach(function () { | ||
afterEach(() =>{ | ||
sandbox.restore(); | ||
}); | ||
it('creates the service file', function (done) { | ||
generate('/path/to/project', pkg, null, null, function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/my-cool-api.service', | ||
sinon.match('SyslogIdentifier=my-cool-api') | ||
); | ||
done(); | ||
}); | ||
it('creates the service file', async () => { | ||
await generate('/path/to/project', pkg, null, null); | ||
sandbox.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/my-cool-api.service', | ||
sandbox.match('SyslogIdentifier=my-cool-api') | ||
); | ||
}); | ||
it('creates directory for SPECS', function (done) { | ||
generate('/path/to/project', pkg, null, null, function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith(fs.mkdirSync, '/path/to/project/SPECS'); | ||
done(); | ||
}); | ||
it('creates directory for SPECS', async () => { | ||
await generate('/path/to/project', pkg, null, null); | ||
sandbox.assert.calledWith(fs.mkdirSync, '/path/to/project/SPECS'); | ||
}); | ||
it('creates the spec file', function (done) { | ||
generate('/path/to/project', pkg, null, null, function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/SPECS/my-cool-api.spec', | ||
sinon.match('%define name my-cool-api') | ||
); | ||
done(); | ||
}); | ||
it('fails if it cannot create directory for SPECS', async () => { | ||
fs.mkdirSync.withArgs('/path/to/project/SPECS').throws(); | ||
try { | ||
await generate('/path/to/project', pkg, null, null); | ||
} catch (e) { | ||
return assert.ok(e); | ||
} | ||
assert.fail(); | ||
}); | ||
it('creates directory for SOURCES', function (done) { | ||
generate('/path/to/project', pkg, null, null, function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith(fs.mkdirSync, '/path/to/project/SOURCES'); | ||
done(); | ||
}); | ||
it('creates the spec file', async () => { | ||
await generate('/path/to/project', pkg, null, null); | ||
sandbox.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/SPECS/my-cool-api.spec', | ||
sandbox.match('%define name my-cool-api') | ||
); | ||
}); | ||
it('creates the sources archive', function (done) { | ||
generate('/path/to/project', pkg, null, null, function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith( | ||
archiver.compress, | ||
'/path/to/project', | ||
'/path/to/project/SOURCES/my-cool-api.tar.gz' | ||
); | ||
done(); | ||
}); | ||
it('creates the sources archive', async () => { | ||
await generate('/path/to/project', pkg, null, null); | ||
sandbox.assert.calledWith( | ||
archiver.compress, | ||
'/path/to/project', | ||
'/path/to/project/SOURCES/my-cool-api.tar.gz', | ||
{ | ||
files: undefined, | ||
main: 'index.js' | ||
} | ||
); | ||
}); | ||
it('creates the spec file with the correct release number', function (done) { | ||
generate('/path/to/project', pkg, 7, null, function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/SPECS/my-cool-api.spec', | ||
sinon.match('%define release 7') | ||
); | ||
done(); | ||
}); | ||
it('creates directory for SOURCES', async () => { | ||
await generate('/path/to/project', pkg, null, null); | ||
sandbox.assert.calledWith(fs.mkdirSync, '/path/to/project/SOURCES'); | ||
}); | ||
it('creates the spec file with a custom name if specified', function (done) { | ||
generate('/path/to/project', pkg, 1, 'penguin', function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/SPECS/penguin.spec', | ||
sinon.match('%define name penguin') | ||
); | ||
done(); | ||
}); | ||
it('fails if it cannot create directory for SOURCES', async () => { | ||
fs.mkdirSync.withArgs('/path/to/project/SOURCES').throws(); | ||
try { | ||
await generate('/path/to/project', pkg, null, null); | ||
} catch (e) { | ||
return assert.ok(e); | ||
} | ||
assert.fail(); | ||
}); | ||
it('creates the service file with a custom name if specified', function (done) { | ||
generate('/path/to/project', pkg, 1, 'penguin', function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/penguin.service', | ||
sinon.match('SyslogIdentifier=penguin') | ||
); | ||
done(); | ||
}); | ||
it('creates the spec file with the correct release number', async () => { | ||
await generate('/path/to/project', pkg, 7, null); | ||
sandbox.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/SPECS/my-cool-api.spec', | ||
sandbox.match('%define release 7') | ||
); | ||
}); | ||
it('creates the sources archive with a custom name if specified', function (done) { | ||
generate('/path/to/project', pkg, null, 'penguin', function (err) { | ||
assert.ifError(err); | ||
sinon.assert.calledWith( | ||
archiver.compress, | ||
'/path/to/project', | ||
'/path/to/project/SOURCES/penguin.tar.gz' | ||
); | ||
done(); | ||
}); | ||
it('creates the spec file with a custom name if specified', async () => { | ||
await generate('/path/to/project', pkg, 1, 'penguin'); | ||
sandbox.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/SPECS/penguin.spec', | ||
sandbox.match('%define name penguin') | ||
); | ||
}); | ||
it('returns an array of files created', function (done) { | ||
var filesExpected = ['SPECS/my-cool-api.spec', 'SOURCES/my-cool-api.tar.gz', 'my-cool-api.service']; | ||
generate('/path/to/project', pkg, null, null, function (err, files) { | ||
assert.ifError(err); | ||
assert.deepEqual(files, filesExpected); | ||
done(); | ||
}); | ||
it('creates the sources archive with a custom name if specified', async () => { | ||
await generate('/path/to/project', pkg, null, 'penguin'); | ||
sandbox.assert.calledWith( | ||
archiver.compress, | ||
'/path/to/project', | ||
'/path/to/project/SOURCES/penguin.tar.gz', | ||
{ | ||
files: undefined, | ||
main: 'index.js' | ||
} | ||
); | ||
}); | ||
it('passes files and main values from the package.json to archiver', async () => { | ||
await generate('/path/to/project', pkgWithWhitelist, null, null); | ||
sandbox.assert.calledWith( | ||
archiver.compress, | ||
'/path/to/project', | ||
'/path/to/project/SOURCES/my-cool-api.tar.gz', | ||
{ | ||
main: 'server.js', | ||
files: [ | ||
'lib', | ||
'routes', | ||
'index.js' | ||
] | ||
} | ||
); | ||
}); | ||
it('creates the service file with a custom name if specified', async () => { | ||
await generate('/path/to/project', pkg, 1, 'penguin'); | ||
sandbox.assert.calledWith( | ||
fs.writeFileSync, | ||
'/path/to/project/penguin.service', | ||
sandbox.match('SyslogIdentifier=penguin') | ||
); | ||
}); | ||
it('creates the sources archive with a custom name if specified', async () => { | ||
await generate('/path/to/project', pkg, null, 'penguin'); | ||
sandbox.assert.calledWith( | ||
archiver.compress, | ||
'/path/to/project', | ||
'/path/to/project/SOURCES/penguin.tar.gz' | ||
); | ||
}); | ||
it('returns an array of files created', async () => { | ||
const filesExpected = ['SPECS/my-cool-api.spec', 'SOURCES/my-cool-api.tar.gz', 'my-cool-api.service']; | ||
const files = await generate('/path/to/project', pkg, null, null); | ||
assert.deepEqual(files, filesExpected); | ||
}); | ||
it('fails if archiver fails', async () => { | ||
archiver.compress.returns(Promise.reject(new Error('Thanks Jim :-)'))); | ||
try { | ||
await generate('/path/to/project', pkg, null, null); | ||
} catch (e) { | ||
return assert.ok(e); | ||
} | ||
assert.fail(); | ||
}); | ||
}); |
@@ -1,8 +0,10 @@ | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
'use strict'; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
module.exports = function loadFixture(fixtureName) { | ||
var fixtureFile = path.join(__dirname, './fixtures/', fixtureName); | ||
const fixtureFile = path.join(__dirname, './fixtures/', fixtureName); | ||
return fs.readFileSync(fixtureFile, 'utf-8'); | ||
}; |
@@ -1,18 +0,20 @@ | ||
var createServiceFile = require('../lib/service'); | ||
var assert = require('assert'); | ||
var loadFixture = require('./loadFixture'); | ||
'use strict'; | ||
describe('service', function () { | ||
it('creates a service file from a package.json', function () { | ||
var pkg = require('./fixtures/my-cool-api'); | ||
var expected = loadFixture('my-cool-api.service'); | ||
var service = createServiceFile(pkg); | ||
const createServiceFile = require('../lib/service'); | ||
const assert = require('assert'); | ||
const loadFixture = require('./loadFixture'); | ||
describe('service', () => { | ||
it('creates a service file from a package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api'); | ||
const expected = loadFixture('my-cool-api.service'); | ||
const service = createServiceFile(pkg); | ||
assert.equal(service, expected); | ||
}); | ||
it('truncates the service name if over the Linux username character limit', function () { | ||
var pkg = require('./fixtures/my-super-long-long-long-long-cat-api'); | ||
var expected = loadFixture('my-super-long-long-long-long-cat-api.service'); | ||
var service = createServiceFile(pkg); | ||
it('truncates the service name if over the Linux username character limit', () => { | ||
const pkg = require('./fixtures/my-super-long-long-long-long-cat-api'); | ||
const expected = loadFixture('my-super-long-long-long-long-cat-api.service'); | ||
const service = createServiceFile(pkg); | ||
@@ -22,6 +24,6 @@ assert.equal(service, expected); | ||
it('includes environment variables from the spec.environment property in package.json', function() { | ||
var pkg = require('./fixtures/my-cool-api-environment'); | ||
var expected = loadFixture('my-cool-api-environment.service'); | ||
var service = createServiceFile(pkg); | ||
it('includes environment constiables from the spec.environment property in package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api-environment'); | ||
const expected = loadFixture('my-cool-api-environment.service'); | ||
const service = createServiceFile(pkg); | ||
@@ -31,6 +33,6 @@ assert.equal(service, expected); | ||
it('includes service options from the spec.serviceOptions property in package.json', function() { | ||
var pkg = require('./fixtures/my-cool-api-with-service-options'); | ||
var expected = loadFixture('my-cool-api-with-service-options.service'); | ||
var service = createServiceFile(pkg); | ||
it('includes service options from the spec.serviceOptions property in package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-service-options'); | ||
const expected = loadFixture('my-cool-api-with-service-options.service'); | ||
const service = createServiceFile(pkg); | ||
@@ -37,0 +39,0 @@ assert.equal(service, expected); |
100
test/spec.js
@@ -1,18 +0,20 @@ | ||
var createSpecFile = require('../lib/spec'); | ||
var assert = require('assert'); | ||
var loadFixture = require('./loadFixture'); | ||
'use strict'; | ||
describe('spec', function () { | ||
it('creates a spec file from a package.json', function () { | ||
var pkg = require('./fixtures/my-cool-api'); | ||
var expected = loadFixture('my-cool-api.spec'); | ||
var spec = createSpecFile(pkg); | ||
const createSpecFile = require('../lib/spec'); | ||
const assert = require('assert'); | ||
const loadFixture = require('./loadFixture'); | ||
describe('spec', () => { | ||
it('creates a spec file from a package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api'); | ||
const expected = loadFixture('my-cool-api.spec'); | ||
const spec = createSpecFile(pkg); | ||
assert.equal(spec, expected); | ||
}); | ||
it('truncates the service name if over the Linux username character limit', function () { | ||
var pkg = require('./fixtures/my-super-long-long-long-long-cat-api'); | ||
var expected = loadFixture('my-super-long-long-long-long-cat-api.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('truncates the service name if over the Linux username character limit', () => { | ||
const pkg = require('./fixtures/my-super-long-long-long-long-cat-api'); | ||
const expected = loadFixture('my-super-long-long-long-long-cat-api.spec'); | ||
const spec = createSpecFile(pkg); | ||
@@ -22,6 +24,6 @@ assert.equal(spec, expected); | ||
it('removes the prune step when specified', function () { | ||
var pkg = require('./fixtures/my-cool-api-no-prune'); | ||
var expected = loadFixture('my-cool-api-no-prune.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('removes the prune step when specified', () => { | ||
const pkg = require('./fixtures/my-cool-api-no-prune'); | ||
const expected = loadFixture('my-cool-api-no-prune.spec'); | ||
const spec = createSpecFile(pkg); | ||
@@ -31,7 +33,7 @@ assert.equal(spec, expected); | ||
it('sets the release number when specified', function () { | ||
var releaseNumber = 7; | ||
var pkg = require('./fixtures/my-cool-api'); | ||
var expected = loadFixture('my-cool-api-7.spec'); | ||
var spec = createSpecFile(pkg, releaseNumber); | ||
it('sets the release number when specified', () => { | ||
const releaseNumber = 7; | ||
const pkg = require('./fixtures/my-cool-api'); | ||
const expected = loadFixture('my-cool-api-7.spec'); | ||
const spec = createSpecFile(pkg, releaseNumber); | ||
@@ -41,6 +43,6 @@ assert.equal(spec, expected); | ||
it('requires a particular node version when specified', function () { | ||
var pkg = require('./fixtures/my-cool-api-with-node-version'); | ||
var expected = loadFixture('my-cool-api-with-node-version.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('requires a particular node version when specified', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-node-version'); | ||
const expected = loadFixture('my-cool-api-with-node-version.spec'); | ||
const spec = createSpecFile(pkg); | ||
@@ -50,6 +52,6 @@ assert.equal(spec, expected); | ||
it('adds all of the required packages from the spec.requires property in package.json', function () { | ||
var pkg = require('./fixtures/my-cool-api-with-requires'); | ||
var expected = loadFixture('my-cool-api-with-requires.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('adds all of the required packages from the spec.requires property in package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-requires'); | ||
const expected = loadFixture('my-cool-api-with-requires.spec'); | ||
const spec = createSpecFile(pkg); | ||
@@ -59,6 +61,6 @@ assert.equal(spec, expected); | ||
it('adds all of the required packages from the spec.buildRequires property in package.json', function () { | ||
var pkg = require('./fixtures/my-cool-api-with-buildrequires'); | ||
var expected = loadFixture('my-cool-api-with-buildrequires.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('adds all of the required packages from the spec.buildRequires property in package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-buildrequires'); | ||
const expected = loadFixture('my-cool-api-with-buildrequires.spec'); | ||
const spec = createSpecFile(pkg); | ||
@@ -68,6 +70,6 @@ assert.equal(spec, expected); | ||
it('adds all of the executable files from the spec.executable property in package.json', function () { | ||
var pkg = require('./fixtures/my-cool-api-with-executable'); | ||
var expected = loadFixture('my-cool-api-with-executable.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('adds all of the executable files from the spec.executable property in package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-executable'); | ||
const expected = loadFixture('my-cool-api-with-executable.spec'); | ||
const spec = createSpecFile(pkg); | ||
@@ -77,22 +79,22 @@ assert.equal(spec, expected); | ||
it('includes post-install actions from the spec.post property in package.json', function () { | ||
var pkg = require('./fixtures/my-cool-api-with-post'); | ||
var expected = loadFixture('my-cool-api-with-post.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('includes post-install actions from the spec.post property in package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-post'); | ||
const expected = loadFixture('my-cool-api-with-post.spec'); | ||
const spec = createSpecFile(pkg); | ||
assert.equal(spec, expected); | ||
}); | ||
it('sets the license from the package.json', function () { | ||
var pkg = require('./fixtures/my-cool-api-with-diff-licence'); | ||
var expected = loadFixture('my-cool-api-with-diff-licence.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('sets the license from the package.json', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-diff-licence'); | ||
const expected = loadFixture('my-cool-api-with-diff-licence.spec'); | ||
const spec = createSpecFile(pkg); | ||
assert.equal(spec, expected); | ||
}); | ||
it('avoid escaping the Requires and Buildrequires', function () { | ||
var pkg = require('./fixtures/my-cool-api-with-requires-noescape.json'); | ||
var expected = loadFixture('my-cool-api-with-requires-noescape.spec'); | ||
var spec = createSpecFile(pkg); | ||
it('avoid escaping the Requires and Buildrequires', () => { | ||
const pkg = require('./fixtures/my-cool-api-with-requires-noescape.json'); | ||
const expected = loadFixture('my-cool-api-with-requires-noescape.spec'); | ||
const spec = createSpecFile(pkg); | ||
assert.equal(spec, expected); | ||
}); | ||
}); |
@@ -1,14 +0,16 @@ | ||
var validator = require('../lib/validator'); | ||
var assert = require('assert'); | ||
var path = require('path'); | ||
'use strict'; | ||
describe('validator', function () { | ||
it('returns true with there is a valid package.json in the working directory', function () { | ||
var isValid = validator(path.resolve(__dirname, './fixtures/project-with-package-json')); | ||
const validator = require('../lib/validator'); | ||
const assert = require('assert'); | ||
const path = require('path'); | ||
describe('validator', () => { | ||
it('returns true with there is a valid package.json in the working directory', () => { | ||
const isValid = validator(path.resolve(__dirname, './fixtures/project-with-package-json')); | ||
assert.strictEqual(isValid, true); | ||
}); | ||
it('returns false with there is no package.json in the working directory', function () { | ||
var isValid = validator(path.resolve(__dirname, './fixtures/project-without-package-json')); | ||
it('returns false with there is no package.json in the working directory', () => { | ||
const isValid = validator(path.resolve(__dirname, './fixtures/project-without-package-json')); | ||
@@ -18,4 +20,4 @@ assert.strictEqual(isValid, false); | ||
it('returns false with there is no valid package.json in the working directory', function () { | ||
var isValid = validator(path.resolve(__dirname, './fixtures/project-with-invalid-package-json')); | ||
it('returns false with there is no valid package.json in the working directory', () => { | ||
const isValid = validator(path.resolve(__dirname, './fixtures/project-with-invalid-package-json')); | ||
@@ -22,0 +24,0 @@ assert.strictEqual(isValid, false); |
Sorry, the diff of this file is not supported yet
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
53962
4
54
892
309
6
1
1
- Removedlodash@^4.6.1
- Removedlodash@4.17.21(transitive)