You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2018/12/12 11:31:43 UTC

[GitHub] csantanapr closed pull request #46: PHP 7.3 runtime

csantanapr closed pull request #46: PHP 7.3 runtime
URL: https://github.com/apache/incubator-openwhisk-runtime-php/pull/46
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/README.md b/README.md
index 1833a8e..3e22d34 100644
--- a/README.md
+++ b/README.md
@@ -24,11 +24,16 @@
 
 ## PHP versions
 
-This runtime provides PHP 7.2 and 7.1.
+This runtime provides PHP 7.3, 7.2 and 7.1.
 
 ### Give it a try today
 To use as a docker action
 
+PHP 7.3:
+```
+wsk action update myAction myAction.php --docker openwhisk/action-php-v7.3:latest
+```
+
 PHP 7.2:
 ```
 wsk action update myAction myAction.php --docker openwhisk/action-php-v7.2:latest
@@ -41,9 +46,14 @@ wsk action update myAction myAction.php --docker openwhisk/action-php-v7.1:lates
 
 This works on any deployment of Apache OpenWhisk
 
-### To use on deployment that contains the rutime as a kind
+### To use on deployment that contains the runtime as a kind
 To use as a kind action
 
+PHP 7.3:
+```
+wsk action update myAction myAction.php --kind php:7.3
+```
+
 PHP 7.2:
 ```
 wsk action update myAction myAction.php --kind php:7.2
@@ -56,19 +66,21 @@ wsk action update myAction myAction.php --kind php:7.1
 
 ### Local development
 ```
+./gradlew core:php7.3Action:distDocker
 ./gradlew core:php7.2Action:distDocker
 ./gradlew core:php7.1Action:distDocker
 ```
-This will produce the images `whisk/action-php-v7.2` & `whisk/action-php-v7.1`
+This will produce the images `whisk/action-php-v7.3`, `whisk/action-php-v7.2` & `whisk/action-php-v7.1`
 
 Build and Push image
 ```
 docker login
+./gradlew core:php7.3Action:distDocker -PdockerImagePrefix=$prefix-user -PdockerRegistry=docker.io
 ./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 kinds `php:7.2` & `php:7.1`
+Deploy OpenWhisk using ansible environment that contains the kinds `php:7.3`, `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.
@@ -92,6 +104,10 @@ 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.3
+docker push $user_prefix/action-php-v7.3
+```
+```
 docker tag whisk/php7.2Action $user_prefix/action-php-v7.2
 docker push $user_prefix/action-php-v7.2
 ```
@@ -101,7 +117,7 @@ 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.2
+wsk action update myAction myAction.php --docker $user_prefix/action-php-v7.3
 ```
 The `$user_prefix` is usually your dockerhub user id.
 
diff --git a/core/php7.3Action/CHANGELOG.md b/core/php7.3Action/CHANGELOG.md
new file mode 100644
index 0000000..ce138a8
--- /dev/null
+++ b/core/php7.3Action/CHANGELOG.md
@@ -0,0 +1,38 @@
+<!--
+#
+# 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.
+#
+-->
+
+## 1.0.0
+Initial release
+
+- Added: PHP: 7.3.0
+- 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.8.0
diff --git a/core/php7.3Action/Dockerfile b/core/php7.3Action/Dockerfile
new file mode 100644
index 0000000..85c7801
--- /dev/null
+++ b/core/php7.3Action/Dockerfile
@@ -0,0 +1,71 @@
+#
+# 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 openwhisk/actionloop:410d006 as builder
+
+FROM php:7.3.0-cli-stretch
+
+# install dependencies
+RUN \
+    apt-get -y update && \
+    apt-get -y install \
+      libfreetype6-dev \
+      libicu-dev \
+      libicu57 \
+      libjpeg-dev \
+      libpng-dev \
+      libxml2-dev \
+      libzip-dev \
+      postgresql-server-dev-9.6 \
+      unzip \
+      zlib1g-dev
+
+# Install useful PHP extensions
+RUN \
+    docker-php-ext-install \
+      bcmath \
+      gd \
+      intl \
+      mysqli \
+      opcache \
+      pdo_mysql \
+      pdo_pgsql \
+      soap \
+      zip
+
+COPY php.ini /usr/local/etc/php
+
+# 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 --no-plugins --no-scripts
+
+
+# install default Composer dependencies
+RUN mkdir -p /phpAction/composer
+COPY composer.json /phpAction/composer
+RUN cd /phpAction/composer && /usr/bin/composer install --no-plugins --no-scripts --prefer-dist --no-dev -o && rm composer.lock
+
+# install proxy binary alogn with compile and launcher scripts
+RUN mkdir -p /phpAction/action
+WORKDIR /phpAction
+COPY --from=builder /bin/proxy /bin/proxy
+ADD compile /bin/compile
+ADD runner.php /bin/runner.php
+ENV OW_COMPILER=/bin/compile
+
+ENTRYPOINT [ "/bin/proxy" ]
diff --git a/core/php7.3Action/build.gradle b/core/php7.3Action/build.gradle
new file mode 100644
index 0000000..fea7083
--- /dev/null
+++ b/core/php7.3Action/build.gradle
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+ext.dockerImageName = 'action-php-v7.3'
+apply from: '../../gradle/docker.gradle'
diff --git a/core/php7.3Action/compile b/core/php7.3Action/compile
new file mode 100755
index 0000000..d74939b
--- /dev/null
+++ b/core/php7.3Action/compile
@@ -0,0 +1,82 @@
+#!/usr/bin/env php
+<?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.
+ */
+
+/**
+ * compile
+ *
+ * This file is launched by the action proxy.
+ * It copies runner.php to right source directory and creates a bash exec script
+ * that the action proxy will call to start everything off
+ */
+
+main($argc, $argv);
+exit;
+
+function main($argc, $argv)
+{
+    if ($argc < 4) {
+        print("usage: <main-function-name> <source-dir> <bin-dir>");
+        exit(1);
+    }
+    $main = $argv[1];
+    $src = realpath($argv[2]);
+    $bin = realpath($argv[3]);
+
+    $shim = $bin.'/exec';
+
+    sources($src);
+    build($shim, $src, $main);
+}
+
+/**
+ * Sort out the source code
+ *
+ * 1. Copy src/exec to src/index.php if necessary
+ * 2. Ensure vendor directory exists
+ */
+function sources(string $src)
+{
+    // If the file uploaded by the user is a plain PHP file, then
+    // the filename will be called exec by the action proxy.
+    // Rename it to index.php
+    if (file_exists($src . '/exec')) {
+        rename($src . '/exec', $src . '/index.php');
+    }
+
+    // put vendor in the right place if it doesn't exist
+    if (!is_dir($src . '/vendor')) {
+        exec('cp -a /phpAction/composer/vendor ' . escapeshellarg($src . '/vendor'));
+    }
+}
+
+/**
+ * Create bin/exec shim
+ */
+function build(string $shim, string $src, string $main) : void
+{
+    $contents = <<<EOT
+#!/bin/bash
+cd $src
+exec php -f /bin/runner.php -- "$main"
+
+EOT;
+
+    file_put_contents($shim, $contents);
+    chmod($shim, 0755);
+}
diff --git a/core/php7.3Action/composer.json b/core/php7.3Action/composer.json
new file mode 100644
index 0000000..f1cf236
--- /dev/null
+++ b/core/php7.3Action/composer.json
@@ -0,0 +1,11 @@
+{
+    "config": {
+        "platform": {
+            "php": "7.3"
+        }
+    },
+    "require": {
+        "guzzlehttp/guzzle": "6.3.3",
+        "ramsey/uuid": "3.8.0"
+    }
+}
diff --git a/core/php7.3Action/php.ini b/core/php7.3Action/php.ini
new file mode 100644
index 0000000..bee173d
--- /dev/null
+++ b/core/php7.3Action/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.3Action/runner.php b/core/php7.3Action/runner.php
new file mode 100755
index 0000000..6941986
--- /dev/null
+++ b/core/php7.3Action/runner.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * PHP Action runner
+ *
+ * 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.
+ */
+
+
+// open fd/3 as that's where we send the result
+$fd3 = fopen('php://fd/3', 'w');
+
+// Register a shutdown function so that we can fail gracefully when a fatal error occurs
+register_shutdown_function(function () use ($fd3) {
+    $error = error_get_last();
+    if ($error && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR])) {
+        file_put_contents('php://stderr', "An error occurred running the action.\n");
+        fwrite($fd3, "An error occurred running the action.\n");
+    }
+    fclose($fd3);
+});
+
+require 'vendor/autoload.php';
+require 'index.php';
+
+// retrieve main function
+$__functionName = $argv[1] ?? 'main';
+
+
+// read stdin
+while ($f = fgets(STDIN)) {
+    // call the function
+    $data = json_decode($f ?? '', true);
+    if (!is_array($data)) {
+        $data = [];
+    }
+
+    // convert all parameters other than value to environment variables
+    foreach ($data as $key => $value) {
+        if ($key == 'value') {
+            $_ENV['WHISK_INPUT'] = $data['value'] ?? [];
+        } else {
+            $_ENV['__OW_' . strtoupper($key)] = $value;
+        }
+    }
+
+    $values = $data['value'] ?? [];
+    try {
+        $result = $__functionName($values);
+
+        // convert result to an array if we can
+        if (is_object($result)) {
+            if (method_exists($result, 'getArrayCopy')) {
+                $result = $result->getArrayCopy();
+            } elseif ($result instanceof stdClass) {
+                $result = (array)$result;
+            }
+        } elseif ($result === null) {
+            $result = [];
+        }
+
+        // process the result
+        if (!is_array($result)) {
+            file_put_contents('php://stderr', 'Result must be an array but has type "'
+                . gettype($result) . '": ' . (string)$result);
+            file_put_contents('php://stdout', 'The action did not return a dictionary.');
+            $result = (string)$result;
+        } else {
+            $result = json_encode((object)$result);
+        }
+    } catch (Throwable $e) {
+        file_put_contents('php://stderr', (string)$e);
+        $result = 'An error occurred running the action.';
+    }
+
+    // ensure that the sentinels will be on their own lines
+    file_put_contents('php://stderr', "\n");
+    file_put_contents('php://stdout', "\n");
+
+    // cast result to an object for json_encode to ensure that an empty array becomes "{}" & send to fd/3
+    fwrite($fd3, $result . "\n");
+}
diff --git a/settings.gradle b/settings.gradle
index 0e32a1e..da27e32 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -19,6 +19,7 @@ include 'tests'
 
 include 'core:php7.1Action'
 include 'core:php7.2Action'
+include 'core:php7.3Action'
 
 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 44352d9..ca9e619 100644
--- a/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/Php71ActionContainerTests.scala
@@ -19,6 +19,8 @@ package runtime.actionContainers
 
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
+import actionContainers.ResourceHelpers.ZipBuilder
+import spray.json._
 
 @RunWith(classOf[JUnitRunner])
 class Php71ActionContainerTests extends Php7ActionContainerTests {
@@ -27,4 +29,89 @@ class Php71ActionContainerTests extends Php7ActionContainerTests {
 
   override val testLargeInput = TestConfig("", skipTest = true)
 
+  it should "fail to initialize with bad code" in {
+    val (out, err) = withPhp7Container { 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 gracefully on invalid zip files" in {
+    // Some text-file encoded to base64.
+    val code = "Q2VjaSBuJ2VzdCBwYXMgdW4gemlwLgo="
+
+    val (out, err) = withPhp7Container { 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) = withPhp7Container { 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) = withPhp7Container { 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")
+    })
+  }
 }
diff --git a/tests/src/test/scala/runtime/actionContainers/Php72ActionContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/Php72ActionContainerTests.scala
index 7faed5e..80897cc 100644
--- a/tests/src/test/scala/runtime/actionContainers/Php72ActionContainerTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/Php72ActionContainerTests.scala
@@ -19,9 +19,97 @@ package runtime.actionContainers
 
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
+import actionContainers.ResourceHelpers.ZipBuilder
+import spray.json._
 
 @RunWith(classOf[JUnitRunner])
 class Php72ActionContainerTests extends Php7ActionContainerTests {
 
   override lazy val phpContainerImageName = "action-php-v7.2"
+
+  it should "fail to initialize with bad code" in {
+    val (out, err) = withPhp7Container { 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 gracefully on invalid zip files" in {
+    // Some text-file encoded to base64.
+    val code = "Q2VjaSBuJ2VzdCBwYXMgdW4gemlwLgo="
+
+    val (out, err) = withPhp7Container { 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) = withPhp7Container { 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) = withPhp7Container { 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")
+    })
+  }
 }
diff --git a/tests/src/test/scala/runtime/actionContainers/Php73ActionContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/Php73ActionContainerTests.scala
new file mode 100644
index 0000000..fb51648
--- /dev/null
+++ b/tests/src/test/scala/runtime/actionContainers/Php73ActionContainerTests.scala
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package runtime.actionContainers
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class Php73ActionContainerTests extends Php7ActionContainerTests {
+
+  override lazy val phpContainerImageName = "action-php-v7.3"
+}
diff --git a/tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala
index 430ea71..35181af 100644
--- a/tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/Php7ActionContainerTests.scala
@@ -129,29 +129,6 @@ abstract class Php7ActionContainerTests extends BasicActionRunnerTests with WskA
       """.stripMargin)
   }
 
-  it should "fail to initialize with bad code" in {
-    val (out, err) = withPhp7Container { 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 "return some error on action error" in {
     val (out, err) = withPhp7Container { c =>
       val code = """
@@ -219,7 +196,6 @@ abstract class Php7ActionContainerTests extends BasicActionRunnerTests with WskA
 
       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
@@ -416,69 +392,6 @@ abstract class Php7ActionContainerTests extends BasicActionRunnerTests with WskA
     }
   }
 
-  it should "fail gracefully on invalid zip files" in {
-    // Some text-file encoded to base64.
-    val code = "Q2VjaSBuJ2VzdCBwYXMgdW4gemlwLgo="
-
-    val (out, err) = withPhp7Container { 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) = withPhp7Container { 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) = withPhp7Container { 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 zipped actions using non-default entry point" in {
     val srcs = Seq(Seq("index.php") -> """
                 | <?php
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index e3aa931..7cc36ff 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -38,6 +38,10 @@ TERM=dumb ./gradlew install
 echo "openwhisk.home=$WHISKDIR" > whisk.properties
 echo "vcap.services.file=" >> whisk.properties
 
+curl -fsSL https://get.docker.com -o get-docker.sh
+sudo sh get-docker.sh
+docker version
+
 # Build runtime
 cd $ROOTDIR
 TERM=dumb ./gradlew distDocker


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services