From 15249ff122a3f7267baf17c386c8ba0a1674438b Mon Sep 17 00:00:00 2001 From: Jesse MacFadyen Date: Fri, 30 May 2025 14:45:35 -0700 Subject: [PATCH 1/5] restore process.env after exec action with side-effects --- src/lib/run-dev.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/run-dev.js b/src/lib/run-dev.js index 412b8f7..adb6e65 100644 --- a/src/lib/run-dev.js +++ b/src/lib/run-dev.js @@ -349,6 +349,10 @@ async function invokeAction ({ actionRequestContext, logger }) { } } } + + // if we run an action, we will restore the process.env after the call + // we must do this before we load the action because code can execute on require/import + const preCallEnv = cloneDeep(process.env) // generate an activationID just like openwhisk process.env.__OW_ACTIVATION_ID = crypto.randomBytes(16).toString('hex') @@ -366,10 +370,15 @@ async function invokeAction ({ actionRequestContext, logger }) { if (actionFunction) { try { + // get cwd and process.env before changing it, so we can restore it later + const originalCwd = process.cwd() process.chdir(path.dirname(action.function)) process.env.__OW_ACTION_NAME = `/${process.env.__OW_NAMESPACE}/${packageName}/${actionName}` const response = await actionFunction(params) delete process.env.__OW_ACTION_NAME + logger.debug('restoring process.env and cwd') + process.env = preCallEnv // restore the environment variables + process.chdir(originalCwd) // restore the original working directory let statusCode, headers, body From 595f2b523e6988b7706e2ebbbad470512beb7966 Mon Sep 17 00:00:00 2001 From: Jesse MacFadyen Date: Mon, 2 Jun 2025 15:15:45 -0700 Subject: [PATCH 2/5] added try/catch/finally to ensure env gets reset even if the action throws --- src/lib/run-dev.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/run-dev.js b/src/lib/run-dev.js index adb6e65..f449f4a 100644 --- a/src/lib/run-dev.js +++ b/src/lib/run-dev.js @@ -353,6 +353,7 @@ async function invokeAction ({ actionRequestContext, logger }) { // if we run an action, we will restore the process.env after the call // we must do this before we load the action because code can execute on require/import const preCallEnv = cloneDeep(process.env) + const originalCwd = process.cwd() // generate an activationID just like openwhisk process.env.__OW_ACTIVATION_ID = crypto.randomBytes(16).toString('hex') @@ -371,14 +372,10 @@ async function invokeAction ({ actionRequestContext, logger }) { if (actionFunction) { try { // get cwd and process.env before changing it, so we can restore it later - const originalCwd = process.cwd() process.chdir(path.dirname(action.function)) process.env.__OW_ACTION_NAME = `/${process.env.__OW_NAMESPACE}/${packageName}/${actionName}` const response = await actionFunction(params) delete process.env.__OW_ACTION_NAME - logger.debug('restoring process.env and cwd') - process.env = preCallEnv // restore the environment variables - process.chdir(originalCwd) // restore the original working directory let statusCode, headers, body @@ -426,6 +423,10 @@ async function invokeAction ({ actionRequestContext, logger }) { statusCode, body: { error: 'Response is not valid \'message/http\'.' } } + } finally { + logger.debug('restoring process.env and cwd') + process.env = preCallEnv // restore the environment variables + process.chdir(originalCwd) // restore the original working directory } } else { // this case the action returned an error object, so we should use it From 66695b9581875d60c5fa593aea2cc4c850b0f655 Mon Sep 17 00:00:00 2001 From: Jesse MacFadyen Date: Mon, 2 Jun 2025 17:34:39 -0700 Subject: [PATCH 3/5] Use Object.assign since env props are only strings Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/lib/run-dev.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/run-dev.js b/src/lib/run-dev.js index f449f4a..3d46e2c 100644 --- a/src/lib/run-dev.js +++ b/src/lib/run-dev.js @@ -352,7 +352,7 @@ async function invokeAction ({ actionRequestContext, logger }) { // if we run an action, we will restore the process.env after the call // we must do this before we load the action because code can execute on require/import - const preCallEnv = cloneDeep(process.env) + const preCallEnv = Object.assign({}, process.env) const originalCwd = process.cwd() // generate an activationID just like openwhisk process.env.__OW_ACTIVATION_ID = crypto.randomBytes(16).toString('hex') From 53ba902d066dbf2c056db84ef6dff9dde4487263 Mon Sep 17 00:00:00 2001 From: Jesse MacFadyen Date: Mon, 2 Jun 2025 17:38:28 -0700 Subject: [PATCH 4/5] remove outdated comment --- src/lib/run-dev.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/run-dev.js b/src/lib/run-dev.js index 3d46e2c..33ea969 100644 --- a/src/lib/run-dev.js +++ b/src/lib/run-dev.js @@ -371,7 +371,6 @@ async function invokeAction ({ actionRequestContext, logger }) { if (actionFunction) { try { - // get cwd and process.env before changing it, so we can restore it later process.chdir(path.dirname(action.function)) process.env.__OW_ACTION_NAME = `/${process.env.__OW_NAMESPACE}/${packageName}/${actionName}` const response = await actionFunction(params) From 4d6bd5e09d1e974f7456afb0ca430f74867ed49a Mon Sep 17 00:00:00 2001 From: Jesse MacFadyen Date: Tue, 3 Jun 2025 17:49:13 -0700 Subject: [PATCH 5/5] spread syntax for cloning Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/lib/run-dev.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/run-dev.js b/src/lib/run-dev.js index 33ea969..1352d76 100644 --- a/src/lib/run-dev.js +++ b/src/lib/run-dev.js @@ -352,7 +352,7 @@ async function invokeAction ({ actionRequestContext, logger }) { // if we run an action, we will restore the process.env after the call // we must do this before we load the action because code can execute on require/import - const preCallEnv = Object.assign({}, process.env) + const preCallEnv = { ...process.env } const originalCwd = process.cwd() // generate an activationID just like openwhisk process.env.__OW_ACTIVATION_ID = crypto.randomBytes(16).toString('hex')