From c4ad232720767c5982c46de11a7affe628b8cf06 Mon Sep 17 00:00:00 2001
From: Igor Braga <higorb1@gmail.com>
Date: Wed, 10 Mar 2021 19:06:12 -0500
Subject: [PATCH 1/2] Introduce tutorial to deploy NodeJS runtime locally

The introduced tutorial uses Docker and a tranfer data
tool (e.g. curl, wget or Postman). A summary of the tutorial
steps are:

1. Create docker container based on core/nodejs14Action
   Dockerfile
2. Deploy/run the container locally
3. Create function that resides in a json file
4. Initialize the function against the deployed container
   using either curl, wget or Postman
5. Call/trigger function using either curl, wget or Postman

Signed-off-by: Igor Braga <higorb1@gmail.com>
---
 README.md | 311 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 308 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 1ecaef9c..90e75315 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,312 @@ This README documents the build, customisation and testing of these runtime imag
 
 **Do you want to learn more about using Node.js actions to build serverless applications?** Please see the main project documentation [here](https://github.com/apache/openwhisk/blob/master/docs/actions-nodejs.md) for that information.
 
-## Usage
+## Build Runtimes
+
+### You have 2 options to build the NodeJS runtime:
+- Building locally
+- Using OpenWhisk Actions.
+### This README walks you through how to do both
+
+# Building NodeJS Runtime Locally
+
+### Pre-requisites
+- [Docker](https://www.docker.com/)
+- [curl](https://curl.se/), [wget](https://www.gnu.org/software/wget/), or [Postman](https://www.postman.com/)
+
+
+0. Choose/create a folder of your liking and make sure docker daemon is running
+
+1. Clone this repo:
+```
+git clone https://github.com/apache/openwhisk-runtime-nodejs
+cd openwhisk-runtime-nodejs
+```
+
+1.1 Choose a NodeJS version. All build files reside inside `core/nodejsActionBase`. If you take a look into `core/nodejsActionBase/Dockerfile` you’ll see a line that looks like:
+```
+FROM node:lts-stretch
+```
+This will use the latest NodeJS version. But we want to be more specific. Now if you look into each of the Dockerfile’s of `core/nodejs14Action`, `core/nodejs12Action`, `core/nodejs10Action`, you’ll notice different nodeJS versions. Let’s go ahead with the 14 version. All you have to do is substitute the line above from `core/nodejsActionBase/Dockerfile` with the equivalent line from `core/nodejs14Action/Dockerfile` that looks like:
+```
+FROM node:14.16.0-stretch
+```
+
+Or in the command line you can simply type:
+```
+cp core/nodejs14Action/Dockerfile core/nodejsActionBase/
+```
+
+If you follow the instructions at end of this tutorial [here](#build_dradle) that uses Gradle, you'll notice that Gradle takes care of this copying for us internally. Here since we just want to use docker and not worry about anything else we copy manually.
+
+**NOTE**: If you think that you messed up some file you can restore all files to its original state by typing the following. Then you can repeat the above command (careful with this command as it will remove all modifications you made to any file locally):
+```
+git reset --hard origin/master
+```
+
+2. Build docker
+```
+docker build -t nodejs-action-v14:1.0-SNAPSHOT $(pwd)/core/nodejsActionBase
+```
+
+2.1. Check docker `IMAGE ID` (1st column) for repository `nodejs-action-v14` (assuming you built with the first option above)
+```
+docker images
+```
+
+2.2. Tag image (Optional step). Required if you’re pushing your docker image to a registry e.g. dockerHub
+```
+docker tag <docker_image_ID> <dockerHub_username>/nodejs-action-v14:1.0-SNAPSHOT
+```
+
+3. Run docker on localhost with either the following commands:
+```
+docker run -p 127.0.0.1:80:8080/tcp --name=bloom_whisker --rm -it nodejs-action-v14:1.0-SNAPSHOT
+```
+Or run the container in the background (Add `-d` (detached) to the command above)
+```
+docker run -d -p 127.0.0.1:80:8080/tcp --name=bloom_whisker --rm -it nodejs-action-v14:1.0-SNAPSHOT
+```
+
+Lists all running containers
+```
+docker ps
+```
+or
+```
+docker ps -a
+```
+You should see a container named `bloom_whisker` being run
+
+4. Create your function (note that each container can only hold one function). In this first example we'll be creating a very simple function. Create a json file called `js-data-init-run.json` which will contain the function that looks something like the following:
+
+NOTE: value of code is the actual payload and must match the syntax of the target runtime language, in this case `javascript`
+```javascript
+{
+   "value": {
+      "name" : "js-helloworld",
+      "main" : "main",
+      "binary" : false,
+      "code" : "function main() {return {payload: 'Hello World!'};}"
+   }
+}
+```
+
+To issue the action against the running runtime, we must first make a request against the `init` API
+We need to issue `POST` requests to init our function
+Using curl (the option `-d` signifies we're issuing a POST request)
+```
+curl -d "@js-data-init-run.json" -H "Content-Type: application/json" http://localhost/init
+```
+Using wget (the option `--post-file` signifies we're issuing a POST request. The option `--output` redirects `wget` output to a file since its response is quite verbose and we're only interested in the Server response; additionally, `wget` will store the Server response in a file called `init.#` where `#` is a number)
+```
+wget -O- --post-file=js-data-init-run.json --header="Content-Type: application/json" --output-file=logfile http://localhost/init
+```
+The above can also be achieved with [Postman](https://www.postman.com/) by setting the headers and body accordingly
+
+Client expected response:
+```
+{"ok":true}
+```
+
+Server will remain silent in this case
+
+Now we can invoke/run our function against the `run` API with:
+Using curl `POST` request
+
+curl -d "@js-data-init-run.json" -H "Content-Type: application/json" http://localhost/run
+Or using `GET` request
+```
+curl --data-binary "@js-data-init-run.json" -H "Content-Type: application/json" http://localhost/run
+```
+
+Or
+Using wget `POST` request. The `-O-` is to redirect `wget` response to `stdout`.
+```
+wget -O- --post-file=js-data-init-run.json --header="Content-Type: application/json" --output-file=logfile http://localhost/run
+```
+
+The above can also be achieved with [Postman](https://www.postman.com/) by setting the headers and body accordingly.
+
+You noticed that we’re passing the same file `js-data-init-run.json` from function initialization request to trigger the function. That’s not necessary and not recommended since to trigger a function all we need is to pass the parameters of the function. So in the above example, it's preferred if we create a file called `js-data-params.json` that looks like the following:
+```javascript
+{
+   "value": {}
+}
+```
+
+And trigger the function with the following (it also works with wget and postman equivalents):
+```
+curl --data-binary "@js-data-params.json" -H "Content-Type: application/json" http://localhost/run
+```
+
+#### You can perform the same steps as above using [Postman](https://www.postman.com/) application. Make sure you have the correct request type set and the respective body. Also set the correct headers key value pairs, which for us is "Content-Type: application/json"
+
+After you trigger the function with one of the above commands you should expect the following client response:
+```
+{"payload": "Hello World!"}
+```
+And Server expected response:
+
+```
+XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+```
+
+
+## Creating functions with arguments
+If your container still running from the previous example you must stop it and re-run it before proceeding. Remember that each NodeJS runtime can only hold one function (which cannot be overrided due to security reasons)
+Create a json file called `js-data-init-params.json` which will contain the function to be initialized that looks like the following:
+```javascript
+{
+   "value": {
+      "name": "js-helloworld-with-params",
+      "main" : "main",
+      "binary" : false,
+      "code" : "function main(params) { return {payload: 'Hello ' + params.name + ' from ' + params.place + '!!!'} }"
+   }
+}
+```
+
+Also create a json file `js-data-run-params.json` which will contain the parameters to the function used to trigger it. Notice here we're creating 2 separate file from the beginning since this is good practice to make the distinction between what needs to be send via the `init` API and what needs to be sent via the `run` API:
+```javascript
+{
+   "value": {
+      "name": "UFO",
+      "place": "Mars"
+   }
+}
+```
+
+Now, all we have to do is initialize and trigger our function.
+First, to initialize our function make sure your NodeJS runtime container is running if not, spin the container by following step 3.
+Issue a `POST` request against the `init` API with the following command:
+Using curl:
+
+```
+curl -d "@js-data-init-params.json" -H "Content-Type: application/json" http://localhost/init
+```
+Using wget:
+```
+wget --post-file=js-data-init-params.json --header="Content-Type: application/json" --output-file=logfile http://localhost/init
+```
+
+Second, to run/trigger the function issue requests against the run API with the following command:
+Using curl with `POST`:
+```
+curl -d "@js-data-run-params.json" -H "Content-Type: application/json" http://localhost/run
+```
+Or
+Using wget with `POST`:
+```
+wget -O- --post-file=js-data-run-params.json --header="Content-Type: application/json" --output-file=logfile http://localhost/run
+```
+
+After you trigger the function with one of the above commands you should expect the following client response:
+```
+{"payload": "Hello UFO from Mars!!!"}
+```
+
+And Server expected response:
+```
+XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+```
+
+## Now let's create a more interesting function
+### This function will calculate the nth Fibonacci number
+This is the function we’re trying to create. It calculates the nth number of the Fibonacci sequence recursively in `O(n)` time
+```javascript
+function fibonacci(n, mem) {
+   if (n == 0 || n == 1) {
+      return 1;
+   }
+   if (mem[n] == -1) {
+      mem[n] = fibonacci(n-1, mem) + fibonacci(n-2, mem);
+   }
+   return mem[n];
+}
+
+function main(args) {
+   let n = parseInt(args.fib_n);
+   var mem = Array(n+1);
+   mem.fill(-1,0);
+   var result = fibonacci(n, mem);
+   var key = 'Fib: ';
+   key = key.concat(n.toString());
+   return {key: key, result: result};
+}
+```
+
+Create a json file called `js-fib-init.json` to initialize our fibonacci function and insert the following. (It’s the same code as above but since we can’t have a string span multiple lines in Json we need to put all this code in one line and this is how we do it. It’s ugly but not much we can do here)
+```javascript
+{
+   "value": {
+      "name": "js-recursive-fibonacci",
+      "main" : "main",
+      "binary" : false,
+      "code" : "function fibonacci(n, mem) {\nif (n == 0 || n == 1) {\nreturn 1;\n}\nif (mem[n] == -1) {\nmem[n] = fibonacci(n-1, mem) + fibonacci(n-2, mem);\n}\nreturn mem[n];\n}\nfunction main(args) {\nvar n = parseInt(args.fib_n);\nvar mem = Array(n+1);\nmem.fill(-1,0);\nvar result = fibonacci(n, mem);\nvar key = 'Fib: ';\nkey = key.concat(n.toString());\nreturn {key: key, result: result};\n}"
+   }
+}
+```
+
+Create a json file called `js-fib-run.json` which will be used to run/trigger our function with the appropriate argument:
+```javascript
+{
+   "value": {
+      "fib_n": "40"
+   }
+}
+```
+
+Now we’re all set.
+Make sure your NodeJS runtime container is running if not, spin the container by following step 3.
+Initialize our fibonacci function by issuing a POST request against the init API with the following command:
+Using curl:
+```
+curl -d "@js-fib-init.json" -H "Content-Type: application/json" http://localhost/init
+```
+Using wget:
+```
+wget --post-file=js-fib-init.json --header="Content-Type: application/json" --output-file=logfile http://localhost/init
+```
+
+Client expected response:
+```
+{"ok":true}
+```
+You've noticed by now that `init` API always returns `{"ok":true}` for a successful initialized function. And the server, again, will remain silent
+
+Trigger the function by running/triggering the function with a request against the `run` API with the following command:
+Using curl with `POST`:
+```
+curl -d "@js-fib-run.json" -H "Content-Type: application/json" http://localhost/run
+```
+Using wget with `POST`:
+```
+wget -O- --post-file=js-fib-run.json --header="Content-Type: application/json" --output-file=logfile http://localhost/run
+```
+
+After you trigger the function with one of the above commands you should expect the following client response:
+```
+{"key":"Fib: 40","result":165580141}
+```
+
+And Server expected response:
+```
+XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
+```
+
+#### At this point you can edit js-fib-run.json an try other `fib_n` values. All you have to do is save `js-fib-run.json` and trigger the function again. Notice that here we're just modifying the parameters of our function; therefore, there's no need to re-run/re-initialize our container that contains our NodeJS runtime.
+
+
+# Building NodeJS Runtime using OpenWhisk Actions
+
+### Pre-requisites
+- [Gradle](https://gradle.org/)
+- [Docker](https://www.docker.com/)
+- [OpenWhisk CLI wsk](https://github.com/apache/openwhisk-cli/releases)
 
 If the deployment of Apache OpenWhisk includes these images in the runtime manifest, use the `--kind` parameter to select the Node.js runtime version.
 
@@ -84,9 +389,9 @@ Dockerfiles for runtime images are defined in the `core` directory. Each runtime
 
 The `core/nodejsActionBase` folder contains the Node.js app server used to implement the [action interface](https://github.com/apache/openwhisk/blob/master/docs/actions-new.md#action-interface), used by the platform to inject action code into the runtime and fire invocation requests. This common code is used in all runtime versions.
 
-### Build
+### Build <a name="build_dradle"></a>
 
-- Run the `distDocker` command to generate local Docker images for the different runtime versions.
+- Run the `distDocker` command to generate local Docker images for the different runtime versions. (Make sure docker daemon is running)
 
 ```
 ./gradlew core:nodejs10Action:distDocker

From 6699cba06114939d2c845423fe006eedcfae65fe Mon Sep 17 00:00:00 2001
From: Igor Braga <higorb1@gmail.com>
Date: Fri, 12 Mar 2021 20:22:00 -0500
Subject: [PATCH 2/2] Add build folder to .gitignore and address issue comments

Reorder tutorial so that Gradle instructions come first

Signed-off-by: Igor Braga <higorb1@gmail.com>
---
 .gitignore |   1 +
 README.md  | 220 +++++++++++++++++++++++++++--------------------------
 2 files changed, 112 insertions(+), 109 deletions(-)

diff --git a/.gitignore b/.gitignore
index 0f904f2d..45a748b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ default.props
 .ant-targets-build.xml
 /results/
 /logs/
+/build/
 /config/custom-config.xml
 results
 *.retry
diff --git a/README.md b/README.md
index 90e75315..615a2818 100644
--- a/README.md
+++ b/README.md
@@ -36,12 +36,109 @@ This README documents the build, customisation and testing of these runtime imag
 
 ## Build Runtimes
 
-### You have 2 options to build the NodeJS runtime:
-- Building locally
-- Using OpenWhisk Actions.
-### This README walks you through how to do both
+You have 2 options to build the NodeJS runtime:
+- [Using Gradle](#using_gradle)
+- [Using Docker](#using_docker)
 
-# Building NodeJS Runtime Locally
+This README walks you through how to do both
+
+---
+
+## Using Gradle <a name="using_gradle"></a>
+
+### Pre-requisites
+- [Gradle](https://gradle.org/)
+- [Docker](https://www.docker.com/)
+- [OpenWhisk CLI wsk](https://github.com/apache/openwhisk-cli/releases)
+
+If the deployment of Apache OpenWhisk includes these images in the runtime manifest, use the `--kind` parameter to select the Node.js runtime version.
+
+### Node.js v10
+
+```
+wsk action update myAction myAction.js --kind nodejs:10
+```
+
+### Node.js v12
+
+```
+wsk action update myAction myAction.js --kind nodejs:12
+```
+
+### Node.js v14
+
+```
+wsk action update myAction myAction.js --kind nodejs:14
+```
+
+## Images
+
+All the runtime images are published by the project to Docker Hub @ [https://hub.docker.com/u/openwhisk](https://hub.docker.com/u/openwhisk)
+
+- [https://hub.docker.com/r/openwhisk/action-nodejs-v10](https://hub.docker.com/r/openwhisk/action-nodejs-v10)
+- [https://hub.docker.com/r/openwhisk/action-nodejs-v12](https://hub.docker.com/r/openwhisk/action-nodejs-v12)
+- [https://hub.docker.com/r/openwhisk/action-nodejs-v14](https://hub.docker.com/r/openwhisk/action-nodejs-v14)
+
+These images can be used to execute Node.js actions on any deployment of Apache OpenWhisk, even those without those images defined the in runtime manifest, using the `--docker` action parameter.
+
+```
+wsk action update myAction myAction.js --docker openwhisk/action-nodejs-v12
+```
+
+If you build a custom version of the images, pushing those an external Docker Hub repository will allow you to use those on the Apache OpenWhisk deployment.
+
+### Runtimes Manifest
+
+Available runtimes in Apache OpenWhisk are defined using the runtimes manifest in this file: [runtimes.json](https://github.com/apache/openwhisk/blob/master/ansible/files/runtimes.json#L16-L72)
+
+Modify the manifest and re-deploy the platform to pick up local images changes.
+
+## Development
+
+Dockerfiles for runtime images are defined in the `core` directory. Each runtime version folder has a custom `Dockerfile` and `package.json`. If you need to add extra dependencies to a runtime version - modify these files.
+
+The `core/nodejsActionBase` folder contains the Node.js app server used to implement the [action interface](https://github.com/apache/openwhisk/blob/master/docs/actions-new.md#action-interface), used by the platform to inject action code into the runtime and fire invocation requests. This common code is used in all runtime versions.
+
+### Build <a name="build_gradle"></a>
+
+- Run the `distDocker` command to generate local Docker images for the different runtime versions. (Make sure docker daemon is running)
+
+```
+./gradlew core:nodejs10Action:distDocker
+./gradlew core:nodejs12Action:distDocker
+./gradlew core:nodejs14Action:distDocker
+```
+
+This will return the following runtime images with the following names: `action-nodejs-v10`, `action-nodejs-v12` and `action-nodejs-v14`.
+
+### Testing
+
+- Install project dependencies from the top-level Apache OpenWhisk [project](https://github.com/apache/openwhisk), which ensures correct versions of dependent libraries are available in the Maven cache.
+
+```
+./gradlew install
+```
+
+*This command **MUST BE** run from the directory containing the main Apache OpenWhisk [repository](https://github.com/apache/openwhisk), not this repository's directory.*
+
+- Build the local Docker images for the runtime versions (see the instructions above).
+- Build the custom Docker images used in local testing.
+
+```
+./gradlew tests:dat:docker:nodejs10docker:distDocker
+./gradlew tests:dat:docker:nodejs12docker:distDocker
+./gradlew tests:dat:docker:nodejs14docker:distDocker
+```
+
+- Run the project tests.
+
+```
+./gradlew :tests:test
+```
+
+---
+
+## Using Docker <a name="using_docker"></a>
 
 ### Pre-requisites
 - [Docker](https://www.docker.com/)
@@ -60,29 +157,27 @@ cd openwhisk-runtime-nodejs
 ```
 FROM node:lts-stretch
 ```
-This will use the latest NodeJS version. But we want to be more specific. Now if you look into each of the Dockerfile’s of `core/nodejs14Action`, `core/nodejs12Action`, `core/nodejs10Action`, you’ll notice different nodeJS versions. Let’s go ahead with the 14 version. All you have to do is substitute the line above from `core/nodejsActionBase/Dockerfile` with the equivalent line from `core/nodejs14Action/Dockerfile` that looks like:
-```
-FROM node:14.16.0-stretch
-```
+This will use the latest NodeJS version. But we want to be more specific. Now if you look into each of the Dockerfile’s of `core/nodejs14Action`, `core/nodejs12Action`, `core/nodejs10Action`, you’ll notice different nodeJS versions. Let’s go ahead with the 14 version. We'll be creating a `build` folder that will contain all the necessary files for us to build our NodeJS container. All you have to do is copy paste the commands below. This will copy the NodeJS application as well as our target Dockerfile with the NodeJS version 14.
 
-Or in the command line you can simply type:
 ```
-cp core/nodejs14Action/Dockerfile core/nodejsActionBase/
+mkdir build
+cp -r core/nodejsActionBase/* build
+cp core/nodejs14Action/Dockerfile build
 ```
 
-If you follow the instructions at end of this tutorial [here](#build_dradle) that uses Gradle, you'll notice that Gradle takes care of this copying for us internally. Here since we just want to use docker and not worry about anything else we copy manually.
+If you follow the instructions at beginning of this tutorial [here](#build_gradle) that uses Gradle, you'll notice that Gradle takes care of this copying for us internally. Here since we just want to use docker and not worry about anything else we make create our own little build folder.
 
 **NOTE**: If you think that you messed up some file you can restore all files to its original state by typing the following. Then you can repeat the above command (careful with this command as it will remove all modifications you made to any file locally):
 ```
-git reset --hard origin/master
+rm -rf build/*
 ```
 
 2. Build docker
 ```
-docker build -t nodejs-action-v14:1.0-SNAPSHOT $(pwd)/core/nodejsActionBase
+docker build -t nodejs-action-v14:1.0-SNAPSHOT $(pwd)/build
 ```
 
-2.1. Check docker `IMAGE ID` (1st column) for repository `nodejs-action-v14` (assuming you built with the first option above)
+2.1. Check docker `IMAGE ID` (1st column) for repository `nodejs-action-v14`
 ```
 docker images
 ```
@@ -100,7 +195,7 @@ Or run the container in the background (Add `-d` (detached) to the command above
 ```
 docker run -d -p 127.0.0.1:80:8080/tcp --name=bloom_whisker --rm -it nodejs-action-v14:1.0-SNAPSHOT
 ```
-
+**NOTE**: The instructions above that [uses gradle](#using_gradle) will also create a docker image. You can also use that image to start your NodeJS container locally and issue the below commands against localhost and things should still work <br/><br/>
 Lists all running containers
 ```
 docker ps
@@ -332,96 +427,3 @@ XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
 ```
 
 #### At this point you can edit js-fib-run.json an try other `fib_n` values. All you have to do is save `js-fib-run.json` and trigger the function again. Notice that here we're just modifying the parameters of our function; therefore, there's no need to re-run/re-initialize our container that contains our NodeJS runtime.
-
-
-# Building NodeJS Runtime using OpenWhisk Actions
-
-### Pre-requisites
-- [Gradle](https://gradle.org/)
-- [Docker](https://www.docker.com/)
-- [OpenWhisk CLI wsk](https://github.com/apache/openwhisk-cli/releases)
-
-If the deployment of Apache OpenWhisk includes these images in the runtime manifest, use the `--kind` parameter to select the Node.js runtime version.
-
-### Node.js v10
-
-```
-wsk action update myAction myAction.js --kind nodejs:10
-```
-
-### Node.js v12
-
-```
-wsk action update myAction myAction.js --kind nodejs:12
-```
-
-### Node.js v14
-
-```
-wsk action update myAction myAction.js --kind nodejs:14
-```
-
-## Images
-
-All the runtime images are published by the project to Docker Hub @ [https://hub.docker.com/u/openwhisk](https://hub.docker.com/u/openwhisk)
-
-- [https://hub.docker.com/r/openwhisk/action-nodejs-v10](https://hub.docker.com/r/openwhisk/action-nodejs-v10)
-- [https://hub.docker.com/r/openwhisk/action-nodejs-v12](https://hub.docker.com/r/openwhisk/action-nodejs-v12)
-- [https://hub.docker.com/r/openwhisk/action-nodejs-v14](https://hub.docker.com/r/openwhisk/action-nodejs-v14)
-
-These images can be used to execute Node.js actions on any deployment of Apache OpenWhisk, even those without those images defined the in runtime manifest, using the `--docker` action parameter.
-
-```
-wsk action update myAction myAction.js --docker openwhisk/action-nodejs-v12
-```
-
-If you build a custom version of the images, pushing those an external Docker Hub repository will allow you to use those on the Apache OpenWhisk deployment.
-
-### Runtimes Manifest
-
-Available runtimes in Apache OpenWhisk are defined using the runtimes manifest in this file: [runtimes.json](https://github.com/apache/openwhisk/blob/master/ansible/files/runtimes.json#L16-L72)
-
-Modify the manifest and re-deploy the platform to pick up local images changes.
-
-## Development
-
-Dockerfiles for runtime images are defined in the `core` directory. Each runtime version folder has a custom `Dockerfile` and `package.json`. If you need to add extra dependencies to a runtime version - modify these files.
-
-The `core/nodejsActionBase` folder contains the Node.js app server used to implement the [action interface](https://github.com/apache/openwhisk/blob/master/docs/actions-new.md#action-interface), used by the platform to inject action code into the runtime and fire invocation requests. This common code is used in all runtime versions.
-
-### Build <a name="build_dradle"></a>
-
-- Run the `distDocker` command to generate local Docker images for the different runtime versions. (Make sure docker daemon is running)
-
-```
-./gradlew core:nodejs10Action:distDocker
-./gradlew core:nodejs12Action:distDocker
-./gradlew core:nodejs14Action:distDocker
-```
-
-This will return the following runtime images with the following names: `action-nodejs-v10`, `action-nodejs-v12` and `action-nodejs-v14`.
-
-### Testing
-
-- Install project dependencies from the top-level Apache OpenWhisk [project](https://github.com/apache/openwhisk), which ensures correct versions of dependent libraries are available in the Maven cache.
-
-```
-./gradlew install
-```
-
-*This command **MUST BE** run from the directory containing the main Apache OpenWhisk [repository](https://github.com/apache/openwhisk), not this repository's directory.*
-
-- Build the local Docker images for the runtime versions (see the instructions above).
-- Build the custom Docker images used in local testing.
-
-```
-./gradlew tests:dat:docker:nodejs10docker:distDocker
-./gradlew tests:dat:docker:nodejs12docker:distDocker
-./gradlew tests:dat:docker:nodejs14docker:distDocker
-```
-
-- Run the project tests.
-
-```
-./gradlew :tests:test
-```
