This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/incubator-openwhisk-runtime-php.git


The following commit(s) were added to refs/heads/master by this push:
     new 86c0a91  Add PHP 7.2.6 runtime (#28)
86c0a91 is described below

commit 86c0a91b6bf45837faf0fc9f7057e3b349d37e85
Author: Rob Allen <[email protected]>
AuthorDate: Wed Jun 20 15:38:46 2018 +0100

    Add PHP 7.2.6 runtime (#28)
---
 README.md                                          |  35 +-
 ansible/environments/local/group_vars/all          |   8 +-
 .../test.sh => core/php7.2Action/CHANGELOG.md      |  40 +-
 core/php7.2Action/Dockerfile                       |  63 +++
 settings.gradle => core/php7.2Action/build.gradle  |  21 +-
 core/php7.2Action/composer.json                    |  11 +
 core/php7.2Action/php.ini                          |  37 ++
 core/php7.2Action/router.php                       | 342 +++++++++++++++
 settings.gradle                                    |   1 +
 .../Php71ActionContainerTests.scala                | 470 +--------------------
 .../Php72ActionContainerTests.scala                |  23 +-
 ...rTests.scala => Php7ActionContainerTests.scala} |  44 +-
 tools/travis/test.sh                               |   2 +-
 13 files changed, 547 insertions(+), 550 deletions(-)

diff --git a/README.md b/README.md
index 5d66dcc..1833a8e 100644
--- a/README.md
+++ b/README.md
@@ -22,33 +22,54 @@
 [![Build 
Status](https://travis-ci.org/apache/incubator-openwhisk-runtime-php.svg?branch=master)](https://travis-ci.org/apache/incubator-openwhisk-runtime-php)
 
 
+## PHP versions
+
+This runtime provides PHP 7.2 and 7.1.
+
 ### Give it a try today
 To use as a docker action
+
+PHP 7.2:
 ```
-wsk action update myAction myAction.php --docker 
openwhisk/action-php-v7.1:1.0.0
+wsk action update myAction myAction.php --docker 
openwhisk/action-php-v7.2:latest
 ```
+
+PHP 7.1:
+```
+wsk action update myAction myAction.php --docker 
openwhisk/action-php-v7.1:latest
+```
+
 This works on any deployment of Apache OpenWhisk
 
 ### To use on deployment that contains the rutime as a kind
 To use as a kind action
+
+PHP 7.2:
+```
+wsk action update myAction myAction.php --kind php:7.2
+```
+
+PHP 7.1:
 ```
 wsk action update myAction myAction.php --kind php:7.1
 ```
 
 ### Local development
 ```
+./gradlew core:php7.2Action:distDocker
 ./gradlew core:php7.1Action:distDocker
 ```
-This will produce the image `whisk/action-php-v7.1`
+This will produce the images `whisk/action-php-v7.2` & `whisk/action-php-v7.1`
 
 Build and Push image
 ```
 docker login
+./gradlew core:php7.2Action:distDocker -PdockerImagePrefix=$prefix-user 
-PdockerRegistry=docker.io
 ./gradlew core:php7.1Action:distDocker -PdockerImagePrefix=$prefix-user 
-PdockerRegistry=docker.io
 ```
 
-Deploy OpenWhisk using ansible environment that contains the kind `php:7.1`
-Assuming you have OpenWhisk already deploy localy and `OPENWHISK_HOME` 
pointing to root directory of OpenWhisk core repository.
+Deploy OpenWhisk using ansible environment that contains the kinds `php:7.2` & 
`php:7.1`
+Assuming you have OpenWhisk already deploy locally and `OPENWHISK_HOME` 
pointing to root directory of OpenWhisk core repository.
 
 Set `ROOTDIR` to the root directory of this repository.
 
@@ -71,12 +92,16 @@ wskdev fresh -t local-php
 
 To use as docker action push to your own dockerhub account
 ```
+docker tag whisk/php7.2Action $user_prefix/action-php-v7.2
+docker push $user_prefix/action-php-v7.2
+```
+```
 docker tag whisk/php7.1Action $user_prefix/action-php-v7.1
 docker push $user_prefix/action-php-v7.1
 ```
 Then create the action using your the image from dockerhub
 ```
-wsk action update myAction myAction.php --docker $user_prefix/action-php-v7.1
+wsk action update myAction myAction.php --docker $user_prefix/action-php-v7.2
 ```
 The `$user_prefix` is usually your dockerhub user id.
 
diff --git a/ansible/environments/local/group_vars/all 
b/ansible/environments/local/group_vars/all
index 1b3fe54..936316f 100755
--- a/ansible/environments/local/group_vars/all
+++ b/ansible/environments/local/group_vars/all
@@ -40,9 +40,15 @@ runtimes_manifest:
       deprecated: false
     php:
     - kind: "php:7.1"
-      default: true
+      default: false
       image:
         name: "action-php-v7.1"
       deprecated: false
+    php:
+    - kind: "php:7.2"
+      default: true
+      image:
+        name: "action-php-v7.2"
+      deprecated: false
   blackboxes:
     - name: "dockerskeleton"
diff --git a/tools/travis/test.sh b/core/php7.2Action/CHANGELOG.md
old mode 100755
new mode 100644
similarity index 64%
copy from tools/travis/test.sh
copy to core/php7.2Action/CHANGELOG.md
index 28da4fb..702b708
--- a/tools/travis/test.sh
+++ b/core/php7.2Action/CHANGELOG.md
@@ -1,4 +1,4 @@
-#!/bin/bash
+<!--
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -15,20 +15,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-set -ex
-
-# Build script for Travis-CI.
-
-SCRIPTDIR=$(cd $(dirname "$0") && pwd)
-ROOTDIR="$SCRIPTDIR/../.."
-WHISKDIR="$ROOTDIR/../openwhisk"
-
-export OPENWHISK_HOME=$WHISKDIR
-
-cd ${ROOTDIR}
-TERM=dumb ./gradlew :tests:checkScalafmtAll
-TERM=dumb ./gradlew :tests:test --tests *Php71*Tests
-
-
-
+-->
+
+## 1.0.0
+Initial release
+
+- Added: PHP: 7.2.6
+- Added: PHP extensions in addition to the standard ones:
+    - bcmath
+    - curl
+    - gd
+    - intl
+    - mbstring
+    - mysqli
+    - pdo_mysql
+    - pdo_pgsql
+    - pdo_sqlite
+    - soap
+    - zip
+- Added: Composer packages:
+    - [guzzlehttp/guzzle](https://packagist.org/packages/guzzlehttp/guzzle): 
6.3.3
+    - [ramsey/uuid](https://packagist.org/packages/ramsey/uuid): 3.7.3
diff --git a/core/php7.2Action/Dockerfile b/core/php7.2Action/Dockerfile
new file mode 100644
index 0000000..fb08b24
--- /dev/null
+++ b/core/php7.2Action/Dockerfile
@@ -0,0 +1,63 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+FROM php:7.2.6-alpine
+
+RUN \
+    apk update && apk upgrade && \
+    # install dependencies
+   apk add \
+       postgresql-dev \
+       icu \
+       icu-libs \
+       icu-dev \
+       freetype-dev \
+       libjpeg-turbo-dev \
+       libpng-dev \
+       libxml2-dev \
+   && \
+   # install useful PHP extensions
+   docker-php-ext-install \
+       opcache \
+       mysqli \
+       pdo_mysql \
+       pdo_pgsql \
+       intl \
+       bcmath \
+       zip \
+       gd \
+       soap
+
+# install composer
+RUN curl -s -f -L -o /tmp/installer.php https://getcomposer.org/installer \
+    && php /tmp/installer.php --no-ansi --install-dir=/usr/bin 
--filename=composer \
+    && composer --ansi --version --no-interaction
+
+# create src directory to store action files
+RUN mkdir -p /action/src
+
+# install Composer dependencies
+COPY composer.json /action
+RUN cd /action && /usr/bin/composer install --no-plugins --no-scripts 
--prefer-dist --no-dev -o && rm composer.lock
+
+# copy required files
+COPY router.php /action
+COPY php.ini /usr/local/etc/php
+
+# Run webserver on port 8080
+CMD [ "php", "-S", "0.0.0.0:8080", "/action/router.php" ]
+
diff --git a/settings.gradle b/core/php7.2Action/build.gradle
similarity index 66%
copy from settings.gradle
copy to core/php7.2Action/build.gradle
index 3802e56..c168aa2 100644
--- a/settings.gradle
+++ b/core/php7.2Action/build.gradle
@@ -15,22 +15,5 @@
  * limitations under the License.
  */
 
-include 'tests'
-
-include 'core:php7.1Action'
-
-rootProject.name = 'runtime-php'
-
-gradle.ext.openwhisk = [
-        version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
-    version: '2.11.11',
-    compileFlags: ['-feature', '-unchecked', '-deprecation', 
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
-    version: '1.5.0',
-    config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+ext.dockerImageName = 'action-php-v7.2'
+apply from: '../../gradle/docker.gradle'
diff --git a/core/php7.2Action/composer.json b/core/php7.2Action/composer.json
new file mode 100644
index 0000000..5819627
--- /dev/null
+++ b/core/php7.2Action/composer.json
@@ -0,0 +1,11 @@
+{
+    "config": {
+        "platform": {
+            "php": "7.2"
+        }
+    },
+    "require": {
+        "guzzlehttp/guzzle": "6.3.3",
+        "ramsey/uuid": "3.7.3"
+    }
+}
diff --git a/core/php7.2Action/php.ini b/core/php7.2Action/php.ini
new file mode 100644
index 0000000..bee173d
--- /dev/null
+++ b/core/php7.2Action/php.ini
@@ -0,0 +1,37 @@
+; Licensed to the Apache Software Foundation (ASF) under one or more
+; contributor license agreements.  See the NOTICE file distributed with
+; this work for additional information regarding copyright ownership.
+; The ASF licenses this file to You under the Apache License, Version 2.0
+; (the "License"); you may not use this file except in compliance with
+; the License.  You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+[PHP]
+short_open_tag = Off
+output_buffering = Off
+expose_php = Off
+max_execution_time = 0
+memory_limit = -1
+error_reporting = E_ALL
+display_errors = Off
+log_errors = On
+log_errors_max_len = 0
+html_errors = Off
+variables_order = "EGPCS"
+request_order = "GP"
+post_max_size = 0
+enable_dl = Off
+zend.assertions = -1
+
+[opcache]
+opcache.enable=1
+opcache.enable_cli=1
+opcache.max_accelerated_files=7963
+opcache.validate_timestamps=0
diff --git a/core/php7.2Action/router.php b/core/php7.2Action/router.php
new file mode 100644
index 0000000..6a2c570
--- /dev/null
+++ b/core/php7.2Action/router.php
@@ -0,0 +1,342 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * router.php
+ *
+ * This file is the API client for the action. The controller POSTs /init to 
set up the action and
+ * then POSTs to /run to invoke it.
+ */
+
+namespace OpenWhiskPhpRuntime;
+
+use RuntimeException;
+use Throwable;
+use ZipArchive;
+
+// set up an output buffer to redirect any script output to stdout, rather 
than the default
+// php://output, so that it goes to the logs, not the HTTP client.
+ob_start(function ($data) {
+    file_put_contents("php://stdout", $data);
+    return '';
+}, 1, PHP_OUTPUT_HANDLER_CLEANABLE | PHP_OUTPUT_HANDLER_FLUSHABLE | 
PHP_OUTPUT_HANDLER_REMOVABLE);
+
+// Register a shutdown function so that we can fail gracefully when a fatal 
error occurs
+register_shutdown_function(function () {
+    $error = error_get_last();
+    if ($error && in_array($error["type"], [E_ERROR, E_CORE_ERROR, 
E_COMPILE_ERROR, E_USER_ERROR])) {
+        $result = ['error' => 'An error occurred running the action.'];
+        $body = json_encode((object)$result);
+        header('HTTP/1.0 502 Bad Gateway');
+        header('Content-Type: application/json');
+        header("Content-Length: " . mb_strlen($body));
+
+        // write out sentinels as we've finished all log output
+        file_put_contents("php://stdout", 
"XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX\n");
+        file_put_contents("php://stderr", 
"XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX\n");
+
+        ob_end_clean();
+        echo $body;
+        exit;
+    }
+});
+
+const ACTION_SRC_FILENAME = 'index.php';
+const SRC_DIR  = __DIR__ . '/src';
+const ACTION_CONFIG_FILE = __DIR__. '/config.json';
+const ACTION_SRC_FILE = SRC_DIR . '/' . ACTION_SRC_FILENAME;
+const TMP_ZIP_FILE = '/action.zip';
+
+// execute the revelant endpoint
+$result = route($_SERVER['REQUEST_URI']);
+sendResponse($result);
+exit;
+
+/**
+ * executes the relevant method for a given URL and return an array of data to 
send to the client
+ */
+function route(string $uri) : array
+{
+    try {
+        switch ($uri) {
+            case '/init':
+                return init();
+
+            case '/run':
+                $result = run();
+                writeSentinels();
+                return $result;
+
+            default:
+                throw new RuntimeException('Unexpected call to ' . 
$_SERVER["REQUEST_URI"], 500);
+        }
+    } catch (Throwable $e) {
+        $code = $e->getCode() < 400 ? 500 : $e->getCode();
+
+        if ($code != 502) {
+            writeTo("php://stdout", 'Error: ' . $e->getMessage());
+        }
+        writeSentinels();
+
+        http_response_code($code);
+        return ['error' => $e->getMessage()];
+    }
+}
+
+/**
+ * Send the response back
+ */
+function sendResponse(array $result) : void
+{
+    $body = json_encode((object)$result);
+    header('Content-Type: application/json');
+    header("Content-Length: " . mb_strlen($body));
+    ob_end_clean();
+    echo $body;
+}
+
+/**
+ * Handle the /init endpoint
+ *
+ * This end point is called once per container creation. It gives us the code 
we need
+ * to run and the name of the function within that code that's the entry 
point. As PHP
+ * has a setup/teardown model, we store the function name to a config file for 
retrieval
+ * in the /run end point.
+ *
+ * @return array Data to return to the client
+ */
+function init() : array
+{
+    // data is POSTed to us as a JSON string
+    $post = file_get_contents('php://input');
+    $data = json_decode($post, true)['value'] ?? [];
+
+    $name = $data['name'] ?? '';         // action name
+    $main = $data['main'] ?? 'main';     // function to call (default: main)
+    $code = trim($data['code'] ?? '');   // source code to run
+    $binary = $data['binary'] ?? false;  // code is binary?
+
+    if (!$code) {
+        throw new RuntimeException("No code to execute");
+    }
+
+    if ($binary) {
+        // binary code is a zip file that's been base64 encoded, so unzip it
+        unzipString($code, SRC_DIR);
+
+        // if the zip file didn't contain a vendor directory, move our vendor 
into the src folder
+        if (! file_exists(SRC_DIR . '/vendor/autoload.php')) {
+            exec('mv ' . escapeshellarg(__DIR__ . '/vendor') . ' ' . 
escapeshellarg(SRC_DIR . '/vendor'));
+        }
+
+        // check that we have the expected action source file
+        if (! file_exists(ACTION_SRC_FILE)) {
+            throw new RuntimeException('Zipped actions must contain ' . 
ACTION_SRC_FILENAME . ' at the root.', 500);
+        }
+    } else {
+        // non-binary code is a text string, so save to disk
+        file_put_contents(ACTION_SRC_FILE, $code);
+
+        // move vendor folder into the src folder
+        exec('mv ' . escapeshellarg(__DIR__ . '/vendor') . ' ' . 
escapeshellarg(SRC_DIR . '/vendor'));
+    }
+
+    // is action file valid PHP? run `php -l` to find out
+    list($returnCode, $stdout, $stderr) = runPHP(['-l', '-f', 
ACTION_SRC_FILE]);
+    if ($returnCode != 0) {
+        writeTo("php://stderr", $stderr);
+        writeTo("php://stdout", $stdout);
+
+        $message = 'PHP syntax error in ' . ($binary ? ACTION_SRC_FILENAME : 
'action.');
+        throw new RuntimeException($message, 500);
+    }
+
+    // does the action have the expected function name?
+    $testCode = 'require "' . ACTION_SRC_FILE . '"; exit((int)(! 
function_exists("' . $main .'")));';
+    list($returnCode, $stdout, $stderr) = runPHP(['-r', $testCode]);
+    if ($returnCode != 0) {
+        writeTo("php://stderr", $stderr);
+        writeTo("php://stdout", $stdout);
+        throw new RuntimeException("The function $main is missing.");
+    }
+
+    // write config file for use by /run
+    $config = [
+        'file' => ACTION_SRC_FILE,
+        'function' => $main,
+        'name' => $name,
+    ];
+    file_put_contents(ACTION_CONFIG_FILE, '<?php return ' . 
var_export($config, true) . ';');
+
+    // reset OPcache
+    opcache_reset();
+
+    return ["OK" => true];
+}
+
+/**
+ * Handle the /run endpoint
+ *
+ * This end point is called once per action invocation. We load the function 
name from
+ * the config file and then invoke it. Note that as PHP writes to 
php://output, we
+ * capture in an output buffer and write the buffer to stdout for the 
OpenWhisk logs.
+ *
+ * @return array Data to return to the client
+ */
+function run() : array
+{
+    $config = require ACTION_CONFIG_FILE;
+    $_actionFile = $config['file'];
+    $_functionName = $config['function'];
+
+    // Extract the posted data
+    $post = json_decode(file_get_contents('php://input'), true);
+    if (!is_array($post)) {
+        $post = [];
+    }
+
+    // assign environment variables from the posted data
+    foreach (['api_key', 'namespace', 'action_name', 'activation_id', 
'deadline'] as $param) {
+        if (array_key_exists($param, $post)) {
+            $_ENV['__OW_' . strtoupper($param)] = $post[$param];
+        }
+    }
+
+    // extract the function arguments from the posted data's "value" field
+    $args = [];
+    if (array_key_exists('value', $post) && is_array($post['value'])) {
+        $args = $post['value'];
+    }
+    $_ENV['WHISK_INPUT'] = json_encode($args);
+
+    // run the action
+    require __DIR__ . '/src/vendor/autoload.php';
+    require $_actionFile;
+    $result = $_functionName($args);
+    if (is_array($result)) {
+        return $result;
+    } elseif (is_scalar($result)) {
+        file_put_contents("php://stderr", 'Result must be an array but has 
type "'
+            . gettype($result) . '": ' . (string)$result . "\n");
+        file_put_contents("php://stdout", 'The action did not return a 
dictionary.');
+        throw new RuntimeException('The action did not return a dictionary.', 
502);
+    } elseif (is_object($result)) {
+        if (method_exists($result, 'getArrayCopy')) {
+            return $result->getArrayCopy();
+        } elseif ($result instanceof \stdClass) {
+            return (array)$result;
+        }
+    }
+
+    return [];
+}
+
+/**
+ * Unzip a base64 encoded string to a directory
+ */
+function unzipString(string $b64Data, $dir): void
+{
+    file_put_contents(TMP_ZIP_FILE, base64_decode($b64Data));
+
+    $zip = new ZipArchive();
+    $res = $zip->open(TMP_ZIP_FILE);
+    if ($res !== true) {
+        $reasons = [
+            ZipArchive::ER_EXISTS => "File already exists.",
+            ZipArchive::ER_INCONS => "Zip archive inconsistent.",
+            ZipArchive::ER_INVAL => "Invalid argument.",
+            ZipArchive::ER_MEMORY => "Malloc failure.",
+            ZipArchive::ER_NOENT => "No such file.",
+            ZipArchive::ER_NOZIP => "Not a zip archive.",
+            ZipArchive::ER_OPEN => "Can't open file.",
+            ZipArchive::ER_READ => "Read error.",
+            ZipArchive::ER_SEEK => "Seek error.",
+        ];
+        $reason = $reasons[$res] ?? "Unknown error: $res.";
+        throw new RuntimeException("Failed to open zip file: $reason", 500);
+    }
+
+    $res = $zip->extractTo($dir . '/');
+    $zip->close();
+}
+
+/**
+ * Write the OpenWhisk sentinels to stdout and stderr so that it knows that 
we've finished
+ * writing data to them.
+ *
+ * @return void
+ */
+function writeSentinels() : void
+{
+    // write out sentinels as we've finished all log output
+    writeTo("php://stderr", "XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX");
+    writeTo("php://stdout", "XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX");
+}
+
+/**
+ * Run the PHP command in a separate process
+ *
+ * This ensures that if the action causes a fatal error, we can handle it.
+ *
+ * @param  array  $args  arguments to the PHP executable
+ * @param  string $stdin stdin to pass to the process
+ * @return array         array containing [int return code, string stdout 
string stderr]
+ */
+function runPHP(array $args, string $stdin = '') : array
+{
+    $cmd = '/usr/local/bin/php ' . implode(' ', array_map('escapeshellarg', 
$args));
+
+    $process = proc_open(
+        $cmd,
+        [
+            0 => ['pipe', 'r'],
+            1 => ['pipe', 'w'],
+            2 => ['pipe', 'w'],
+        ],
+        $pipes,
+        SRC_DIR
+    );
+
+    // write to the process' stdin
+    $bytes = fwrite($pipes[0], $stdin);
+    fclose($pipes[0]);
+
+    // read the process' stdout
+    $stdout = stream_get_contents($pipes[1]);
+    fclose($pipes[1]);
+
+    // read the process' stderr
+    $stderr = stream_get_contents($pipes[2]);
+    fclose($pipes[2]);
+
+    // close process & get return code
+    $returnCode = proc_close($process);
+
+    // tidy up paths in any PHP stack traces
+    $stderr = str_replace(__DIR__ . '/', '', trim($stderr));
+    $stdout = str_replace(__DIR__ . '/', '', trim($stdout));
+
+    return [$returnCode, $stdout, $stderr];
+}
+
+function writeTo($pipe, $text)
+{
+    if ($text) {
+        file_put_contents($pipe, $text . PHP_EOL);
+    }
+}
diff --git a/settings.gradle b/settings.gradle
index 3802e56..39f191d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -18,6 +18,7 @@
 include 'tests'
 
 include 'core:php7.1Action'
+include 'core:php7.2Action'
 
 rootProject.name = 'runtime-php'
 
diff --git 
a/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala 
b/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala
index d215725..03f42f3 100644
--- 
a/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala
+++ 
b/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala
@@ -19,475 +19,9 @@ package runtime.actionContainers
 
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
-import common.WskActorSystem
-import actionContainers.{ActionContainer, BasicActionRunnerTests}
-import actionContainers.ActionContainer.withContainer
-import actionContainers.ResourceHelpers.ZipBuilder
-import spray.json._
 
 @RunWith(classOf[JUnitRunner])
-class Php71ActionContainerTests extends BasicActionRunnerTests with 
WskActorSystem {
-  // note: "out" will not be empty as the PHP web server outputs a message when
-  // it starts up
-  val enforceEmptyOutputStream = false
+class Php71ActionContainerTests extends Php7ActionContainerTests {
 
-  lazy val php71ContainerImageName = "action-php-v7.1"
-
-  override def withActionContainer(env: Map[String, String] = Map.empty)(code: 
ActionContainer => Unit) = {
-    withContainer(php71ContainerImageName, env)(code)
-  }
-
-  def withPhp71Container(code: ActionContainer => Unit) = 
withActionContainer()(code)
-
-  behavior of php71ContainerImageName
-
-  testEcho(Seq {
-    (
-      "PHP",
-      """
-          |<?php
-          |function main(array $args) : array {
-          |    echo 'hello stdout';
-          |    error_log('hello stderr');
-          |    return $args;
-          |}
-          """.stripMargin)
-  })
-
-  testNotReturningJson("""
-        |<?php
-        |function main(array $args) {
-        |    return "not a json object";
-        |}
-        """.stripMargin)
-
-  testUnicode(Seq {
-    (
-      "PHP",
-      """
-         |<?php
-         |function main(array $args) : array {
-         |    $str = $args['delimiter'] . " ☃ " . $args['delimiter'];
-         |    echo $str . "\n";
-         |    return  ["winter" => $str];
-         |}
-         """.stripMargin.trim)
-  })
-
-  testEnv(
-    Seq {
-      (
-        "PHP",
-        """
-         |<?php
-         |function main(array $args) : array {
-         |    return [
-         |       "env" => $_ENV,
-         |       "api_host" => $_ENV['__OW_API_HOST'],
-         |       "api_key" => $_ENV['__OW_API_KEY'],
-         |       "namespace" => $_ENV['__OW_NAMESPACE'],
-         |       "action_name" => $_ENV['__OW_ACTION_NAME'],
-         |       "activation_id" => $_ENV['__OW_ACTIVATION_ID'],
-         |       "deadline" => $_ENV['__OW_DEADLINE'],
-         |    ];
-         |}
-         """.stripMargin.trim)
-    },
-    enforceEmptyOutputStream)
-
-  it should "fail to initialize with bad code" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-                |<?php
-                | 10 PRINT "Hello world!"
-                | 20 GOTO 10
-            """.stripMargin
-
-      val (initCode, error) = c.init(initPayload(code))
-      initCode should not be (200)
-      error shouldBe a[Some[_]]
-      error.get shouldBe a[JsObject]
-      error.get.fields("error").toString should include("PHP syntax error")
-    }
-
-    // Somewhere, the logs should mention an error occurred.
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("error")
-        (o + e).toLowerCase should include("syntax")
-    })
-  }
-
-  it should "fail to initialize with no code" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = ""
-
-      val (initCode, error) = c.init(initPayload(code))
-
-      initCode should not be (200)
-      error shouldBe a[Some[_]]
-      error.get shouldBe a[JsObject]
-      error.get.fields("error").toString should include("No code to execute")
-    }
-  }
-
-  it should "return some error on action error" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-                |<?php
-                | function main(array $args) : array {
-                |     throw new Exception ("nooooo");
-                | }
-            """.stripMargin
-
-      val (initCode, _) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runCode should not be (200)
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-    // runRes.get.fields("error").toString.toLowerCase should include("nooooo")
-    }
-
-    // Somewhere, the logs should be the error text
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("nooooo")
-    })
-
-  }
-
-  it should "support application errors" in {
-    withPhp71Container { c =>
-      val code = """
-                |<?php
-                | function main(array $args) : array {
-                |     return [ "error" => "sorry" ];
-                | }
-            """.stripMargin;
-
-      val (initCode, error) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runCode should be(200) // action writer returning an error is OK
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-      runRes.get.fields("error").toString.toLowerCase should include("sorry")
-    }
-  }
-
-  it should "fail gracefully when an action has a fatal error" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-                | <?php
-                | function main(array $args) : array {
-                |     eval("class Error {};");
-                |     return [ "hello" => "world" ];
-                | }
-            """.stripMargin;
-
-      val (initCode, _) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runCode should be(502)
-
-      runRes shouldBe defined
-      runRes.get.fields.get("error") shouldBe defined
-      runRes.get.fields("error").toString should include("An error occurred 
running the action.")
-    }
-
-    // Somewhere, the logs should be the error text
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("fatal error")
-    })
-  }
-
-  it should "suport returning a stdClass" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-                | <?php
-                | function main($params) {
-                |     $obj = new stdClass();
-                |     $obj->hello = 'world';
-                |     return $obj;
-                | }
-            """.stripMargin
-
-      val (initCode, _) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runCode should be(200) // action writer returning an error is OK
-
-      runRes shouldBe defined
-      runRes.get.fields.get("hello") shouldBe defined
-      runRes.get.fields("hello").toString.toLowerCase should include("world")
-    }
-  }
-
-  it should "support returning an object with a getArrayCopy() method" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-                | <?php
-                | function main($params) {
-                |     $obj = new ArrayObject();
-                |     $obj['hello'] = 'world';
-                |     return $obj;
-                | }
-            """.stripMargin
-
-      val (initCode, _) = c.init(initPayload(code))
-      initCode should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runCode should be(200) // action writer returning an error is OK
-
-      runRes shouldBe defined
-      runRes.get.fields.get("hello") shouldBe defined
-      runRes.get.fields.get("hello") shouldBe Some(JsString("world"))
-    }
-  }
-
-  it should "support the documentation examples (1)" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-                | <?php
-                | function main($params) {
-                |     if ($params['payload'] == 0) {
-                |         return;
-                |     } else if ($params['payload'] == 1) {
-                |         return ['payload' => 'Hello, World!'] ;        // 
indicates normal completion
-                |     } else if ($params['payload'] == 2) {
-                |         return ['error' => 'payload must be 0 or 1'];  // 
indicates abnormal completion
-                |     }
-                | }
-            """.stripMargin
-
-      c.init(initPayload(code))._1 should be(200)
-
-      val (c1, r1) = c.run(runPayload(JsObject("payload" -> JsNumber(0))))
-      val (c2, r2) = c.run(runPayload(JsObject("payload" -> JsNumber(1))))
-      val (c3, r3) = c.run(runPayload(JsObject("payload" -> JsNumber(2))))
-
-      c1 should be(200)
-      r1 should be(Some(JsObject()))
-
-      c2 should be(200)
-      r2 should be(Some(JsObject("payload" -> JsString("Hello, World!"))))
-
-      c3 should be(200) // application error, not container or system
-      r3.get.fields.get("error") shouldBe Some(JsString("payload must be 0 or 
1"))
-    }
-  }
-
-  it should "have Guzzle and Uuid packages available" in {
-    // GIVEN that it should "error when requiring a non-existent package" (see 
test above for this)
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-                | <?php
-                | use Ramsey\Uuid\Uuid;
-                | use GuzzleHttp\Client;
-                | function main(array $args) {
-                |     Uuid::uuid4();
-                |     new Client();
-                | }
-            """.stripMargin
-
-      val (initCode, _) = c.init(initPayload(code))
-
-      initCode should be(200)
-
-      // WHEN I run an action that calls a Guzzle & a Uuid method
-      val (runCode, out) = c.run(runPayload(JsObject()))
-
-      // THEN it should pass only when these packages are available
-      runCode should be(200)
-    }
-  }
-
-  it should "support large-ish actions" in {
-    val thought = " I took the one less traveled by, and that has made all the 
difference."
-    val assignment = "    $x = \"" + thought + "\";\n"
-
-    val code = """
-            | <?php
-            | function main(array $args) {
-            |     $x = "hello";
-            """.stripMargin + (assignment * 7000) + """
-            |     $x = "world";
-            |     return [ "message" => $x ];
-            | }
-            """.stripMargin
-
-    // Lest someone should make it too easy.
-    code.length should be >= 500000
-
-    val (out, err) = withPhp71Container { c =>
-      c.init(initPayload(code))._1 should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-
-      runCode should be(200)
-      runRes.get.fields.get("message") shouldBe defined
-      runRes.get.fields.get("message") shouldBe Some(JsString("world"))
-    }
-  }
-
-  val exampleOutputDotPhp: String = """
-        | <?php
-        | function output($data) {
-        |     return ['result' => $data];
-        | }
-    """.stripMargin
-
-  it should "support zip-encoded packages" in {
-    val srcs = Seq(
-      Seq("output.php") -> exampleOutputDotPhp,
-      Seq("index.php") -> """
-                | <?php
-                | require __DIR__ . '/output.php';
-                | function main(array $args) {
-                |     $name = $args['name'] ?? 'stranger';
-                |     return output($name);
-                | }
-            """.stripMargin)
-
-    val code = ZipBuilder.mkBase64Zip(srcs)
-
-    val (out, err) = withPhp71Container { c =>
-      c.init(initPayload(code))._1 should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-
-      runCode should be(200)
-      runRes.get.fields.get("result") shouldBe defined
-      runRes.get.fields.get("result") shouldBe Some(JsString("stranger"))
-    }
-  }
-
-  it should "support replacing vendor in zip-encoded packages " in {
-    val srcs = Seq(
-      Seq("vendor/autoload.php") -> exampleOutputDotPhp,
-      Seq("index.php") -> """
-                | <?php
-                | function main(array $args) {
-                |     $name = $args['name'] ?? 'stranger';
-                |     return output($name);
-                | }
-            """.stripMargin)
-
-    val code = ZipBuilder.mkBase64Zip(srcs)
-
-    val (out, err) = withPhp71Container { c =>
-      c.init(initPayload(code))._1 should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-
-      runCode should be(200)
-      runRes.get.fields.get("result") shouldBe defined
-      runRes.get.fields.get("result") shouldBe Some(JsString("stranger"))
-    }
-  }
-
-  it should "fail gracefully on invalid zip files" in {
-    // Some text-file encoded to base64.
-    val code = "Q2VjaSBuJ2VzdCBwYXMgdW4gemlwLgo="
-
-    val (out, err) = withPhp71Container { c =>
-      val (initCode, error) = c.init(initPayload(code))
-      initCode should not be (200)
-      error shouldBe a[Some[_]]
-      error.get shouldBe a[JsObject]
-      error.get.fields("error").toString should include("Failed to open zip 
file")
-    }
-
-    // Somewhere, the logs should mention the failure
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("error")
-        (o + e).toLowerCase should include("failed to open zip file")
-    })
-  }
-
-  it should "fail gracefully on valid zip files that are not actions" in {
-    val srcs = Seq(Seq("hello") -> """
-                | Hello world!
-            """.stripMargin)
-
-    val code = ZipBuilder.mkBase64Zip(srcs)
-
-    val (out, err) = withPhp71Container { c =>
-      c.init(initPayload(code))._1 should not be (200)
-    }
-
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("error")
-        (o + e).toLowerCase should include("zipped actions must contain 
index.php at the root.")
-    })
-  }
-
-  it should "fail gracefully on valid zip files with invalid code in 
index.php" in {
-    val (out, err) = withPhp71Container { c =>
-      val srcs = Seq(Seq("index.php") -> """
-                    | <?php
-                    | 10 PRINT "Hello world!"
-                    | 20 GOTO 10
-                """.stripMargin)
-
-      val code = ZipBuilder.mkBase64Zip(srcs)
-
-      val (initCode, error) = c.init(initPayload(code))
-      initCode should not be (200)
-      error shouldBe a[Some[_]]
-      error.get shouldBe a[JsObject]
-      error.get.fields("error").toString should include("PHP syntax error in 
index.php")
-    }
-
-    // Somewhere, the logs should mention an error occurred.
-    checkStreams(out, err, {
-      case (o, e) =>
-        (o + e).toLowerCase should include("error")
-        (o + e).toLowerCase should include("syntax")
-    })
-  }
-
-  it should "support actions using non-default entry point" in {
-    val (out, err) = withPhp71Container { c =>
-      val code = """
-            | <?php
-            | function niam(array $args) {
-            |     return [result => "it works"];
-            | }
-            """.stripMargin
-
-      c.init(initPayload(code, main = "niam"))._1 should be(200)
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runRes.get.fields.get("result") shouldBe Some(JsString("it works"))
-    }
-  }
-
-  it should "support zipped actions using non-default entry point" in {
-    val srcs = Seq(Seq("index.php") -> """
-                | <?php
-                | function niam(array $args) {
-                |     return [result => "it works"];
-                | }
-            """.stripMargin)
-
-    val code = ZipBuilder.mkBase64Zip(srcs)
-
-    withPhp71Container { c =>
-      c.init(initPayload(code, main = "niam"))._1 should be(200)
-
-      val (runCode, runRes) = c.run(runPayload(JsObject()))
-      runRes.get.fields.get("result") shouldBe Some(JsString("it works"))
-    }
-  }
+  override lazy val phpContainerImageName = "action-php-v7.1"
 }
diff --git a/settings.gradle 
b/tests/src/test/scala/runtime/actionContainers/Php72ActionContainerTests.scala
similarity index 66%
copy from settings.gradle
copy to 
tests/src/test/scala/runtime/actionContainers/Php72ActionContainerTests.scala
index 3802e56..7faed5e 100644
--- a/settings.gradle
+++ 
b/tests/src/test/scala/runtime/actionContainers/Php72ActionContainerTests.scala
@@ -15,22 +15,13 @@
  * limitations under the License.
  */
 
-include 'tests'
+package runtime.actionContainers
 
-include 'core:php7.1Action'
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
 
-rootProject.name = 'runtime-php'
+@RunWith(classOf[JUnitRunner])
+class Php72ActionContainerTests extends Php7ActionContainerTests {
 
-gradle.ext.openwhisk = [
-        version: '1.0.0-SNAPSHOT'
-]
-
-gradle.ext.scala = [
-    version: '2.11.11',
-    compileFlags: ['-feature', '-unchecked', '-deprecation', 
'-Xfatal-warnings', '-Ywarn-unused-import']
-]
-
-gradle.ext.scalafmt = [
-    version: '1.5.0',
-    config: new File(rootProject.projectDir, '.scalafmt.conf')
-]
+  override lazy val phpContainerImageName = "action-php-v7.2"
+}
diff --git 
a/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala 
b/tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala
similarity index 93%
copy from 
tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala
copy to 
tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala
index d215725..8ac62c7 100644
--- 
a/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala
+++ 
b/tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala
@@ -26,20 +26,20 @@ import actionContainers.ResourceHelpers.ZipBuilder
 import spray.json._
 
 @RunWith(classOf[JUnitRunner])
-class Php71ActionContainerTests extends BasicActionRunnerTests with 
WskActorSystem {
+abstract class Php7ActionContainerTests extends BasicActionRunnerTests with 
WskActorSystem {
   // note: "out" will not be empty as the PHP web server outputs a message when
   // it starts up
   val enforceEmptyOutputStream = false
 
-  lazy val php71ContainerImageName = "action-php-v7.1"
+  lazy val phpContainerImageName = "action-php-v7.x"
 
   override def withActionContainer(env: Map[String, String] = Map.empty)(code: 
ActionContainer => Unit) = {
-    withContainer(php71ContainerImageName, env)(code)
+    withContainer(phpContainerImageName, env)(code)
   }
 
-  def withPhp71Container(code: ActionContainer => Unit) = 
withActionContainer()(code)
+  def withPhp7Container(code: ActionContainer => Unit) = 
withActionContainer()(code)
 
-  behavior of php71ContainerImageName
+  behavior of phpContainerImageName
 
   testEcho(Seq {
     (
@@ -96,7 +96,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
     enforceEmptyOutputStream)
 
   it should "fail to initialize with bad code" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
                 |<?php
                 | 10 PRINT "Hello world!"
@@ -119,7 +119,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "fail to initialize with no code" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = ""
 
       val (initCode, error) = c.init(initPayload(code))
@@ -132,7 +132,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "return some error on action error" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
                 |<?php
                 | function main(array $args) : array {
@@ -160,7 +160,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "support application errors" in {
-    withPhp71Container { c =>
+    withPhp7Container { c =>
       val code = """
                 |<?php
                 | function main(array $args) : array {
@@ -181,7 +181,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "fail gracefully when an action has a fatal error" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
                 | <?php
                 | function main(array $args) : array {
@@ -209,7 +209,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "suport returning a stdClass" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
                 | <?php
                 | function main($params) {
@@ -232,7 +232,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "support returning an object with a getArrayCopy() method" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
                 | <?php
                 | function main($params) {
@@ -255,7 +255,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "support the documentation examples (1)" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
                 | <?php
                 | function main($params) {
@@ -288,7 +288,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
 
   it should "have Guzzle and Uuid packages available" in {
     // GIVEN that it should "error when requiring a non-existent package" (see 
test above for this)
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
                 | <?php
                 | use Ramsey\Uuid\Uuid;
@@ -328,7 +328,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
     // Lest someone should make it too easy.
     code.length should be >= 500000
 
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       c.init(initPayload(code))._1 should be(200)
 
       val (runCode, runRes) = c.run(runPayload(JsObject()))
@@ -360,7 +360,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
 
     val code = ZipBuilder.mkBase64Zip(srcs)
 
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       c.init(initPayload(code))._1 should be(200)
 
       val (runCode, runRes) = c.run(runPayload(JsObject()))
@@ -384,7 +384,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
 
     val code = ZipBuilder.mkBase64Zip(srcs)
 
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       c.init(initPayload(code))._1 should be(200)
 
       val (runCode, runRes) = c.run(runPayload(JsObject()))
@@ -399,7 +399,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
     // Some text-file encoded to base64.
     val code = "Q2VjaSBuJ2VzdCBwYXMgdW4gemlwLgo="
 
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val (initCode, error) = c.init(initPayload(code))
       initCode should not be (200)
       error shouldBe a[Some[_]]
@@ -422,7 +422,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
 
     val code = ZipBuilder.mkBase64Zip(srcs)
 
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       c.init(initPayload(code))._1 should not be (200)
     }
 
@@ -434,7 +434,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "fail gracefully on valid zip files with invalid code in 
index.php" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val srcs = Seq(Seq("index.php") -> """
                     | <?php
                     | 10 PRINT "Hello world!"
@@ -459,7 +459,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
   }
 
   it should "support actions using non-default entry point" in {
-    val (out, err) = withPhp71Container { c =>
+    val (out, err) = withPhp7Container { c =>
       val code = """
             | <?php
             | function niam(array $args) {
@@ -483,7 +483,7 @@ class Php71ActionContainerTests extends 
BasicActionRunnerTests with WskActorSyst
 
     val code = ZipBuilder.mkBase64Zip(srcs)
 
-    withPhp71Container { c =>
+    withPhp7Container { c =>
       c.init(initPayload(code, main = "niam"))._1 should be(200)
 
       val (runCode, runRes) = c.run(runPayload(JsObject()))
diff --git a/tools/travis/test.sh b/tools/travis/test.sh
index 28da4fb..05d080e 100755
--- a/tools/travis/test.sh
+++ b/tools/travis/test.sh
@@ -28,7 +28,7 @@ export OPENWHISK_HOME=$WHISKDIR
 
 cd ${ROOTDIR}
 TERM=dumb ./gradlew :tests:checkScalafmtAll
-TERM=dumb ./gradlew :tests:test --tests *Php71*Tests
+TERM=dumb ./gradlew :tests:test
 
 
 

Reply via email to