From e9a90f2b378cda418eacc74690d3b968d9438ab7 Mon Sep 17 00:00:00 2001
From: Jack Hsu <jack.hsu@gmail.com>
Date: Wed, 6 Dec 2023 09:51:41 -0500
Subject: [PATCH] fix(core): run-commands should handle signals correctly

---
 e2e/nx-misc/src/extras.test.ts                | 32 ++++++++++++++++++-
 .../run-commands/run-commands.impl.ts         | 14 +++++---
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/e2e/nx-misc/src/extras.test.ts b/e2e/nx-misc/src/extras.test.ts
index 9a845cca20e6bd..3aad885fc843d6 100644
--- a/e2e/nx-misc/src/extras.test.ts
+++ b/e2e/nx-misc/src/extras.test.ts
@@ -4,12 +4,13 @@ import {
   cleanupProject,
   isNotWindows,
   newProject,
+  readFile,
   readJson,
   runCLI,
+  runCommandUntil,
   setMaxWorkers,
   uniq,
   updateFile,
-  readFile,
   updateJson,
 } from '@nx/e2e/utils';
 import { join } from 'path';
@@ -265,6 +266,35 @@ describe('Extra Nx Misc Tests', () => {
       runCLI(`build ${mylib}`);
       checkFilesExist(`${folder}/dummy.txt`);
     }, 120000);
+
+    it('should handle SIGTERM signal gracefully', async () => {
+      updateFile(
+        'main.js',
+        `
+        const fs = require('fs');
+        console.log('Started');
+        const t = setInterval(() => {
+          // Keep alive
+        }, 1000);
+        process.on('SIGTERM', () => {
+          fs.writeFileSync('exited.txt', '');
+          clearInterval(t);
+        });
+      `
+      );
+      runCLI(
+        `generate @nx/workspace:run-commands serve --command="node main.js" --project=${mylib}`
+      );
+
+      const p = await runCommandUntil(`serve ${mylib}`, (output) =>
+        output.includes('Started')
+      );
+      const exited = new Promise<void>((res) => p.on('exit', () => res()));
+
+      p.kill('SIGTERM');
+      await exited;
+      checkFilesExist('exited.txt');
+    });
   });
 
   describe('generate --quiet', () => {
diff --git a/packages/nx/src/executors/run-commands/run-commands.impl.ts b/packages/nx/src/executors/run-commands/run-commands.impl.ts
index ba6cf37c0cba83..355001ac116598 100644
--- a/packages/nx/src/executors/run-commands/run-commands.impl.ts
+++ b/packages/nx/src/executors/run-commands/run-commands.impl.ts
@@ -20,7 +20,9 @@ async function loadEnvVars(path?: string) {
   }
 }
 
-export type Json = { [k: string]: any };
+export type Json = {
+  [k: string]: any;
+};
 
 export interface RunCommandsOptions extends Json {
   command?: string;
@@ -65,13 +67,17 @@ export interface NormalizedRunCommandsOptions extends RunCommandsOptions {
     command: string;
     forwardAllArgs?: boolean;
   }[];
-  parsedArgs: { [k: string]: any };
+  parsedArgs: {
+    [k: string]: any;
+  };
 }
 
 export default async function (
   options: RunCommandsOptions,
   context: ExecutorContext
-): Promise<{ success: boolean }> {
+): Promise<{
+  success: boolean;
+}> {
   await loadEnvVars(options.envFile);
   const normalized = normalizeOptions(options);
 
@@ -215,7 +221,7 @@ function createProcess(
     /**
      * Ensure the child process is killed when the parent exits
      */
-    const processExitListener = (signal?: number | NodeJS.Signals) => () =>
+    const processExitListener = (signal?: number | NodeJS.Signals) =>
       childProcess.kill(signal);
 
     process.on('exit', processExitListener);