code: function spawnExt(command, args, options, ignoreClose = false) {
    let proc;
    const promise = new Promise((resolve, reject) => {
      let descr = command + ' ' + args.join(' ');
      console.log('running: ' + descr);
      try {
        proc = xSpawn.spawn(command, args, options);
      } catch (e) {
        console.log(e);
        reject(e);
        return { proc: null, promise };
      }
      proc.stdout.on('data', function (data) {
        process.stdout.write(data.toString());
      });
      proc.stderr.on('data', function (data) {
        process.stdout.write(data.toString());
      });
      proc.on('close', function (returnCode) {
        console.log(`completed: ${descr} \n`);
        // Many tasks (e.g., tsc) complete but are actually errors;
        // Confirm return code is zero.
        returnCode === 0 || ignoreClose ? resolve(0) : reject(returnCode);
      });
      proc.on('error', function (data) {
        console.log(`completed with error: ${descr} \n`);
        console.log(data.toString());
        reject(data);
      });
    });
    return { proc, promise };
  }
docs: Returns both a promise and the spawned process so that it can be killed if needed.