From 9342a5324d5a1292f326e8adcb2d05ea0315a7b4 Mon Sep 17 00:00:00 2001 From: Christian Budde Christensen Date: Thu, 28 Jan 2016 20:46:01 +0100 Subject: [PATCH] feat: Add possibility to stop a karma server Add detached mode using the `karma start --detached` command. Add middleware for stopping a server (detached or not). Described the detached option. --- docs/config/01-configuration-file.md | 12 +++++++++ lib/cli.js | 37 +++++++++++++++++++++++++++- lib/config.js | 1 + lib/middleware/runner.js | 2 +- lib/middleware/stopper.js | 18 ++++++++++++++ lib/stopper.js | 33 +++++++++++++++++++++++++ lib/web-server.js | 2 ++ 7 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 lib/middleware/stopper.js create mode 100644 lib/stopper.js diff --git a/docs/config/01-configuration-file.md b/docs/config/01-configuration-file.md index ea58e3c0e..6f4a73348 100644 --- a/docs/config/01-configuration-file.md +++ b/docs/config/01-configuration-file.md @@ -249,6 +249,18 @@ customHeaders: [{ }] ``` + +## detached +**Type:** Boolean + +**Default:** `false` + +**CLI:** `--detached` + +**Description:** When true, this will start the karma server in another process, writing no output to the console. +The server can be stopped using the `karma stop` command. + + ## exclude **Type:** Array diff --git a/lib/cli.js b/lib/cli.js index d8198abcf..edeb56df3 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,6 +1,7 @@ var path = require('path') var optimist = require('optimist') var fs = require('graceful-fs') +var spawn = require('child_process').spawn var Server = require('./server') var helper = require('./helper') @@ -159,6 +160,7 @@ var describeStart = function () { ' $0 start [] []') .describe('port', ' Port where the server is running.') .describe('auto-watch', 'Auto watch source files and run on change.') + .describe('detached', 'Detach the server.') .describe('no-auto-watch', 'Do not watch source files.') .describe('log-level', ' Level of logging.') .describe('colors', 'Use colors when reporting and printing logs.') @@ -190,6 +192,17 @@ var describeRun = function () { .describe('no-colors', 'Do not use colors when reporting or printing logs.') } +var describeStop = function () { + optimist + .usage('Karma - Spectacular Test Runner for JavaScript.\n\n' + + 'STOP - Stop the server (requires running server).\n\n' + + 'Usage:\n' + + ' $0 run [] []') + .describe('port', ' Port where the server is listening.') + .describe('log-level', ' Level of logging.') + .describe('help', 'Print usage.') +} + var describeCompletion = function () { optimist .usage('Karma - Spectacular Test Runner for JavaScript.\n\n' + @@ -199,6 +212,21 @@ var describeCompletion = function () { .describe('help', 'Print usage.') } +var startServer = function (config) { + var args = process.argv + var detachedIndex = args.indexOf('--detached') + if (detachedIndex === -1) { + new Server(config).start() + return + } + args.splice(detachedIndex, 1) + var child = spawn(args[0], args.slice(1), { + detached: true, + stdio: ['ignore', 'ignore', 'ignore'] + }) + child.unref() +} + exports.process = function () { var argv = optimist.parse(argsBeforeDoubleDash(process.argv.slice(2))) var options = { @@ -215,6 +243,10 @@ exports.process = function () { options.clientArgs = parseClientArgs(process.argv) break + case 'stop': + describeStop() + break + case 'init': describeInit() break @@ -243,11 +275,14 @@ exports.run = function () { switch (config.cmd) { case 'start': - new Server(config).start() + startServer(config) break case 'run': require('./runner').run(config) break + case 'stop': + require('./stopper').stop(config) + break case 'init': require('./init').init(config) break diff --git a/lib/config.js b/lib/config.js index 40621b402..b4a3accdc 100644 --- a/lib/config.js +++ b/lib/config.js @@ -266,6 +266,7 @@ var Config = function () { this.concurrency = Infinity this.failOnEmptyTestSuite = true this.retryLimit = 2 + this.detached = false } var CONFIG_SYNTAX_HELP = ' module.exports = function(config) {\n' + diff --git a/lib/middleware/runner.js b/lib/middleware/runner.js index 00f03e201..7c0d13dbc 100644 --- a/lib/middleware/runner.js +++ b/lib/middleware/runner.js @@ -1,5 +1,5 @@ /** - * Runner middleware is reponsible for communication with `karma run`. + * Runner middleware is responsible for communication with `karma run`. * * It basically triggers a test run and streams stdout back. */ diff --git a/lib/middleware/stopper.js b/lib/middleware/stopper.js new file mode 100644 index 000000000..ecd2b0b90 --- /dev/null +++ b/lib/middleware/stopper.js @@ -0,0 +1,18 @@ +/** + * Stopper middleware is responsible for communicating with `karma stop`. + */ + +var log = require('../logger').create('middleware:stopper') + +var createStopperMiddleware = function (urlRoot) { + return function (request, response, next) { + if (request.url !== urlRoot + 'stop') return next() + response.writeHead(200) + log.info('Stopping server') + response.end('OK') + process.exit(0) + } +} + +createStopperMiddleware.$inject = ['config.urlRoot'] +exports.create = createStopperMiddleware diff --git a/lib/stopper.js b/lib/stopper.js new file mode 100644 index 000000000..ebf69f081 --- /dev/null +++ b/lib/stopper.js @@ -0,0 +1,33 @@ +var http = require('http') + +var cfg = require('./config') +var logger = require('./logger') + +exports.stop = function (config) { + logger.setupFromConfig(config) + var log = logger.create('stopper') + config = cfg.parseConfig(config.configFile, config) + var options = { + hostname: config.hostname, + path: config.urlRoot + 'stop', + port: config.port, + method: 'GET' + } + + var request = http.request(options) + + request.on('response', function (response) { + log.info('Server stopped.') + process.exit(response.statusCode === 200) + }) + + request.on('error', function (e) { + if (e.code === 'ECONNREFUSED') { + log.error('There is no server listening on port %d', options.port) + process.exit(1, e.code) + } else { + throw e + } + }) + request.end() +} diff --git a/lib/web-server.js b/lib/web-server.js index 4dfc248c7..fc5e7eb99 100644 --- a/lib/web-server.js +++ b/lib/web-server.js @@ -7,6 +7,7 @@ var Promise = require('bluebird') var common = require('./middleware/common') var runnerMiddleware = require('./middleware/runner') +var stopperMiddleware = require('./middleware/stopper') var stripHostMiddleware = require('./middleware/strip_host') var karmaMiddleware = require('./middleware/karma') var sourceFilesMiddleware = require('./middleware/source_files') @@ -56,6 +57,7 @@ var createWebServer = function (injector, emitter, fileList) { var handler = connect() .use(injector.invoke(runnerMiddleware.create)) + .use(injector.invoke(stopperMiddleware.create)) .use(injector.invoke(stripHostMiddleware.create)) .use(injector.invoke(karmaMiddleware.create)) .use(injector.invoke(sourceFilesMiddleware.create))