From 719806432eb18ca6afdc3ca62fbb2aacd72e4f15 Mon Sep 17 00:00:00 2001 From: Elliott Foster Date: Mon, 22 Feb 2016 17:08:07 -0600 Subject: [PATCH 1/2] 1.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28905be..ba4c6fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adios", - "version": "1.1.1", + "version": "1.1.2", "description": "A simple module for handling shutdowns within a clustered application.", "main": "lib/adios.js", "scripts": { From 86ae94211a6c10c0e7ade0d244d53d632a93b6f8 Mon Sep 17 00:00:00 2001 From: Elliott Foster Date: Tue, 1 Nov 2016 17:29:32 -0500 Subject: [PATCH 2/2] feat(semantic-release): Adding semantic release * Adding semantic release * Updating eslint config BREAKING CHANGE: ES6 features that are only supported in node 6 and higher now appear in the codebase. --- .eslintrc | 80 ---------------------------------- .eslintrc.json | 28 ++++++++++++ .travis.yml | 28 +++++++++--- lib/adios.js | 9 +++- lib/child.js | 9 ++-- lib/master.js | 25 ++++++----- package.json | 13 +++--- test/.eslintrc.json | 9 ++++ test/child.js | 28 +++++++----- test/index.js | 3 +- test/master.js | 103 +++++++++++++++++++++++++------------------- test/testWorker.js | 7 +-- 12 files changed, 177 insertions(+), 165 deletions(-) delete mode 100644 .eslintrc create mode 100644 .eslintrc.json create mode 100644 test/.eslintrc.json diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index b81c631..0000000 --- a/.eslintrc +++ /dev/null @@ -1,80 +0,0 @@ -{ - "env": { - "browser": false, - "node": true, - "es6": true - }, - "rules": { - "block-scoped-var": 2, - "camelcase": 2, - "comma-dangle": [2, "never"], - "complexity": 2, - "consistent-return": 2, - "curly": 2, - "default-case": 2, - "dot-location": [2, "property"], - "dot-notation": 2, - "eol-last": 2, - "eqeqeq": 2, - "guard-for-in": 2, - "indent": [2, 2], - "keyword-spacing": 2, - "no-alert": 2, - "no-caller": 2, - "no-div-regex": 2, - "no-dupe-args": 2, - "no-dupe-keys": 2, - "no-else-return": 2, - "no-empty": 2, - "no-eq-null": 2, - "no-eval": 2, - "no-extra-bind": 1, - "no-extra-boolean-cast": 2, - "no-extra-semi": 2, - "semi": 2, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-func-assign": 2, - "no-implied-eval": 2, - "no-inner-declarations": 2, - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-lone-blocks": 2, - "no-loop-func": 2, - "no-mixed-spaces-and-tabs": 2, - "no-multi-spaces": 2, - "no-multi-str": 2, - "no-native-reassign": 2, - "no-negated-in-lhs": 2, - "no-new": 2, - "no-new-wrappers": 2, - "no-obj-calls": 2, - "no-regex-spaces": 2, - "no-return-assign": 2, - "no-script-url": 2, - "no-self-compare": 2, - "no-sparse-arrays": 2, - "no-throw-literal": 2, - "no-trailing-spaces": 2, - "no-underscore-dangle": 0, - "no-unreachable": 2, - "no-unused-expressions": 0, - "no-unused-vars": 2, - "no-use-before-define": [2, "nofunc"], - "no-warning-comments": 1, - "quotes": [2, "single"], - "radix": 2, - "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], - "space-infix-ops": 2, - "object-curly-spacing": [2, "never"], - "array-bracket-spacing": [2, "never"], - "space-unary-ops": [1, { "words": true, "nonwords": false }], - "strict": [0, "never"], - "use-isnan": 2, - "valid-jsdoc": [2, {"requireReturn": false}], - "valid-typeof": 2, - "vars-on-top": 0, - "wrap-iife": 2, - "yoda": 2 - } -} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..f0cfd60 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,28 @@ +{ + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "script" + }, + "extends": "airbnb-base", + "rules": { + "brace-style": ["error", "stroustrup"], + "max-len": ["warn", { + "code": 100, + "comments": 80, + "ignoreUrls": true, + "ignorePattern": "(logger\\.|new Error\\)|new TypeError\\()", + "ignoreTrailingComments": true, + "tabWidth": 2 + }], + "no-warning-comments": "warn", + "quotes": ["error", "single", {"avoidEscape": true, "allowTemplateLiterals": true}], + "require-jsdoc": ["error", { + "require": { + "FunctionDeclaration": true, + "MethodDefinition": true, + "ClassDeclaration": true + } + }], + "valid-jsdoc": "error" + } +} diff --git a/.travis.yml b/.travis.yml index 6f2f7f3..4d77d50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,24 @@ -language: node_js sudo: false +language: node_js +cache: + directories: + - node_modules +notifications: + email: false node_js: - - "4" - - "node" -script: npm run lint && npm test && npm run coverage -after_success: npm run coveralls - + - '6' + - 'node' +before_install: + - npm i -g npm@^2.0.0 +before_script: + - npm prune +script: npm run lint && npm t +after_success: + - npm run coveralls + - 'curl -Lo travis_after_all.py https://git.io/travis_after_all' + - python travis_after_all.py + - export $(cat .to_export_back) &> /dev/null + - npm run semantic-release +branches: + except: + - /^v\d+\.\d+\.\d+$/ diff --git a/lib/adios.js b/lib/adios.js index c012ce8..2c51bd1 100644 --- a/lib/adios.js +++ b/lib/adios.js @@ -1,4 +1,9 @@ +'use strict'; + +const master = require('./master'); +const child = require('./child'); + module.exports = { - master: require('./master'), - child: require('./child') + master, + child, }; diff --git a/lib/child.js b/lib/child.js index 137856d..b2dcae7 100644 --- a/lib/child.js +++ b/lib/child.js @@ -1,4 +1,5 @@ 'use strict'; + const cluster = require('cluster'); const net = require('net'); @@ -34,13 +35,13 @@ module.exports = { return new Promise((resolve, reject) => { socket = net.connect(path || DEFAULT_PATH, () => { - socket.write('pid:' + process.pid); + socket.write(`pid:${process.pid}`); resolve(); }) .setKeepAlive(true) .on('data', (msg) => { - msg = msg.toString(); - if (msg === 'SIGINT') { + const msgStr = msg.toString(); + if (msgStr === 'SIGINT') { cleanCb() .then(() => { socket.end(); @@ -56,6 +57,6 @@ module.exports = { socket.destroy(); socket = null; } - } + }, }; diff --git a/lib/master.js b/lib/master.js index a7c6775..a70dd9e 100644 --- a/lib/master.js +++ b/lib/master.js @@ -1,4 +1,5 @@ 'use strict'; + const cluster = require('cluster'); const net = require('net'); @@ -29,10 +30,12 @@ function eachWorker(cb) { * * @param {int} killTimeout * Time in milliseconds to wait before forcefully killing a child process. + * + * @return {undefined} */ function sigint(killTimeout) { - let shutdowns = eachWorker(worker => new Promise(resolve => { - let timeout = setTimeout(() => { + const shutdowns = eachWorker(worker => new Promise((resolve) => { + const timeout = setTimeout(() => { if (workerSockets[worker.process.pid]) { workerSockets[worker.process.pid].end(); } @@ -65,6 +68,8 @@ function sigint(killTimeout) { /** * A SIGTERM listener. Force kills all workers and exits the master process. + * + * @return {undefined} */ function sigterm() { eachWorker(worker => worker.kill()); @@ -99,13 +104,13 @@ module.exports = { const timeout = (config && config.timeout) || 10000; - return new Promise(resolve => { - server = net.createServer(c => { + return new Promise((resolve) => { + server = net.createServer((c) => { let pid; - c.on('data', msg => { - msg = msg.toString(); - if (msg.indexOf('pid:') !== -1) { - pid = msg.split(':')[1]; + c.on('data', (msg) => { + const msgStr = msg.toString(); + if (msgStr.startsWith('pid:')) { + pid = msgStr.split(':')[1]; workerSockets[pid] = c; } }); @@ -136,7 +141,7 @@ module.exports = { workerSockets = {}; if (server) { - return new Promise(resolve => { + return new Promise((resolve) => { server.close(() => { server = null; resolve(); @@ -145,6 +150,6 @@ module.exports = { } return Promise.resolve(); - } + }, }; diff --git a/package.json b/package.json index ba4c6fc..32d3fe6 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "adios", - "version": "1.1.2", "description": "A simple module for handling shutdowns within a clustered application.", "main": "lib/adios.js", "scripts": { "test": "istanbul cover --print both nodeunit ./test/index.js", "lint": "eslint .", "coverage": "istanbul check-coverage --statements 100 --lines 100 --branches 81 --functions 100", - "coveralls": "cat ./coverage/lcov.info | coveralls" + "coveralls": "cat ./coverage/lcov.info | coveralls", + "semantic-release": "semantic-release pre && npm publish && semantic-release post" }, "repository": { "type": "git", @@ -20,15 +20,18 @@ "author": "Elliott Foster (http://codebrews.com/)", "license": "MIT", "engines": { - "node": ">= 4.2" + "node": ">= 6" }, "devDependencies": { "coveralls": "^2.11.6", - "eslint": "^2.2.0", + "eslint": "^3.9.1", + "eslint-config-airbnb-base": "^9.0.0", + "eslint-plugin-import": "^2.0.0", "ghooks": "^1.0.1", "istanbul": "^0.4.2", "nodeunit": "^0.9.1", - "sinon": "^1.17.2" + "sinon": "^1.17.2", + "semantic-release": "^4.3.5" }, "config": { "defaultPath": "/var/run/adios.sock", diff --git a/test/.eslintrc.json b/test/.eslintrc.json new file mode 100644 index 0000000..217444a --- /dev/null +++ b/test/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "rules": { + "class-methods-use-this": "off", + "global-require": "off", + "require-jsdoc": "off", + "import/no-extraneous-dependencies": "off" + } +} + diff --git a/test/child.js b/test/child.js index 47b2f29..2526aa7 100644 --- a/test/child.js +++ b/test/child.js @@ -1,9 +1,17 @@ 'use strict'; + const cluster = require('cluster'); const net = require('net'); const sinon = require('sinon'); const Adios = require('../'); +/** + * Noop + * @return {undefined} + */ +function noop() { +} + module.exports = { tearDown(cb) { if (this.server) { @@ -22,7 +30,7 @@ module.exports = { test.expect(1); Adios.master.destroy(); - Adios.child.init(console.log) + Adios.child.init(noop) .then(test.done) .catch(() => { test.ok(true, 'Error connecting caught.'); @@ -52,22 +60,22 @@ module.exports = { test.expect(2); test.doesNotThrow(() => { - Adios.child.init(console.log, this.testSock); + Adios.child.init(noop, this.testSock); }, 'Child not initialized.'); test.throws(() => { - Adios.child.init(console.log); + Adios.child.init(noop); }, 'Child initialized twice.'); test.done(); - } + }, }, comm: { announcePid(test) { test.expect(1); - this.server = net.createServer(c => { - c.on('data', msg => { + this.server = net.createServer((c) => { + c.on('data', (msg) => { Adios.child.destroy(); test.equal(msg.toString().indexOf('pid:'), 0, 'Pid not announced.'); test.done(); @@ -75,13 +83,13 @@ module.exports = { }); this.server.listen(this.testSock, () => { cluster.isMaster = false; - Adios.child.init(console.log, this.testSock); + Adios.child.init(noop, this.testSock); }); }, sigint(test) { test.expect(2); - this.stubs.push(sinon.stub(process, 'exit', code => { + this.stubs.push(sinon.stub(process, 'exit', (code) => { test.equal(0, code, 'Process did not exit cleanly.'); test.done(); })); @@ -94,7 +102,7 @@ module.exports = { return Promise.resolve(); }, this.testSock); }); - } - } + }, + }, }; diff --git a/test/index.js b/test/index.js index 0766218..6e46f36 100644 --- a/test/index.js +++ b/test/index.js @@ -1,4 +1,5 @@ 'use strict'; + const cluster = require('cluster'); const os = require('os'); const path = require('path'); @@ -25,6 +26,6 @@ module.exports = { }); }, master: require('./master'), - child: require('./child') + child: require('./child'), }; diff --git a/test/master.js b/test/master.js index f18b201..06ddb55 100644 --- a/test/master.js +++ b/test/master.js @@ -1,8 +1,8 @@ 'use strict'; + const cluster = require('cluster'); const net = require('net'); const sinon = require('sinon'); -const util = require('util'); const Adios = require('../'); const EventEmitter = require('events'); @@ -38,7 +38,7 @@ module.exports = { childFail(test) { test.expect(1); - sinon.stub(net.Server.prototype, 'close', function (cb) { + sinon.stub(net.Server.prototype, 'close', function close(cb) { test.throws(() => { cb(); }, 'Exception not thrown'); @@ -53,7 +53,7 @@ module.exports = { cluster.workers.foo = {}; process.kill(process.pid, 'SIGINT'); }); - } + }, }, comm: { end(test) { @@ -61,19 +61,19 @@ module.exports = { Adios.master.init(this.testSock) .then(() => { - let conn = net.connect(this.testSock, () => { + const conn = net.connect(this.testSock, () => { conn.end(); test.ok(true); test.done(); }); }); - } + }, }, sigint: { noWorkers(test) { test.expect(1); - this.stubs.push(sinon.stub(process, 'exit', code => { + this.stubs.push(sinon.stub(process, 'exit', (code) => { test.equal(0, code, 'Process did not termincate cleanly'); test.done(); })); @@ -86,26 +86,30 @@ module.exports = { workerShutdown(test) { test.expect(3); - this.stubs.push(sinon.stub(process, 'exit', code => { + this.stubs.push(sinon.stub(process, 'exit', (code) => { delete cluster.workers.foo; test.equal(0, code, 'Process did not termincate cleanly'); test.done(); })); - var DummyWorker = function () { - this.process = {pid: 'foo'}; - EventEmitter.call(this); - }; - util.inherits(DummyWorker, EventEmitter); - DummyWorker.prototype.disconnect = function () { - test.ok(true, 'Disconnect called'); - this.emit('disconnect'); - }; + class DummyWorker extends EventEmitter { + constructor() { + super(); + this.process = { pid: 'foo' }; + EventEmitter.call(this); + } + + disconnect() { + test.ok(true, 'Disconnect called'); + this.emit('disconnect'); + } + } + cluster.workers.foo = new DummyWorker(); Adios.master.init(this.testSock) .then(() => { - let conn = net.connect(this.testSock, () => { + const conn = net.connect(this.testSock, () => { conn.write('pid:foo', () => { this.clock.restore(); setTimeout(() => { @@ -114,69 +118,80 @@ module.exports = { }, 10); }); }); - conn.on('data', msg => { + conn.on('data', (msg) => { test.equal('SIGINT', msg.toString(), 'SIGINT not announced.'); }); }); }, workerTimeout(test) { test.expect(3); + let clock = this.clock; - this.stubs.push(sinon.stub(process, 'exit', code => { + this.stubs.push(sinon.stub(process, 'exit', (code) => { delete cluster.workers.foo; test.equal(0, code, 'Process did not termincate cleanly'); test.done(); })); - var DummyWorker = function () { - this.process = {pid: 'foo'}; - EventEmitter.call(this); - }; - util.inherits(DummyWorker, EventEmitter); - DummyWorker.prototype.disconnect = function () { - test.ok(true, 'Disconnect called'); - this.clock.tick(1); - }.bind(this); - DummyWorker.prototype.kill = function () { - test.ok(true, 'Kill called'); - }; + class DummyWorker extends EventEmitter { + constructor() { + super(); + this.process = { pid: 'foo' }; + EventEmitter.call(this); + } + + disconnect() { + test.ok(true, 'Disconnect called'); + clock.tick(1); + } + + kill() { + test.ok(true, 'Kill called'); + } + } + cluster.workers.foo = new DummyWorker(); - Adios.master.init(this.testSock, {timeout: 1}) + Adios.master.init(this.testSock, { timeout: 1 }) .then(() => { - let conn = net.connect(this.testSock, () => { + const conn = net.connect(this.testSock, () => { conn.write('pid:foo', () => { this.clock.restore(); setTimeout(() => { this.clock = sinon.useFakeTimers(); + clock = this.clock; process.kill(process.pid, 'SIGINT'); }, 10); }); }); }); - } + }, }, sigterm(test) { test.expect(2); - this.stubs.push(sinon.stub(process, 'exit', code => { + this.stubs.push(sinon.stub(process, 'exit', (code) => { test.equal(0, code, 'Process did not termincate cleanly'); test.done(); })); - var DummyWorker = function () { - this.process = {pid: 'foo'}; - EventEmitter.call(this); - }; - util.inherits(DummyWorker, EventEmitter); - DummyWorker.prototype.kill = function () { - test.ok(true, 'Kill called'); - }; + class DummyWorker extends EventEmitter { + constructor() { + super(); + this.process = { pid: 'foo' }; + EventEmitter.call(this); + } + + kill() { + test.ok(true, 'Kill called'); + } + } + cluster.workers.foo = new DummyWorker(); Adios.master.init(this.testSock) .then(() => { process.kill(process.pid, 'SIGTERM'); }); - } + }, }; diff --git a/test/testWorker.js b/test/testWorker.js index efaf56b..4b533d9 100644 --- a/test/testWorker.js +++ b/test/testWorker.js @@ -1,7 +1,8 @@ 'use strict'; + const Adios = require('../'); -Adios.child.init(() => { - return Promise.resolve(); -}, process.env.testSock); +Adios.child.init(() => + Promise.resolve() +, process.env.testSock);