Concurrently node exits with status 1. This halts Teamcity leading it to believe that the tests failed

匿名 (未验证) 提交于 2019-12-03 10:03:01

问题:

I am trying to run two scripts at once with concurrently. The basic command looks something like this:

concurrently -k --success first "node ./tools/mock-webapi/mock-webapi.js" "npm run test-single-run" 

Which in turn calls (local):

"test-single-run": "karma start --single-run --browsers ChromeHeadless" 

Or on remote (teamcity host):

"test-teamcity": "karma start --reporters teamcity --single-run --browsers ChromeHeadless", 

The tests run just fine (local & remote). However, I keep getting exit code 1. Even if I use concurrently -k --success first I still get a code 1 even with --success first.

[1] 09 05 2018 17:56:54.032:WARN [launcher]: ChromeHeadless was not killed in 2000 ms, sending SIGKILL. [1] npm run test-single-run exited with code 0 --> Sending SIGTERM to other processes.. [0] node ./tools/mock-webapi/mock-webapi.js exited with code 1 

I tried various ways for json-server to gracefully receive this signal. Nothing seems to work.

mock-webapi.js

process.on('SIGTERM', function (code) {     console.log('Handle SIGTERM', process.pid, code);     exitCode = 0;     server.close(function () {         process.exit(0);     }); });  process.on('SIGKILL', function (code) {     console.log('SIGKILL received...', code);     exitCode = 0;     server.close(function () {         process.exit(0);     }); });  process.on('SIGINT', function (code) {     console.log('SIGINT received...', code);     exitCode = 0;     server.close(function () {         process.exit(0);     }); }); 

回答1:

Finally found a solution to this problem. I wrote a little script that runs the mock webapi and the karma tests as child processes.

test-single-run-single-process.js

const spawn = require('cross-spawn');  /**  * Running the tests requires a mock webapi which is gladly provided by json-server.  * Running the tests in teamcity requires that everything is executed from one terminal.  * Different mock data sets can be easily used if the mockapi is a child process.  * We do not need to keep the mockWebapi alive between trials.  *   * After all the tests have succeeded we then close the json-server by sending (SIGINT).  * Finally the process will exit with code 0, which means for TeamCity that all is OK.  * Now it can proceed with the next build step.  * So basically we can run the tests both standalone and in one single terminal.  * Notice that the mockWebapi is a forked process so we can send messages to it.  *   * <!> Failed approach - Closing the mockwebapi  * Using kill command leaves no option for gracefull shutdown.   * SIGINT or SIGTERM signals are not received by the mockWebapi.  * The server will stay active keeping the 3000 port busy.  *   *     mockWebapi.kill('SIGINT');   */  const fork = require('child_process').fork const mockWebapi = fork('./tools/mock-webapi/mock-webapi.js')  const karma = spawn(     `karma start --single-run --browsers ChromeHeadless`,     [], { stdio: 'inherit' } );  // 1) Listen to karma exit karma.on('close', (code, signal) => {      console.log('Karma closed. Code:', code, 'Signal:', signal);     code === 0 && gracefullyCloseMockWebapi(true); }); karma.on('error', (code, signal) => {      console.log('Karma error. Code:', code, 'Signal:', signal);     gracefullyCloseMockWebapi(false); });  let gracefullyCloseMockWebapi = (testsCompletedOk) => {     console.log('Gracefuly close webapi. Tests completed ok:', testsCompletedOk);     mockWebapi.send({ testsCompletedOk }); };  // 2) Finish the job, pass the exit code from mockWeabpi to the command line mockWebapi.on('close', (code, signal) => {      console.log('Mock webapi closed. Code:', code, 'Signal:', signal);     process.exit(code); }); 

mock-webapi.js

// Some project specific work is done before starting the server  /**  * <!> Failed approach - concurrently  * Dispatching the following command will exit with code 1.   * The SIGTERM or SIGINT handlers are not called after the tests are done.  * concurrently --kill-others --success first   *     "node ./tools/mock-webapi/mock-webapi.js" "npm run test-single-run"  *  *     process.on('SIGINT', (code) => {  *         server.close(function () {  *             process.exit(0);  *         });  *     });  *  * <!> Working approach  * Spawning a process child and sending it a message to self-close.  * Double check it with "echo Exit Code is %errorlevel%" after the processes terminated.  */  function setupJsonServer(mocks, routes) {     let server = jsonServer.create(),         port = 3000;      const router = jsonServer.router(mocks);      server.use(jsonServer.defaults());     server.use(jsonServer.rewriter(routes));     server.use(router);      server.listen(port, () => {         console.log(`JSON Server is running at ${port}`)         console.log('Process id is', process.pid);     });      process.on('message', function ({ testsCompletedOk }) {         console.log('Mockwebapi will terminate. Tests completed ok', testsCompletedOk)         process.exit(testsCompletedOk === true ? 0 : 1)     });  } 

Additional reading:



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!