From 205f6396272cfb3db1720774822fe82ba800d621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=B3=96=E9=A5=BC?= Date: Thu, 20 Jul 2017 17:17:04 +0800 Subject: [PATCH 1/5] refactor: child_process.exec > child_process.spawn --- README.ZH-CN.md | 8 +- README.md | 8 +- lib/run-cmd.js | 109 +++++++++++++++++++ lib/spawn.js | 32 ++++++ lib/worker.js | 82 -------------- src/build.js | 2 +- test/lib/{worker.test.js => run-cmd.test.js} | 3 +- 7 files changed, 155 insertions(+), 89 deletions(-) create mode 100644 lib/run-cmd.js create mode 100644 lib/spawn.js delete mode 100644 lib/worker.js rename test/lib/{worker.test.js => run-cmd.test.js} (92%) diff --git a/README.ZH-CN.md b/README.ZH-CN.md index b5bb7f8..15082b5 100644 --- a/README.ZH-CN.md +++ b/README.ZH-CN.md @@ -140,9 +140,13 @@ ci-task-runner 缓存文件写入路径,用来保存上一次任务的信息 #### `program.options` -进程配置。参考:[child_process.exec](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)。 +设置进程的选项。 -> `program.options` 中的 `timeout` 字段生效后会终止进程,并且抛出错误。这点和 `child_process.exec` 不一样,它只抛出错误。 +* `cwd` 当前子进程的工作目录 +* `env` 环境变量 +* `timeout` 超时时间 +* `uid` 设置进程的用户标识 +* `gid` 设置进程的组标识 #### 变量 diff --git a/README.md b/README.md index d133e0e..7221598 100644 --- a/README.md +++ b/README.md @@ -139,9 +139,13 @@ Setting start command. #### `program.options` -Progress configuration. Reference: [child_process.exec](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback). +Progress configuration. -> The `timeout` field in `program.options` takes effect and terminates the process and throws an error. `child_process.exec` only throw error. +* `cwd` Current working directory of the child process +* `env` Environment key-value pairs +* `timeout` Timeout +* `uid` Sets the user identity of the process +* `gid` Sets the group identity of the process #### Variable diff --git a/lib/run-cmd.js b/lib/run-cmd.js new file mode 100644 index 0000000..6ff5f93 --- /dev/null +++ b/lib/run-cmd.js @@ -0,0 +1,109 @@ +const spawn = require('./spawn'); +const npmRunPath = require('npm-run-path'); +const defaultsDeep = require('lodash.defaultsdeep'); + +const run = (cmd, { env, cwd, uid, gid }, callback) => { + const conf = { env, cwd, uid, gid, stdio: [0, 1, 2] }; + + let sh = 'sh'; + let shFlag = '-c'; + + if (process.platform === 'win32') { + sh = process.env.comspec || 'cmd'; + shFlag = '/d /s /c'; + conf.windowsVerbatimArguments = true; + } + + const proc = spawn(sh, [shFlag, cmd], conf); + + proc.on('error', procError); + proc.on('close', function (code, signal) { + let er; + if (signal) { + process.kill(process.pid, signal); + } else if (code) { + er = new Error('Exit status ' + code); + er.errno = code; + procError(er) + } else { + callback(null); + } + }) + process.once('SIGTERM', procKill); + process.once('SIGINT', procInterupt); + + function procError(er) { + if (er) { + if (er.code !== 'EPERM') { + er.code = 'ELIFECYCLE'; + } + } + process.removeListener('SIGTERM', procKill); + process.removeListener('SIGTERM', procInterupt); + process.removeListener('SIGINT', procKill); + return callback(er); + } + + function procKill() { + proc.kill(); + } + + function procInterupt() { + proc.kill('SIGINT'); + proc.on('exit', function () { + process.exit(); + }); + process.once('SIGINT', procKill); + } + + return { + kill: procKill + }; +}; + + +/** + * 执行命令 + * @param {string} command 命令 + * @param {Object} options 进程选项 + * @param {Object} options.env 环境变量 + * @param {string} options.cwd 工作目录 + * @param {number} options.timeout 超时时间 + * @param {number} options.uid UID + * @param {number} options.gid GID + * @return {Promise} + */ +module.exports = (command, options = {}) => { + + return new Promise((resolve, reject) => { + + options = defaultsDeep({}, options, { + env: npmRunPath.env({ + cwd: options.cwd || process.cwd(), + env: defaultsDeep({}, options.env, process.env) + }) + }); + + let timer = null; + const callback = (errors, data) => { + clearTimeout(timer); + + if (errors) { + errors.messsage = `"${command}": ${errors.messsage}`; + reject(errors); + } else { + resolve(data); + } + }; + + + const spawn = run(command, options, callback); + + if (options.timeout) { + timer = setTimeout(() => { + spawn.kill(); + callback(new Error(`child process timeout`)); + }, options.timeout); + } + }); +}; \ No newline at end of file diff --git a/lib/spawn.js b/lib/spawn.js new file mode 100644 index 0000000..cb1683e --- /dev/null +++ b/lib/spawn.js @@ -0,0 +1,32 @@ +const spawn = require('child_process').spawn +const EventEmitter = require('events').EventEmitter + +module.exports = (cmd, args, options) => { + const raw = spawn(cmd, args, options); + const cooked = new EventEmitter(); + + raw.on('error', (er) => { + er.file = cmd; + cooked.emit('error', er); + }).on('close', (code, signal) => { + // Create ENOENT error because Node.js v0.8 will not emit + // an `error` event if the command could not be found. + if (code === 127) { + const er = new Error('spawn ENOENT'); + er.code = 'ENOENT'; + er.errno = 'ENOENT'; + er.syscall = 'spawn'; + er.file = cmd; + cooked.emit('error', er); + } else { + cooked.emit('close', code, signal); + } + }) + + cooked.stdin = raw.stdin; + cooked.stdout = raw.stdout; + cooked.stderr = raw.stderr; + cooked.kill = sig => raw.kill(sig); + + return cooked +}; \ No newline at end of file diff --git a/lib/worker.js b/lib/worker.js deleted file mode 100644 index 3603a03..0000000 --- a/lib/worker.js +++ /dev/null @@ -1,82 +0,0 @@ -const childProcess = require('child_process'); -const defaultsDeep = require('lodash.defaultsdeep'); -const npmRunPath = require('npm-run-path'); - - -/** - * 使用子进程运行命令 - * @see https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback - * @param {string} command 命令 - * @param {Object} options 进程选项 - * @return {Promise} - */ -module.exports = (command, options = {}) => { - - return new Promise((resolve, reject) => { - - options = defaultsDeep({}, options, { - // 子进程继承父进程的环境变量 - env: process.env - }, { - // 使用 npm 的 PATH - env: npmRunPath.env({ - cwd: options.cwd || process.cwd() - }) - }); - - - let child; - let closed; - let timer = null; - - try { - child = childProcess.exec(command, options); - } catch (errors) { - callback(errors); - } - - child.stdout.on('data', content => { - process.stdout.write(content); - }); - - child.stderr.on('data', content => { - process.stderr.write(content); - }); - - - child.on('exit', (code, signal) => { - if (code === 0) { - callback(null); - } else { - callback(new Error(`exec "${command}": child process terminated due to receipt of signal ${signal}`)); - } - }); - - - // 解决 node timeout 不会走异常流程的问题 - if (options.timeout) { - timer = setTimeout(() => { - callback(new Error(`exec "${command}": child process timeout`)); - child.kill(); - }, options.timeout); - } - - - function callback(errors, data) { - if (closed) { - return; - } else { - closed = true; - } - - clearTimeout(timer); - - if (errors) { - errors.messsage = `exec "${command}": ${errors.messsage}`; - reject(errors); - } else { - resolve(data); - } - } - }); -}; \ No newline at end of file diff --git a/src/build.js b/src/build.js index 8bb9b9b..eab2468 100644 --- a/src/build.js +++ b/src/build.js @@ -1,6 +1,6 @@ const promiseTask = require('../lib/promise-task'); const Loger = require('../lib/loger'); -const worker = require('../lib/worker'); +const worker = require('../lib/run-cmd'); const PACKAGE = require('../package.json'); diff --git a/test/lib/worker.test.js b/test/lib/run-cmd.test.js similarity index 92% rename from test/lib/worker.test.js rename to test/lib/run-cmd.test.js index 3581ae0..612a76c 100644 --- a/test/lib/worker.test.js +++ b/test/lib/run-cmd.test.js @@ -1,6 +1,5 @@ -const path = require('path'); const assert = require('assert'); -const worker = require('../../lib/worker'); +const worker = require('../../lib/run-cmd'); describe('#worker', () => { it('exec script', () => { From d2d880a7b0986f4aefa70cf9ee8f5f3405ee93a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=B3=96=E9=A5=BC?= Date: Thu, 20 Jul 2017 17:29:56 +0800 Subject: [PATCH 2/5] refactor: lib > src --- CHANGELOG.md | 4 ++++ package.json | 2 +- {lib => src}/fs-promise.js | 0 src/index.js | 12 ++++++------ {lib => src}/loger.js | 0 src/parse.js | 2 +- {lib => src}/promise-task.js | 0 {lib => src}/promiseify.js | 0 {lib => src}/repository.js | 0 {lib => src}/run-cmd.js | 0 src/{build.js => run-tasks.js} | 6 +++--- {lib => src}/spawn.js | 0 {lib => src}/template.js | 0 test/{lib => }/fs-promise.test.js | 4 ++-- test/{src => }/index.test.js | 0 test/{lib => }/loger.test.js | 2 +- test/{src => }/parse.test.js | 2 +- test/{lib => }/promise-task.test.js | 2 +- test/{lib => }/promiseify.test.js | 4 ++-- test/{lib => }/repository.test.js | 6 +++--- test/{lib => }/run-cmd.test.js | 2 +- test/{lib => }/template.test.js | 2 +- 22 files changed, 27 insertions(+), 23 deletions(-) rename {lib => src}/fs-promise.js (100%) rename {lib => src}/loger.js (100%) rename {lib => src}/promise-task.js (100%) rename {lib => src}/promiseify.js (100%) rename {lib => src}/repository.js (100%) rename {lib => src}/run-cmd.js (100%) rename src/{build.js => run-tasks.js} (92%) rename {lib => src}/spawn.js (100%) rename {lib => src}/template.js (100%) rename test/{lib => }/fs-promise.test.js (81%) rename test/{src => }/index.test.js (100%) rename test/{lib => }/loger.test.js (98%) rename test/{src => }/parse.test.js (99%) rename test/{lib => }/promise-task.test.js (98%) rename test/{lib => }/promiseify.test.js (56%) rename test/{lib => }/repository.test.js (73%) rename test/{lib => }/run-cmd.test.js (95%) rename test/{lib => }/template.test.js (88%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0caa6f..29aa7eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.0.4 + +1. 修复日志太多可能产生的溢出问题 [#11](https://github.com/huanleguang/ci-task-runner/issues/11) + ## v1.0.3 1. 修复子进程意外退出后的错误信息显示 diff --git a/package.json b/package.json index 3f3820a..6f954a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ci-task-runner", - "version": "1.0.3", + "version": "1.0.4-beta", "description": "this is a multiprocess building tasks scheduler", "main": "src/index.js", "bin": "bin/ci-task-runner", diff --git a/lib/fs-promise.js b/src/fs-promise.js similarity index 100% rename from lib/fs-promise.js rename to src/fs-promise.js diff --git a/src/index.js b/src/index.js index 6683f3a..a048a03 100644 --- a/src/index.js +++ b/src/index.js @@ -1,16 +1,16 @@ const path = require('path'); const findCacheDir = require('find-cache-dir'); -const fsp = require('../lib/fs-promise'); +const fsp = require('./fs-promise'); const defaultsDeep = require('lodash.defaultsdeep'); -const promiseTask = require('../lib/promise-task'); -const Repository = require('../lib/repository'); -const Loger = require('../lib/loger'); +const promiseTask = require('./promise-task'); +const Repository = require('./repository'); +const Loger = require('./loger'); const DEFAULT = require('./config/config.default.json'); const CACHE_DEFAULT = require('./config/cache.default.json'); const PACKAGE = require('../package.json'); const parse = require('./parse'); -const build = require('./build'); +const runTasks = require('./run-tasks'); /** @@ -102,7 +102,7 @@ const taskRunner = (options = {}, context = process.cwd()) => { // 运行构建器 tasks => { - return build(tasks, options.parallel); + return runTasks(tasks, options.parallel); }, diff --git a/lib/loger.js b/src/loger.js similarity index 100% rename from lib/loger.js rename to src/loger.js diff --git a/src/parse.js b/src/parse.js index 765fe95..72360c9 100644 --- a/src/parse.js +++ b/src/parse.js @@ -1,5 +1,5 @@ const path = require('path'); -const template = require('../lib/template'); +const template = require('./template'); const defaultsDeep = require('lodash.defaultsdeep'); const DEFAULT = require('./config/config.program.default.json'); diff --git a/lib/promise-task.js b/src/promise-task.js similarity index 100% rename from lib/promise-task.js rename to src/promise-task.js diff --git a/lib/promiseify.js b/src/promiseify.js similarity index 100% rename from lib/promiseify.js rename to src/promiseify.js diff --git a/lib/repository.js b/src/repository.js similarity index 100% rename from lib/repository.js rename to src/repository.js diff --git a/lib/run-cmd.js b/src/run-cmd.js similarity index 100% rename from lib/run-cmd.js rename to src/run-cmd.js diff --git a/src/build.js b/src/run-tasks.js similarity index 92% rename from src/build.js rename to src/run-tasks.js index eab2468..69d12f8 100644 --- a/src/build.js +++ b/src/run-tasks.js @@ -1,6 +1,6 @@ -const promiseTask = require('../lib/promise-task'); -const Loger = require('../lib/loger'); -const worker = require('../lib/run-cmd'); +const promiseTask = require('./promise-task'); +const Loger = require('./loger'); +const worker = require('./run-cmd'); const PACKAGE = require('../package.json'); diff --git a/lib/spawn.js b/src/spawn.js similarity index 100% rename from lib/spawn.js rename to src/spawn.js diff --git a/lib/template.js b/src/template.js similarity index 100% rename from lib/template.js rename to src/template.js diff --git a/test/lib/fs-promise.test.js b/test/fs-promise.test.js similarity index 81% rename from test/lib/fs-promise.test.js rename to test/fs-promise.test.js index 957e4b5..0db4a59 100644 --- a/test/lib/fs-promise.test.js +++ b/test/fs-promise.test.js @@ -1,9 +1,9 @@ const path = require('path'); const assert = require('assert'); -const fsPromise = require('../../lib/fs-promise'); +const fsPromise = require('../src/fs-promise'); describe('#fs-promise', () => { - const dist = path.join(process.env.TEST_DIST, 'lib', 'fs-promise', 'test.json'); + const dist = path.join(process.env.TEST_DIST, 'src', 'fs-promise', 'test.json'); const json = { type: 'test' }; it('write file && read file', () => { diff --git a/test/src/index.test.js b/test/index.test.js similarity index 100% rename from test/src/index.test.js rename to test/index.test.js diff --git a/test/lib/loger.test.js b/test/loger.test.js similarity index 98% rename from test/lib/loger.test.js rename to test/loger.test.js index 25e96e7..28230e5 100644 --- a/test/lib/loger.test.js +++ b/test/loger.test.js @@ -1,5 +1,5 @@ const assert = require('assert'); -const Loger = require('../../lib/loger'); +const Loger = require('../src/loger'); describe('#loger', () => { diff --git a/test/src/parse.test.js b/test/parse.test.js similarity index 99% rename from test/src/parse.test.js rename to test/parse.test.js index 24583fd..4fd0345 100644 --- a/test/src/parse.test.js +++ b/test/parse.test.js @@ -1,6 +1,6 @@ const assert = require('assert'); const path = require('path'); -const parse = require('../../src/parse'); +const parse = require('../src/parse'); const defaultsDeep = require('lodash.defaultsdeep'); diff --git a/test/lib/promise-task.test.js b/test/promise-task.test.js similarity index 98% rename from test/lib/promise-task.test.js rename to test/promise-task.test.js index 9522c47..573c34a 100644 --- a/test/lib/promise-task.test.js +++ b/test/promise-task.test.js @@ -1,5 +1,5 @@ const assert = require('assert'); -const promiseTask = require('../../lib/promise-task'); +const promiseTask = require('../src/promise-task'); describe('#promise-task', () => { diff --git a/test/lib/promiseify.test.js b/test/promiseify.test.js similarity index 56% rename from test/lib/promiseify.test.js rename to test/promiseify.test.js index 96d0791..afeff39 100644 --- a/test/lib/promiseify.test.js +++ b/test/promiseify.test.js @@ -1,10 +1,10 @@ const fs = require('fs'); const path = require('path'); -const promiseify = require('../../lib/promiseify'); +const promiseify = require('../src/promiseify'); const access = promiseify(fs.access); describe('#merge', () => { it('promise', () => { - return access(path.join(__dirname, '..', '..', 'package.json')); + return access(path.join(__dirname, '..', 'package.json')); }); }); diff --git a/test/lib/repository.test.js b/test/repository.test.js similarity index 73% rename from test/lib/repository.test.js rename to test/repository.test.js index 6ab26de..b13c249 100644 --- a/test/lib/repository.test.js +++ b/test/repository.test.js @@ -1,14 +1,14 @@ const path = require('path'); const assert = require('assert'); -const Repository = require('../../lib/repository'); +const Repository = require('../src/repository'); describe('#repository', () => { - const dbPath = path.join(process.env.TEST_DIST, 'lib', 'repository', '.watch-commit.json'); + const dbPath = path.join(process.env.TEST_DIST, 'src', 'repository', '.watch-commit.json'); const repository = new Repository(dbPath); it('watch one file', () => { - let target = path.join(__dirname, '..', '..', 'package.json'); + let target = path.join(__dirname, '..', 'package.json'); return repository.watch(target, dbPath).then(([newCommitId, oldCommitId]) => { assert.deepEqual('string', typeof newCommitId); if (oldCommitId !== undefined) { diff --git a/test/lib/run-cmd.test.js b/test/run-cmd.test.js similarity index 95% rename from test/lib/run-cmd.test.js rename to test/run-cmd.test.js index 612a76c..8141a1f 100644 --- a/test/lib/run-cmd.test.js +++ b/test/run-cmd.test.js @@ -1,5 +1,5 @@ const assert = require('assert'); -const worker = require('../../lib/run-cmd'); +const worker = require('../src/run-cmd'); describe('#worker', () => { it('exec script', () => { diff --git a/test/lib/template.test.js b/test/template.test.js similarity index 88% rename from test/lib/template.test.js rename to test/template.test.js index 9200502..9bacde1 100644 --- a/test/lib/template.test.js +++ b/test/template.test.js @@ -1,5 +1,5 @@ const assert = require('assert'); -const template = require('../../lib/template'); +const template = require('../src/template'); describe('#template', () => { it('set variables', () => { From c35119b3c528ff85b1c99c1e515ca083f9b99705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=B3=96=E9=A5=BC?= Date: Thu, 20 Jul 2017 17:41:55 +0800 Subject: [PATCH 3/5] refactor: let > const --- src/fs-promise.js | 4 ++-- src/index.js | 8 ++++---- src/loger.js | 16 ++++++++-------- src/parse.js | 20 ++++++++++---------- src/promise-task.js | 6 +++--- src/repository.js | 18 +++++++++--------- src/run-tasks.js | 18 +++++++++--------- 7 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/fs-promise.js b/src/fs-promise.js index 35ed984..9ecaf5a 100644 --- a/src/fs-promise.js +++ b/src/fs-promise.js @@ -21,8 +21,8 @@ const mkdirs = (dirname, callback) => { * @return {Promise} */ const writeFile = promiseify((...params) => { - let file = params[0]; - let dirname = path.dirname(file); + const file = params[0]; + const dirname = path.dirname(file); mkdirs(dirname, ()=> { fs.writeFile(...params); }); diff --git a/src/index.js b/src/index.js index a048a03..1a56ed7 100644 --- a/src/index.js +++ b/src/index.js @@ -67,8 +67,8 @@ const taskRunner = (options = {}, context = process.cwd()) => { ]).then(([modCommit, ...libCommits]) => { - let modChanged = modCommit[0] !== modCommit[1]; - let libChanged = libCommits.filter(libCommit => libCommit[0] !== libCommit[1]).length !== 0; + const modChanged = modCommit[0] !== modCommit[1]; + const libChanged = libCommits.filter(libCommit => libCommit[0] !== libCommit[1]).length !== 0; task.dirty = options.force || modChanged || libChanged; cache.tasks[task.name] = { @@ -113,7 +113,7 @@ const taskRunner = (options = {}, context = process.cwd()) => { .catch(() => defaultsDeep({}, CACHE_DEFAULT)) .then(oldAssets => defaultsDeep(cache, oldAssets)) .then(cache => { - let json = JSON.stringify(cache, null, 2); + const json = JSON.stringify(cache, null, 2); return fsp.writeFile(options.cache, json, 'utf8').then(() => cache); }); }, @@ -126,7 +126,7 @@ const taskRunner = (options = {}, context = process.cwd()) => { } ]).then(results => { - let timeEnd = Math.round((Date.now() - time) / 1000); + const timeEnd = Math.round((Date.now() - time) / 1000); loger.log('░░', `${PACKAGE.name}:`, `${timeEnd}s`); return results[results.length - 1]; }); diff --git a/src/loger.js b/src/loger.js index 7de59f4..2b1e7ec 100644 --- a/src/loger.js +++ b/src/loger.js @@ -20,7 +20,7 @@ class StringStyle { Object.keys(TYPES).filter(key => { return this[key] !== undefined; }).forEach(key => { - let value = this[key]; + const value = this[key]; this[TYPES[key]](value); }); @@ -41,7 +41,7 @@ class StringStyle { } [textAlign](value) { - let content = this.string.join(''); + const content = this.string.join(''); let str; let length; switch (value) { @@ -66,7 +66,7 @@ class StringStyle { [color](value) { if (this.displayColor && StringStyle.colors[value]) { - let style = StringStyle.colors[value]; + const style = StringStyle.colors[value]; this.string.unshift(style[0]); this.string.push(style[1]); } @@ -74,7 +74,7 @@ class StringStyle { [fontWeight](value) { if (this.displayColor && value === 'bold') { - let style = ['\x1B[1m', '\x1B[22m']; + const style = ['\x1B[1m', '\x1B[22m']; this.string.unshift(style[0]); this.string.push(style[1]); } @@ -82,7 +82,7 @@ class StringStyle { [fontStyle](value) { if (this.displayColor && value === 'italic') { - let style = ['\x1B[3m', '\x1B[23m']; + const style = ['\x1B[3m', '\x1B[23m']; this.string.unshift(style[0]); this.string.push(style[1]); } @@ -90,7 +90,7 @@ class StringStyle { [textDecoration](value) { if (this.displayColor && value === 'underline') { - let style = ['\x1B[4m', '\x1B[24m']; + const style = ['\x1B[4m', '\x1B[24m']; this.string.unshift(style[0]); this.string.push(style[1]) } @@ -136,8 +136,8 @@ class Loger { setStyles(messages) { return messages.map((message, index) => { - let stringStyle = new StringStyle(message, this.displayColor); - let style = this.styles[index]; + const stringStyle = new StringStyle(message, this.displayColor); + const style = this.styles[index]; Object.keys(style || {}).forEach(name => { stringStyle[name] = style[name]; diff --git a/src/parse.js b/src/parse.js index 72360c9..c42c3a5 100644 --- a/src/parse.js +++ b/src/parse.js @@ -41,10 +41,10 @@ class Task extends File { * @return {Task[]} */ module.exports = (options, context) => { - let tasks = []; + const tasks = []; - let parseDependencie = lib => { + const parseDependencie = lib => { if (typeof lib === 'string') { lib = { name: lib, @@ -58,7 +58,7 @@ module.exports = (options, context) => { }; - let parseProgram = program => { + const parseProgram = program => { if (typeof program === 'string') { program = { command: program, @@ -71,14 +71,14 @@ module.exports = (options, context) => { // 设置字符串变量 - let setVariables = (target, variables) => { - let type = typeof target; + const setVariables = (target, variables) => { + const type = typeof target; if (type === 'string') { return template(target, variables); } else if (Array.isArray(target)) { return target.map(target => setVariables(target, variables)); } else if (type === 'object' && type !== null) { - let object = {}; + const object = {}; Object.keys(target).forEach(key => object[key] = setVariables(target[key], variables)); return object; } else { @@ -87,7 +87,7 @@ module.exports = (options, context) => { }; - let parseTask = (task, order) => { + const parseTask = (task, order) => { if (typeof task === 'string') { task = { @@ -109,8 +109,8 @@ module.exports = (options, context) => { ) }; - let dependencies = task.dependencies.map(parseDependencie); - let program = setVariables(task.program, { + const dependencies = task.dependencies.map(parseDependencie); + const program = setVariables(task.program, { taskName: task.name, taskPath: task.path, taskDirname: path.dirname(task.path) @@ -126,7 +126,7 @@ module.exports = (options, context) => { }); }; - let each = (task, index) => { + const each = (task, index) => { if (Array.isArray(task)) { task.forEach(task => each(task, index)); } else { diff --git a/src/promise-task.js b/src/promise-task.js index 210d1c5..b53b737 100644 --- a/src/promise-task.js +++ b/src/promise-task.js @@ -5,9 +5,9 @@ */ const serial = tasks => { let p = Promise.resolve(); - let results = []; + const results = []; - let each = task => { + const each = task => { if (typeof task === 'function') { p = p.then(task).then(result => { results.push(result); @@ -39,7 +39,7 @@ const parallel = (tasks, limit = tasks.length) => { } })); } else { - let chunks = []; + const chunks = []; tasks = [...tasks]; for (let i = 0, len = tasks.length; i < len; i += limit) { diff --git a/src/repository.js b/src/repository.js index 03e5ddc..004459d 100644 --- a/src/repository.js +++ b/src/repository.js @@ -32,7 +32,7 @@ class Repository { getNewCommitId(target) { - let commitId = this.cache[target]; + const commitId = this.cache[target]; if (commitId) { return Promise.resolve(commitId); } else { @@ -67,15 +67,15 @@ class Repository { // 将绝对路径转换为相对路径存储 Object.keys(data[this.tableName]).forEach(target => { if (path.isAbsolute(target)) { - let commitId = data[this.tableName][target]; - let relativePath = path.relative(this.dirname, target); + const commitId = data[this.tableName][target]; + const relativePath = path.relative(this.dirname, target); data[this.tableName][relativePath] = commitId; delete data[this.tableName][target]; } }); return data; }).then(data => { - let content = JSON.stringify(data, null, 2); + const content = JSON.stringify(data, null, 2); return fsp.writeFile(this.storagePath, content, 'utf8'); }); } @@ -88,8 +88,8 @@ class Repository { // 将相对路径转换为绝对路径进行内部运算 Object.keys(data[this.tableName]).forEach(target => { if (!path.isAbsolute(target)) { - let commitId = data[this.tableName][target]; - let resolvePath = path.resolve(this.dirname, target); + const commitId = data[this.tableName][target]; + const resolvePath = path.resolve(this.dirname, target); data[this.tableName][resolvePath] = commitId; delete data[this.tableName][target]; } @@ -116,9 +116,9 @@ class Repository { // 获取目标的修订 ID [GET_REVISION](target) { - let type = this.type; - let cwd = path.dirname(target); - let basename = path.basename(target); + const type = this.type; + const cwd = path.dirname(target); + const basename = path.basename(target); let cmd; let runner; diff --git a/src/run-tasks.js b/src/run-tasks.js index 69d12f8..d945d91 100644 --- a/src/run-tasks.js +++ b/src/run-tasks.js @@ -12,32 +12,32 @@ const PACKAGE = require('../package.json'); */ module.exports = (tasks, parallel = require('os').cpus().length) => { - let taskFucs = [[]]; + const taskFucs = [[]]; let preOrder = 0; - let taskFuc = task => () => { + const taskFuc = task => () => { - let program = task.program; - let time = Date.now(); - let logStyles = [ + const program = task.program; + const time = Date.now(); + const logStyles = [ null, { minWidth: 16, color: 'green', textDecoration: 'underline' }, null, { color: 'gray' } ]; - let loger = new Loger([null, ...logStyles]); + const loger = new Loger([null, ...logStyles]); loger.log('░░', `${PACKAGE.name}:`, task.name, '[running]'); return worker(program.command, program.options).then(() => { - let loger = new Loger([{ color: 'green' }, ...logStyles]); - let timeEnd = Math.round((Date.now() - time) / 1000) + const loger = new Loger([{ color: 'green' }, ...logStyles]); + const timeEnd = Math.round((Date.now() - time) / 1000) loger.log('░░', `${PACKAGE.name}:`, task.name, '[success]', `${timeEnd}s`); }).catch(errors => { - let loger = new Loger([{ color: 'red' }, ...logStyles]); + const loger = new Loger([{ color: 'red' }, ...logStyles]); loger.error('░░', `${PACKAGE.name}:`, task.name, '[failure]'); throw errors; }); From 854e1086115abf3a38118bf889a627f4cf42a237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=B3=96=E9=A5=BC?= Date: Thu, 20 Jul 2017 18:56:21 +0800 Subject: [PATCH 4/5] refactor: rename --- src/{parse.js => create-tasks.js} | 0 src/index.js | 11 ++++----- src/{promise-task.js => queue.js} | 0 src/run-tasks.js | 6 ++--- test/{parse.test.js => create-tasks.test.js} | 22 ++++++++--------- test/{promise-task.test.js => queue.test.js} | 26 ++++++++++---------- 6 files changed, 32 insertions(+), 33 deletions(-) rename src/{parse.js => create-tasks.js} (100%) rename src/{promise-task.js => queue.js} (100%) rename test/{parse.test.js => create-tasks.test.js} (95%) rename test/{promise-task.test.js => queue.test.js} (87%) diff --git a/src/parse.js b/src/create-tasks.js similarity index 100% rename from src/parse.js rename to src/create-tasks.js diff --git a/src/index.js b/src/index.js index 1a56ed7..476c639 100644 --- a/src/index.js +++ b/src/index.js @@ -1,15 +1,14 @@ const path = require('path'); const findCacheDir = require('find-cache-dir'); -const fsp = require('./fs-promise'); const defaultsDeep = require('lodash.defaultsdeep'); -const promiseTask = require('./promise-task'); +const fsp = require('./fs-promise'); +const queue = require('./queue'); const Repository = require('./repository'); const Loger = require('./loger'); const DEFAULT = require('./config/config.default.json'); const CACHE_DEFAULT = require('./config/cache.default.json'); const PACKAGE = require('../package.json'); - -const parse = require('./parse'); +const createTasks = require('./create-tasks'); const runTasks = require('./run-tasks'); @@ -49,11 +48,11 @@ const taskRunner = (options = {}, context = process.cwd()) => { const repository = new Repository(options.cache, options.repository, 'revision'); - return promiseTask.serial([ + return queue.serial([ // 将外部输入的配置转换成内部任务描述队列 - parse(options, context), + createTasks(options, context), // 检查任务是否有变更 diff --git a/src/promise-task.js b/src/queue.js similarity index 100% rename from src/promise-task.js rename to src/queue.js diff --git a/src/run-tasks.js b/src/run-tasks.js index d945d91..0f931a8 100644 --- a/src/run-tasks.js +++ b/src/run-tasks.js @@ -1,4 +1,4 @@ -const promiseTask = require('./promise-task'); +const queue = require('./queue'); const Loger = require('./loger'); const worker = require('./run-cmd'); const PACKAGE = require('../package.json'); @@ -53,8 +53,8 @@ module.exports = (tasks, parallel = require('os').cpus().length) => { }); - return promiseTask.serial(taskFucs.map(taskFucs => () => { - return promiseTask.parallel(taskFucs, parallel); + return queue.serial(taskFucs.map(taskFucs => () => { + return queue.parallel(taskFucs, parallel); })).then(buildResults => { return [].concat(...buildResults); }); diff --git a/test/parse.test.js b/test/create-tasks.test.js similarity index 95% rename from test/parse.test.js rename to test/create-tasks.test.js index 4fd0345..502698a 100644 --- a/test/parse.test.js +++ b/test/create-tasks.test.js @@ -1,10 +1,10 @@ const assert = require('assert'); const path = require('path'); -const parse = require('../src/parse'); +const createTasks = require('../src/create-tasks'); const defaultsDeep = require('lodash.defaultsdeep'); -describe('#parse', () => { +describe('#create-tasks', () => { const programDefaults = (options, context) => { let p = path.resolve(context, options.path || options.name); @@ -23,7 +23,7 @@ describe('#parse', () => { }; it('empty', () => { - assert.deepEqual([], parse({ + assert.deepEqual([], createTasks({ tasks: [] }, __dirname)); }); @@ -40,7 +40,7 @@ describe('#parse', () => { program: programDefaults({ name: 'mod1' }, __dirname), order: 0, dirty: false - }], parse({ + }], createTasks({ tasks: ['mod1'], dependencies: ['lib'] }, __dirname)); @@ -60,7 +60,7 @@ describe('#parse', () => { }, programDefaults({ name: 'mod1' }, __dirname)), order: 0, dirty: false - }], parse({ + }], createTasks({ tasks: ['mod1'], dependencies: ['lib'], program: 'node build.js' @@ -79,7 +79,7 @@ describe('#parse', () => { program: programDefaults({ name: 'mod1' }, __dirname), order: 0, dirty: false - }], parse({ + }], createTasks({ tasks: [{ name: 'mod1' }], @@ -104,7 +104,7 @@ describe('#parse', () => { }, __dirname), order: 0, dirty: false - }], parse({ + }], createTasks({ tasks: [{ name: 'mod1', path: 'map/mod1' @@ -139,7 +139,7 @@ describe('#parse', () => { program: programDefaults({ name: 'mod3' }, __dirname), order: 2, dirty: false - }], parse({ + }], createTasks({ tasks: ['mod1', 'mod2', 'mod3'] }, __dirname)); }); @@ -166,7 +166,7 @@ describe('#parse', () => { program: programDefaults({ name: 'mod3' }, __dirname), order: 1, dirty: false - }], parse({ + }], createTasks({ tasks: ['mod1', ['mod2', 'mod3']] }, __dirname)); }); @@ -199,7 +199,7 @@ describe('#parse', () => { }, programDefaults({ name: 'mod2' }, __dirname)), order: 1, dirty: false - }], parse({ + }], createTasks({ tasks: ['mod1', { name: 'mod2', dependencies: ['lib2'], @@ -232,7 +232,7 @@ describe('#parse', () => { }, programDefaults({ name: 'mod1' }, __dirname)), order: 0, dirty: false - }], parse({ + }], createTasks({ tasks: ['mod1'], dependencies: ['lib'], program: defaultsDeep({ diff --git a/test/promise-task.test.js b/test/queue.test.js similarity index 87% rename from test/promise-task.test.js rename to test/queue.test.js index 573c34a..a752f3a 100644 --- a/test/promise-task.test.js +++ b/test/queue.test.js @@ -1,7 +1,7 @@ const assert = require('assert'); -const promiseTask = require('../src/promise-task'); +const queue = require('../src/queue'); -describe('#promise-task', () => { +describe('#queue', () => { const delay = (fuc, time) => { return new Promise(results => { @@ -11,10 +11,10 @@ describe('#promise-task', () => { }); } - describe('#promise-task.serial', () => { + describe('#queue.serial', () => { it('results', () => { - return promiseTask.serial([ + return queue.serial([ 0, (result) => { assert.deepEqual(0, result) @@ -34,7 +34,7 @@ describe('#promise-task', () => { }); it('order', () => { - return promiseTask.serial([ + return queue.serial([ 0, () => { return delay(() => 1, 30); @@ -51,7 +51,7 @@ describe('#promise-task', () => { }); it('Promise reject', () => { - return promiseTask.serial([ + return queue.serial([ () => 0, () => 1, () => Promise.reject(2), @@ -62,7 +62,7 @@ describe('#promise-task', () => { }); it('Function error', () => { - return promiseTask.serial([ + return queue.serial([ () => 0, () => 1, () => { @@ -77,11 +77,11 @@ describe('#promise-task', () => { }); - describe('#promise-task.parallel', () => { + describe('#queue.parallel', () => { const limit = 2; it('results', () => { - return promiseTask.parallel([ + return queue.parallel([ () => 0, () => 1, () => 2, @@ -92,7 +92,7 @@ describe('#promise-task', () => { }); it('order', () => { - return promiseTask.parallel([ + return queue.parallel([ () => { return delay(() => 0, 40); }, @@ -111,7 +111,7 @@ describe('#promise-task', () => { }); it('Promise reject', () => { - return promiseTask.parallel([ + return queue.parallel([ () => 0, () => 1, () => Promise.reject(2), @@ -125,7 +125,7 @@ describe('#promise-task', () => { it('Function error', () => { - return promiseTask.parallel([ + return queue.parallel([ () => 0, () => 1, () => { @@ -141,7 +141,7 @@ describe('#promise-task', () => { it('Function error', () => { - return promiseTask.parallel([ + return queue.parallel([ null, undefined, {}, From ee6ab42806fe8a912ddb1356664d4b0ba96a81c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=B3=96=E9=A5=BC?= Date: Fri, 21 Jul 2017 11:20:24 +0800 Subject: [PATCH 5/5] v1.0.4 --- package.json | 2 +- src/run-cmd.js | 5 ++--- src/run-tasks.js | 4 ++-- test/run-cmd.test.js | 12 ++++++------ 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 6f954a6..ef1a94a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ci-task-runner", - "version": "1.0.4-beta", + "version": "1.0.4", "description": "this is a multiprocess building tasks scheduler", "main": "src/index.js", "bin": "bin/ci-task-runner", diff --git a/src/run-cmd.js b/src/run-cmd.js index 6ff5f93..7e617bd 100644 --- a/src/run-cmd.js +++ b/src/run-cmd.js @@ -18,11 +18,10 @@ const run = (cmd, { env, cwd, uid, gid }, callback) => { proc.on('error', procError); proc.on('close', function (code, signal) { - let er; if (signal) { process.kill(process.pid, signal); } else if (code) { - er = new Error('Exit status ' + code); + const er = new Error(`child process exited with code ${code}`); er.errno = code; procError(er) } else { @@ -89,7 +88,7 @@ module.exports = (command, options = {}) => { clearTimeout(timer); if (errors) { - errors.messsage = `"${command}": ${errors.messsage}`; + errors.message = `run "${command}" failed: ${errors.message}`; reject(errors); } else { resolve(data); diff --git a/src/run-tasks.js b/src/run-tasks.js index 0f931a8..c51b224 100644 --- a/src/run-tasks.js +++ b/src/run-tasks.js @@ -1,6 +1,6 @@ const queue = require('./queue'); const Loger = require('./loger'); -const worker = require('./run-cmd'); +const runCmd = require('./run-cmd'); const PACKAGE = require('../package.json'); @@ -30,7 +30,7 @@ module.exports = (tasks, parallel = require('os').cpus().length) => { const loger = new Loger([null, ...logStyles]); loger.log('░░', `${PACKAGE.name}:`, task.name, '[running]'); - return worker(program.command, program.options).then(() => { + return runCmd(program.command, program.options).then(() => { const loger = new Loger([{ color: 'green' }, ...logStyles]); const timeEnd = Math.round((Date.now() - time) / 1000) diff --git a/test/run-cmd.test.js b/test/run-cmd.test.js index 8141a1f..bd53b26 100644 --- a/test/run-cmd.test.js +++ b/test/run-cmd.test.js @@ -1,13 +1,13 @@ const assert = require('assert'); -const worker = require('../src/run-cmd'); +const runCmd = require('../src/run-cmd'); -describe('#worker', () => { +describe('#runCmd', () => { it('exec script', () => { - return worker('echo "hello"'); + return runCmd('echo "hello"'); }); // it('childProcess.exec error', () => { - // return worker("", { + // return runCmd("", { // cwd: {} // }).then(() => { // throw new Error('error'); @@ -17,7 +17,7 @@ describe('#worker', () => { // }); it('exec error', () => { - return worker(`@error%`, { + return runCmd(`@error%`, { timeout: 100 }).then(() => { throw new Error('error'); @@ -27,7 +27,7 @@ describe('#worker', () => { }); it('options.timeout', () => { - return worker(`node -e "setTimeout(()=> {}, 3000)"`, { + return runCmd(`node -e "setTimeout(()=> {}, 3000)"`, { timeout: 100 }).then(() => { throw new Error('options.timeout: error');