<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[45783] trunk: Build Tools: Miscellaneous `local-env` improvements.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/45783">45783</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/45783","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>pento</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2019-08-12 08:28:33 +0000 (Mon, 12 Aug 2019)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Build Tools: Miscellaneous `local-env` improvements.

- Move the functionality for controlling `local-env` out of `package.json`, into JS scripts.
- Merge the `docker-compose` config files, and move it to the root directory. This allows `docker-compose.override.yml` to work for local overrides.
- Fix nginx redirecting to port 80 under some circumstances.
- `npm run env:install` now creates `wp-tests.config.php` for you.
- Cleaned up a bunch of cruft in `.travis.yml`.

See <a href="https://core.trac.wordpress.org/ticket/47767">#47767</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkenv">trunk/.env</a></li>
<li><a href="#trunkgitignore">trunk/.gitignore</a></li>
<li><a href="#trunktravisyml">trunk/.travis.yml</a></li>
<li><a href="#trunkpackagelockjson">trunk/package-lock.json</a></li>
<li><a href="#trunkpackagejson">trunk/package.json</a></li>
<li><a href="#trunktoolslocalenvdefaulttemplate">trunk/tools/local-env/default.template</a></li>
<li><a href="#trunktoolslocalenvdockercomposeyml">trunk/tools/local-env/docker-compose.yml</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestse2eruntestsjs">trunk/tests/e2e/run-tests.js</a></li>
<li>trunk/tools/local-env/scripts/</li>
<li><a href="#trunktoolslocalenvscriptsdockerjs">trunk/tools/local-env/scripts/docker.js</a></li>
<li><a href="#trunktoolslocalenvscriptsinstalljs">trunk/tools/local-env/scripts/install.js</a></li>
<li><a href="#trunktoolslocalenvscriptsstartjs">trunk/tools/local-env/scripts/start.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunktoolslocalenvdockercomposescriptsyml">trunk/tools/local-env/docker-compose.scripts.yml</a></li>
</ul>

<h3>Property Changed</h3>
<ul>
<li><a href="#trunk">trunk/</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk        2019-08-12 01:53:17 UTC (rev 45782)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk 2019-08-12 08:28:33 UTC (rev 45783)
</ins><a id="trunk"></a>
<div class="propset"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Property changes: trunk</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnignore"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: svn:ignore</h4></div>
<span class="cx" style="display: block; padding: 0 10px"> .git
</span><span class="cx" style="display: block; padding: 0 10px"> jsdoc
</span><span class="cx" style="display: block; padding: 0 10px"> vendor
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+docker-compose.override.yml
</ins><a id="trunkenv"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.env</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.env        2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/.env  2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -29,3 +29,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_WP_DEBUG_LOG=true
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_WP_DEBUG_DISPLAY=true
</span><span class="cx" style="display: block; padding: 0 10px"> LOCAL_SCRIPT_DEBUG=true
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+# The URL to use when running e2e tests.
+WP_BASE_URL=http://localhost:${LOCAL_PORT}
</ins></span></pre></div>
<a id="trunkgitignore"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.gitignore</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.gitignore  2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/.gitignore    2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -73,3 +73,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *.diff
</span><span class="cx" style="display: block; padding: 0 10px"> .svn
</span><span class="cx" style="display: block; padding: 0 10px"> !/src/js/_enqueues/vendor
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+# Files for local environment config
+/docker-compose.override.yml
</ins></span></pre></div>
<a id="trunktravisyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.travis.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.travis.yml 2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/.travis.yml   2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,7 +1,7 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-language: php
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+language: generic
+
</ins><span class="cx" style="display: block; padding: 0 10px"> services:
</span><span class="cx" style="display: block; padding: 0 10px">   - docker
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  - mysql
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> addons:
</span><span class="cx" style="display: block; padding: 0 10px">   apt:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -51,12 +51,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> before_install:
</span><span class="cx" style="display: block; padding: 0 10px"> - |
</span><span class="cx" style="display: block; padding: 0 10px">   if [[ "$WP_TRAVISCI" == "test:php" ]]; then
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      cp wp-tests-config-sample.php wp-tests-config.php
-      sed -i "s/youremptytestdbnamehere/wordpress_develop_tests/" wp-tests-config.php
-      sed -i "s/yourusernamehere/root/" wp-tests-config.php
-      sed -i "s/yourpasswordhere/password/" wp-tests-config.php
-      sed -i "s/localhost/mysql/" wp-tests-config.php
-      echo "define( 'FS_METHOD', 'direct' );" >> wp-tests-config.php
</del><span class="cx" style="display: block; padding: 0 10px">       travis_retry svn checkout https://plugins.svn.wordpress.org/wordpress-importer/tags/0.6.3/ tests/phpunit/data/plugins/wordpress-importer
</span><span class="cx" style="display: block; padding: 0 10px">   fi
</span><span class="cx" style="display: block; padding: 0 10px"> - |
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -74,16 +68,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">     echo "xdebug.ini does not exist"
</span><span class="cx" style="display: block; padding: 0 10px">   fi
</span><span class="cx" style="display: block; padding: 0 10px"> - |
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  # Export Composer's global bin dir to PATH:
-  composer config --list --global
-  export PATH=`composer config --list --global | grep '\[home\]' | { read a; echo "${a#* }/vendor/bin:$PATH"; }`
-- |
-  # Install PHPUnit for the tests that don't run in Docker.
-  if [[ "$WP_TRAVISCI" == "travis:phpunit" ]]; then
-    echo "Using PHPUnit 7.x"
-    travis_retry composer global require "phpunit/phpunit:^7"
-  fi
-- |
</del><span class="cx" style="display: block; padding: 0 10px">   # We only need to run composer install on the PHP coding standards job.
</span><span class="cx" style="display: block; padding: 0 10px">   if [[ "$WP_TRAVISCI" == "travis:phpcs" ]]; then
</span><span class="cx" style="display: block; padding: 0 10px">     composer --version
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -98,18 +82,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">   if [[ "$WP_TRAVISCI" == "test:e2e" ]] || [[ "$WP_TRAVISCI" == "test:php" ]]; then
</span><span class="cx" style="display: block; padding: 0 10px">     npm run env:start
</span><span class="cx" style="display: block; padding: 0 10px">     npm run build
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    docker-compose -f tools/local-env/docker-compose.yml run --rm mysql mysql --version
-    docker-compose -f tools/local-env/docker-compose.yml run --rm php php --version
-    docker-compose -f tools/local-env/docker-compose.yml run --rm php php -m
-    docker-compose -f tools/local-env/docker-compose.yml -f tools/local-env/docker-compose.scripts.yml run --rm phpunit phpunit --version
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    docker-compose run --rm mysql mysql --version
+    docker-compose run --rm php php --version
+    docker-compose run --rm php php -m
+    docker-compose run --rm phpunit phpunit --version
</ins><span class="cx" style="display: block; padding: 0 10px">   fi
</span><span class="cx" style="display: block; padding: 0 10px"> - |
</span><span class="cx" style="display: block; padding: 0 10px">   if [[ "$LOCAL_PHP_MEMCACHED" == "true" ]]; then
</span><span class="cx" style="display: block; padding: 0 10px">     cp tests/phpunit/includes/object-cache.php build/wp-content/object-cache.php
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    docker run --name memcached --net local-env_wpdevnet -d memcached
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    # The memcached server needs to start after `npm run env:start`, which sets up the Docker network.
+    docker run --name memcached --net wordpress-develop_wpdevnet -d memcached
</ins><span class="cx" style="display: block; padding: 0 10px">   fi
</span><span class="cx" style="display: block; padding: 0 10px"> - |
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  if [[ "$WP_TRAVISCI" == "test:e2e" ]]; then
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  if [[ "$WP_TRAVISCI" == "test:e2e" ]] || [[ "$WP_TRAVISCI" == "test:php" ]]; then
+    # Run the install process after memcached has started.
</ins><span class="cx" style="display: block; padding: 0 10px">     npm run env:install
</span><span class="cx" style="display: block; padding: 0 10px">   fi
</span><span class="cx" style="display: block; padding: 0 10px"> - npm --version
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -124,12 +110,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">     if [[ "$WP_TRAVISCI" == "test:e2e" ]]; then
</span><span class="cx" style="display: block; padding: 0 10px">       npm run test:e2e
</span><span class="cx" style="display: block; padding: 0 10px">     elif [[ "$WP_TRAVISCI" == "test:php" ]]; then
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      npm run test:php -- -- -- --verbose -c phpunit.xml.dist &&
-      npm run test:php -- -- -- --verbose -c phpunit.xml.dist --group ajax &&
-      npm run test:php -- -- -- --verbose -c tests/phpunit/multisite.xml &&
-      npm run test:php -- -- -- --verbose -c tests/phpunit/multisite.xml --group ms-files &&
-      npm run test:php -- -- -- --verbose -c phpunit.xml.dist --group external-http &&
-      npm run test:php -- -- -- --verbose -c phpunit.xml.dist --group restapi-jsclient
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      npm run test:php -- --verbose -c phpunit.xml.dist &&
+      npm run test:php -- --verbose -c phpunit.xml.dist --group ajax &&
+      npm run test:php -- --verbose -c tests/phpunit/multisite.xml &&
+      npm run test:php -- --verbose -c tests/phpunit/multisite.xml --group ms-files &&
+      npm run test:php -- --verbose -c phpunit.xml.dist --group external-http &&
+      npm run test:php -- --verbose -c phpunit.xml.dist --group restapi-jsclient
</ins><span class="cx" style="display: block; padding: 0 10px">     else
</span><span class="cx" style="display: block; padding: 0 10px">       npm run grunt $WP_TRAVISCI
</span><span class="cx" style="display: block; padding: 0 10px">     fi
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -138,9 +124,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> - |
</span><span class="cx" style="display: block; padding: 0 10px">   if [[ "$WP_TEST_REPORTER" == "true" ]]; then
</span><span class="cx" style="display: block; padding: 0 10px">     git clone https://github.com/WordPress/phpunit-test-runner.git test-runner
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    export WPT_PREPARE_DIR=$(pwd)
-    export WPT_TEST_DIR=$(pwd)
-    php test-runner/report.php
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    docker-compose run --rm -e WPT_PREPARE_DIR=/var/www -e WPT_TEST_DIR=/var/www php php test-runner/report.php
</ins><span class="cx" style="display: block; padding: 0 10px">   fi
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> notifications:
</span></span></pre></div>
<a id="trunkpackagelockjson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/package-lock.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/package-lock.json   2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/package-lock.json     2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3719,28 +3719,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "trim-right": "^1.0.1"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "babel-helper-bindify-decorators": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz",
-                       "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=",
-                       "dev": true,
-                       "requires": {
-                               "babel-runtime": "^6.22.0",
-                               "babel-traverse": "^6.24.1",
-                               "babel-types": "^6.24.1"
-                       }
-               },
-               "babel-helper-builder-binary-assignment-operator-visitor": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
-                       "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-explode-assignable-expression": "^6.24.1",
-                               "babel-runtime": "^6.22.0",
-                               "babel-types": "^6.24.1"
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "babel-helper-call-delegate": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "6.24.1",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3763,29 +3741,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "lodash": "^4.17.4"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "babel-helper-explode-assignable-expression": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
-                       "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
-                       "dev": true,
-                       "requires": {
-                               "babel-runtime": "^6.22.0",
-                               "babel-traverse": "^6.24.1",
-                               "babel-types": "^6.24.1"
-                       }
-               },
-               "babel-helper-explode-class": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz",
-                       "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-bindify-decorators": "^6.24.1",
-                               "babel-runtime": "^6.22.0",
-                               "babel-traverse": "^6.24.1",
-                               "babel-types": "^6.24.1"
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "babel-helper-function-name": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "6.24.1",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3835,19 +3790,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "lodash": "^4.17.4"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "babel-helper-remap-async-to-generator": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
-                       "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-function-name": "^6.24.1",
-                               "babel-runtime": "^6.22.0",
-                               "babel-template": "^6.24.1",
-                               "babel-traverse": "^6.24.1",
-                               "babel-types": "^6.24.1"
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "babel-helper-replace-supers": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "6.24.1",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4015,146 +3957,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "@types/babel__traverse": "^7.0.6"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "babel-plugin-syntax-async-functions": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
-                       "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-async-generators": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
-                       "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-class-constructor-call": {
-                       "version": "6.18.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
-                       "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-class-properties": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
-                       "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-decorators": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
-                       "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-do-expressions": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz",
-                       "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-dynamic-import": {
-                       "version": "6.18.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
-                       "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-exponentiation-operator": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
-                       "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-export-extensions": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
-                       "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-function-bind": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz",
-                       "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-object-rest-spread": {
-                       "version": "6.13.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
-                       "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
-                       "dev": true
-               },
-               "babel-plugin-syntax-trailing-function-commas": {
-                       "version": "6.22.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
-                       "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
-                       "dev": true
-               },
-               "babel-plugin-transform-async-generator-functions": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz",
-                       "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-remap-async-to-generator": "^6.24.1",
-                               "babel-plugin-syntax-async-generators": "^6.5.0",
-                               "babel-runtime": "^6.22.0"
-                       }
-               },
-               "babel-plugin-transform-async-to-generator": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
-                       "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-remap-async-to-generator": "^6.24.1",
-                               "babel-plugin-syntax-async-functions": "^6.8.0",
-                               "babel-runtime": "^6.22.0"
-                       }
-               },
-               "babel-plugin-transform-class-constructor-call": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz",
-                       "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-syntax-class-constructor-call": "^6.18.0",
-                               "babel-runtime": "^6.22.0",
-                               "babel-template": "^6.24.1"
-                       }
-               },
-               "babel-plugin-transform-class-properties": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
-                       "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-function-name": "^6.24.1",
-                               "babel-plugin-syntax-class-properties": "^6.8.0",
-                               "babel-runtime": "^6.22.0",
-                               "babel-template": "^6.24.1"
-                       }
-               },
-               "babel-plugin-transform-decorators": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz",
-                       "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-explode-class": "^6.24.1",
-                               "babel-plugin-syntax-decorators": "^6.13.0",
-                               "babel-runtime": "^6.22.0",
-                               "babel-template": "^6.24.1",
-                               "babel-types": "^6.24.1"
-                       }
-               },
-               "babel-plugin-transform-do-expressions": {
-                       "version": "6.22.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz",
-                       "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-syntax-do-expressions": "^6.8.0",
-                               "babel-runtime": "^6.22.0"
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "babel-plugin-transform-es2015-arrow-functions": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "6.22.0",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4367,47 +4169,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "regexpu-core": "^2.0.0"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "babel-plugin-transform-exponentiation-operator": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
-                       "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
-                       "dev": true,
-                       "requires": {
-                               "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1",
-                               "babel-plugin-syntax-exponentiation-operator": "^6.8.0",
-                               "babel-runtime": "^6.22.0"
-                       }
-               },
-               "babel-plugin-transform-export-extensions": {
-                       "version": "6.22.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz",
-                       "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-syntax-export-extensions": "^6.8.0",
-                               "babel-runtime": "^6.22.0"
-                       }
-               },
-               "babel-plugin-transform-function-bind": {
-                       "version": "6.22.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz",
-                       "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-syntax-function-bind": "^6.8.0",
-                               "babel-runtime": "^6.22.0"
-                       }
-               },
-               "babel-plugin-transform-object-rest-spread": {
-                       "version": "6.26.0",
-                       "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
-                       "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-syntax-object-rest-spread": "^6.8.0",
-                               "babel-runtime": "^6.26.0"
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "babel-plugin-transform-regenerator": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "6.26.0",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4466,53 +4227,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "babel-plugin-jest-hoist": "^24.6.0"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "babel-preset-stage-0": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz",
-                       "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-transform-do-expressions": "^6.22.0",
-                               "babel-plugin-transform-function-bind": "^6.22.0",
-                               "babel-preset-stage-1": "^6.24.1"
-                       }
-               },
-               "babel-preset-stage-1": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz",
-                       "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-transform-class-constructor-call": "^6.24.1",
-                               "babel-plugin-transform-export-extensions": "^6.22.0",
-                               "babel-preset-stage-2": "^6.24.1"
-                       }
-               },
-               "babel-preset-stage-2": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz",
-                       "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-syntax-dynamic-import": "^6.18.0",
-                               "babel-plugin-transform-class-properties": "^6.24.1",
-                               "babel-plugin-transform-decorators": "^6.24.1",
-                               "babel-preset-stage-3": "^6.24.1"
-                       }
-               },
-               "babel-preset-stage-3": {
-                       "version": "6.24.1",
-                       "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz",
-                       "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=",
-                       "dev": true,
-                       "requires": {
-                               "babel-plugin-syntax-trailing-function-commas": "^6.22.0",
-                               "babel-plugin-transform-async-generator-functions": "^6.24.1",
-                               "babel-plugin-transform-async-to-generator": "^6.24.1",
-                               "babel-plugin-transform-exponentiation-operator": "^6.24.1",
-                               "babel-plugin-transform-object-rest-spread": "^6.22.0"
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "babel-register": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "6.26.0",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6170,174 +5884,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "copyfiles": {
-                       "version": "2.1.1",
-                       "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.1.1.tgz",
-                       "integrity": "sha512-y6DZHve80whydXzBal7r70TBgKMPKesVRR1Sn/raUu7Jh/i7iSLSyGvYaq0eMJ/3Y/CKghwzjY32q1WzEnpp3Q==",
-                       "dev": true,
-                       "requires": {
-                               "glob": "^7.0.5",
-                               "minimatch": "^3.0.3",
-                               "mkdirp": "^0.5.1",
-                               "noms": "0.0.0",
-                               "through2": "^2.0.1",
-                               "yargs": "^13.2.4"
-                       },
-                       "dependencies": {
-                               "ansi-regex": {
-                                       "version": "4.1.0",
-                                       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-                                       "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
-                                       "dev": true
-                               },
-                               "ansi-styles": {
-                                       "version": "3.2.1",
-                                       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-                                       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-                                       "dev": true,
-                                       "requires": {
-                                               "color-convert": "^1.9.0"
-                                       }
-                               },
-                               "camelcase": {
-                                       "version": "5.3.1",
-                                       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-                                       "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
-                                       "dev": true
-                               },
-                               "cliui": {
-                                       "version": "5.0.0",
-                                       "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-                                       "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
-                                       "dev": true,
-                                       "requires": {
-                                               "string-width": "^3.1.0",
-                                               "strip-ansi": "^5.2.0",
-                                               "wrap-ansi": "^5.1.0"
-                                       }
-                               },
-                               "find-up": {
-                                       "version": "3.0.0",
-                                       "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-                                       "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
-                                       "dev": true,
-                                       "requires": {
-                                               "locate-path": "^3.0.0"
-                                       }
-                               },
-                               "get-caller-file": {
-                                       "version": "2.0.5",
-                                       "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-                                       "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
-                                       "dev": true
-                               },
-                               "locate-path": {
-                                       "version": "3.0.0",
-                                       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-                                       "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
-                                       "dev": true,
-                                       "requires": {
-                                               "p-locate": "^3.0.0",
-                                               "path-exists": "^3.0.0"
-                                       }
-                               },
-                               "p-limit": {
-                                       "version": "2.2.0",
-                                       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
-                                       "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
-                                       "dev": true,
-                                       "requires": {
-                                               "p-try": "^2.0.0"
-                                       }
-                               },
-                               "p-locate": {
-                                       "version": "3.0.0",
-                                       "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-                                       "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
-                                       "dev": true,
-                                       "requires": {
-                                               "p-limit": "^2.0.0"
-                                       }
-                               },
-                               "p-try": {
-                                       "version": "2.2.0",
-                                       "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-                                       "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-                                       "dev": true
-                               },
-                               "require-main-filename": {
-                                       "version": "2.0.0",
-                                       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-                                       "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
-                                       "dev": true
-                               },
-                               "string-width": {
-                                       "version": "3.1.0",
-                                       "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-                                       "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-                                       "dev": true,
-                                       "requires": {
-                                               "emoji-regex": "^7.0.1",
-                                               "is-fullwidth-code-point": "^2.0.0",
-                                               "strip-ansi": "^5.1.0"
-                                       }
-                               },
-                               "strip-ansi": {
-                                       "version": "5.2.0",
-                                       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-                                       "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-                                       "dev": true,
-                                       "requires": {
-                                               "ansi-regex": "^4.1.0"
-                                       }
-                               },
-                               "wrap-ansi": {
-                                       "version": "5.1.0",
-                                       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-                                       "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
-                                       "dev": true,
-                                       "requires": {
-                                               "ansi-styles": "^3.2.0",
-                                               "string-width": "^3.0.0",
-                                               "strip-ansi": "^5.0.0"
-                                       }
-                               },
-                               "y18n": {
-                                       "version": "4.0.0",
-                                       "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-                                       "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
-                                       "dev": true
-                               },
-                               "yargs": {
-                                       "version": "13.3.0",
-                                       "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
-                                       "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
-                                       "dev": true,
-                                       "requires": {
-                                               "cliui": "^5.0.0",
-                                               "find-up": "^3.0.0",
-                                               "get-caller-file": "^2.0.1",
-                                               "require-directory": "^2.1.1",
-                                               "require-main-filename": "^2.0.0",
-                                               "set-blocking": "^2.0.0",
-                                               "string-width": "^3.0.0",
-                                               "which-module": "^2.0.0",
-                                               "y18n": "^4.0.0",
-                                               "yargs-parser": "^13.1.1"
-                                       }
-                               },
-                               "yargs-parser": {
-                                       "version": "13.1.1",
-                                       "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
-                                       "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
-                                       "dev": true,
-                                       "requires": {
-                                               "camelcase": "^5.0.0",
-                                               "decamelize": "^1.2.0"
-                                       }
-                               }
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "core-js": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "3.1.4",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6451,31 +5997,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "sha.js": "^2.4.8"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "cross-env": {
-                       "version": "5.2.0",
-                       "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz",
-                       "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==",
-                       "dev": true,
-                       "requires": {
-                               "cross-spawn": "^6.0.5",
-                               "is-windows": "^1.0.0"
-                       },
-                       "dependencies": {
-                               "cross-spawn": {
-                                       "version": "6.0.5",
-                                       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-                                       "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-                                       "dev": true,
-                                       "requires": {
-                                               "nice-try": "^1.0.4",
-                                               "path-key": "^2.0.1",
-                                               "semver": "^5.5.0",
-                                               "shebang-command": "^1.2.0",
-                                               "which": "^1.2.9"
-                                       }
-                               }
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "cross-spawn": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "5.1.0",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6486,19 +6007,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "which": "^1.2.9"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "cross-var": {
-                       "version": "1.1.0",
-                       "resolved": "https://registry.npmjs.org/cross-var/-/cross-var-1.1.0.tgz",
-                       "integrity": "sha1-8PDUuyNdlRONGlOYQtKQ8A23HNY=",
-                       "dev": true,
-                       "requires": {
-                               "babel-preset-es2015": "^6.18.0",
-                               "babel-preset-stage-0": "^6.16.0",
-                               "babel-register": "^6.18.0",
-                               "cross-spawn": "^5.0.1",
-                               "exit": "^0.1.2"
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "crypto-browserify": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "3.12.0",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7609,41 +7117,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "is-obj": "^1.0.0"
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "dotenv-cli": {
-                       "version": "2.0.1",
-                       "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-2.0.1.tgz",
-                       "integrity": "sha512-RnjvnE+r27ni9j93w1ddMs9mQgxWlRozSfby7M4xVDJ5/DgLOFFAP92JrmXHkpn8dXCy+OObRx+w5wx0Dc3yww==",
-                       "dev": true,
-                       "requires": {
-                               "cross-spawn": "^4.0.0",
-                               "dotenv": "^7.0.0",
-                               "dotenv-expand": "^5.0.0",
-                               "minimist": "^1.1.3"
-                       },
-                       "dependencies": {
-                               "cross-spawn": {
-                                       "version": "4.0.2",
-                                       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
-                                       "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
-                                       "dev": true,
-                                       "requires": {
-                                               "lru-cache": "^4.0.1",
-                                               "which": "^1.2.9"
-                                       }
-                               },
-                               "dotenv": {
-                                       "version": "7.0.0",
-                                       "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz",
-                                       "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==",
-                                       "dev": true
-                               },
-                               "minimist": {
-                                       "version": "1.2.0",
-                                       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-                                       "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-                                       "dev": true
-                               }
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         "dotenv": {
+                       "version": "8.0.0",
+                       "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz",
+                       "integrity": "sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg==",
+                       "dev": true
</ins><span class="cx" style="display: block; padding: 0 10px">                 },
</span><span class="cx" style="display: block; padding: 0 10px">                "dotenv-expand": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "5.1.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16143,42 +15621,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        "dev": true,
</span><span class="cx" style="display: block; padding: 0 10px">                        "optional": true
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "noms": {
-                       "version": "0.0.0",
-                       "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz",
-                       "integrity": "sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=",
-                       "dev": true,
-                       "requires": {
-                               "inherits": "^2.0.1",
-                               "readable-stream": "~1.0.31"
-                       },
-                       "dependencies": {
-                               "isarray": {
-                                       "version": "0.0.1",
-                                       "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-                                       "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-                                       "dev": true
-                               },
-                               "readable-stream": {
-                                       "version": "1.0.34",
-                                       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
-                                       "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
-                                       "dev": true,
-                                       "requires": {
-                                               "core-util-is": "~1.0.0",
-                                               "inherits": "~2.0.1",
-                                               "isarray": "0.0.1",
-                                               "string_decoder": "~0.10.x"
-                                       }
-                               },
-                               "string_decoder": {
-                                       "version": "0.10.31",
-                                       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-                                       "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
-                                       "dev": true
-                               }
-                       }
-               },
</del><span class="cx" style="display: block; padding: 0 10px">                 "nopt": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "version": "3.0.6",
</span><span class="cx" style="display: block; padding: 0 10px">                        "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
</span></span></pre></div>
<a id="trunkpackagejson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/package.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/package.json        2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/package.json  2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22,12 +22,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                "babel-jest": "24.8.0",
</span><span class="cx" style="display: block; padding: 0 10px">                "check-node-version": "3.2.0",
</span><span class="cx" style="display: block; padding: 0 10px">                "copy-webpack-plugin": "^4.6.0",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "copyfiles": "2.1.1",
</del><span class="cx" style="display: block; padding: 0 10px">                 "core-js": "3.1.4",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "cross-env": "5.2.0",
-               "cross-var": "1.1.0",
</del><span class="cx" style="display: block; padding: 0 10px">                 "cssnano": "4.1.8",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "dotenv-cli": "2.0.1",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         "dotenv": "8.0.0",
+               "dotenv-expand": "5.1.0",
</ins><span class="cx" style="display: block; padding: 0 10px">                 "grunt": "~1.0.3",
</span><span class="cx" style="display: block; padding: 0 10px">                "grunt-banner": "^0.6.0",
</span><span class="cx" style="display: block; padding: 0 10px">                "grunt-contrib-clean": "~2.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -129,29 +127,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                "test": "grunt test",
</span><span class="cx" style="display: block; padding: 0 10px">                "watch": "grunt watch",
</span><span class="cx" style="display: block; padding: 0 10px">                "grunt": "grunt",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "env:start": "dotenv npm run env:__start-next",
-               "env:__start-next": "docker-compose -f ./tools/local-env/docker-compose.yml up -d",
-               "env:stop": "dotenv npm run env:__stop-next",
-               "env:clean": "dotenv npm run env:__stop-next -- -- -v --remove-orphans",
-               "env:reset": "dotenv npm run env:__stop-next -- -- --rmi all -v --remove-orphans",
-               "env:__stop-next": "docker-compose -f ./tools/local-env/docker-compose.yml -f ./tools/local-env/docker-compose.scripts.yml down",
-               "env:install": "dotenv npm run env:__install-next",
-               "env:__install-next": "npm run env:__install-config && npm run env:__install-config-define-wp_debug && npm run env:__install-config-define-wp_debug_log && npm run env:__install-config-define-wp_debug_display && npm run env:__install-config-define-script_debug && copyfiles -f src/wp-config.php . && npm run env:__reset-site && npm run env:__install-site",
-               "env:__install-config": "cross-var npm run env:__cli-next config create -- --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --path=/var/www/src --force",
-               "env:__install-config-define-wp_debug": "cross-var npm run env:__cli-next config set WP_DEBUG $LOCAL_WP_DEBUG -- --raw",
-               "env:__install-config-define-wp_debug_log": "cross-var npm run env:__cli-next config set WP_DEBUG_LOG $LOCAL_WP_DEBUG_LOG -- --raw",
-               "env:__install-config-define-wp_debug_display": "cross-var npm run env:__cli-next config set WP_DEBUG_DISPLAY $LOCAL_WP_DEBUG_DISPLAY -- --raw",
-               "env:__install-config-define-script_debug": "cross-var npm run env:__cli-next config set SCRIPT_DEBUG $LOCAL_SCRIPT_DEBUG -- --raw",
-               "env:__install-site": "cross-var wait-on tcp:localhost:$LOCAL_PORT && cross-var npm run env:__cli-next core install -- --title=WPDEV --admin_user=admin --admin_password=password --admin_email=test@test.com --skip-email --url=http://localhost:$LOCAL_PORT --quiet",
-               "env:__reset-site": "cross-var wait-on tcp:localhost:$LOCAL_PORT && npm run env:__cli-next db reset -- --yes --quiet",
-               "env:cli": "dotenv npm run env:__cli-next",
-               "env:__cli-next": "docker-compose -f ./tools/local-env/docker-compose.yml -f ./tools/local-env/docker-compose.scripts.yml run --rm cli",
-               "env:logs": "docker-compose -f ./tools/local-env/docker-compose.yml -f ./tools/local-env/docker-compose.scripts.yml logs",
-               "env:pull": "dotenv npm run env:__pull-next",
-               "env:__pull-next": "docker-compose -f ./tools/local-env/docker-compose.yml -f ./tools/local-env/docker-compose.scripts.yml pull",
-               "test:e2e": "dotenv npm run test:__e2e-next",
-               "test:__e2e-next": "cross-var cross-env WP_BASE_URL=http://localhost:$LOCAL_PORT wp-scripts test-e2e --config tests/e2e/jest.config.js",
-               "test:php": "dotenv npm run test:__php-next",
-               "test:__php-next": "docker-compose -f ./tools/local-env/docker-compose.yml -f ./tools/local-env/docker-compose.scripts.yml run --rm phpunit phpunit"
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         "env:start": "node ./tools/local-env/scripts/start.js",
+               "env:stop": "node ./tools/local-env/scripts/docker.js down",
+               "env:clean": "node ./tools/local-env/scripts/docker.js down -v --remove-orphans",
+               "env:reset": "node ./tools/local-env/scripts/docker.js down --rmi all -v --remove-orphans",
+               "env:install": "node ./tools/local-env/scripts/install.js",
+               "env:cli": "node ./tools/local-env/scripts/docker.js run cli",
+               "env:logs": "node ./tools/local-env/scripts/docker.js logs",
+               "env:pull": "node ./tools/local-env/scripts/docker.js pull",
+               "test:php": "node ./tools/local-env/scripts/docker.js run --rm phpunit phpunit",
+               "test:e2e": "node ./tests/e2e/run-tests.js"
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestse2eruntestsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/e2e/run-tests.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/e2e/run-tests.js                              (rev 0)
+++ trunk/tests/e2e/run-tests.js        2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,9 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const dotenv = require( 'dotenv' );
+const dotenv_expand = require( 'dotenv-expand' );
+const { execSync } = require( 'child_process' );
+
+// WP_BASE_URL interpolates LOCAL_PORT, so needs to be parsed by dotenv_expand().
+dotenv_expand( dotenv.config() );
+
+// Run the tests, passing additional arguments through to the test script.
+execSync( 'wp-scripts test-e2e --config tests/e2e/jest.config.js ' + process.argv.slice( 2 ).join( ' ' ), { stdio: 'inherit' } );
</ins></span></pre></div>
<a id="trunktoolslocalenvdefaulttemplate"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tools/local-env/default.template</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tools/local-env/default.template    2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/tools/local-env/default.template      2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,6 +13,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        root /var/www/${LOCAL_DIR};
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        absolute_redirect off;
+
</ins><span class="cx" style="display: block; padding: 0 10px">         location / {
</span><span class="cx" style="display: block; padding: 0 10px">                try_files $uri $uri/ /index.php?$args;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span></span></pre></div>
<a id="trunktoolslocalenvdockercomposescriptsyml"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: trunk/tools/local-env/docker-compose.scripts.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tools/local-env/docker-compose.scripts.yml  2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/tools/local-env/docker-compose.scripts.yml    2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,50 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-version: '3.7'
-
-services:
-
-  ##
-  # The WP CLI container.
-  ##
-  cli:
-    image: wordpressdevelop/cli:${LOCAL_PHP-latest}
-
-    networks:
-      - wpdevnet
-
-    environment:
-      LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false}
-      LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
-
-    volumes:
-      - ../../:/var/www
-
-    # The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly.
-    init: true
-
-  ##
-  # The PHPUnit container.
-  ##
-  phpunit:
-    image: wordpressdevelop/phpunit:${LOCAL_PHP-latest}
-
-    networks:
-      - wpdevnet
-
-    environment:
-      LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false}
-      LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
-
-    volumes:
-      - ./phpunit-config.ini:/usr/local/etc/php/conf.d/phpunit-config.ini
-      - ../../:/wordpress-develop
-      - phpunit-uploads:/wordpress-develop/${LOCAL_DIR-src}/wp-content/uploads
-
-    # The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly.
-    init: true
-
-    depends_on:
-      - mysql
-
-volumes:
-  # Using a volume for the uploads directory improves PHPUnit performance.
-  phpunit-uploads: {}
</del></span></pre></div>
<a id="trunktoolslocalenvdockercomposeyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tools/local-env/docker-compose.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tools/local-env/docker-compose.yml  2019-08-12 01:53:17 UTC (rev 45782)
+++ trunk/tools/local-env/docker-compose.yml    2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -18,8 +18,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">       LOCAL_DIR: ${LOCAL_DIR-src}
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     volumes:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      - ./default.template:/etc/nginx/conf.d/default.template
-      - ../../:/var/www
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      - ./tools/local-env/default.template:/etc/nginx/conf.d/default.template
+      - ./:/var/www
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     # Load our config file, substituning environment variables into the config.
</span><span class="cx" style="display: block; padding: 0 10px">     command: /bin/sh -c "envsubst '$$LOCAL_DIR' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41,8 +41,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">       LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     volumes:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      - ./php-config.ini:/usr/local/etc/php/conf.d/php-config.ini
-      - ../../:/var/www
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      - ./tools/local-env/php-config.ini:/usr/local/etc/php/conf.d/php-config.ini
+      - ./:/var/www
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     depends_on:
</span><span class="cx" style="display: block; padding: 0 10px">       - mysql
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -60,15 +60,60 @@
</span><span class="cx" style="display: block; padding: 0 10px">       MYSQL_ROOT_PASSWORD: password
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     volumes:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      - ./mysql-init.sql:/docker-entrypoint-initdb.d/mysql-init.sql
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+      - ./tools/local-env/mysql-init.sql:/docker-entrypoint-initdb.d/mysql-init.sql
</ins><span class="cx" style="display: block; padding: 0 10px">       - mysql:/var/lib/mysql
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">     # For compatibility with PHP versions that don't support the caching_sha2_password auth plugin used in MySQL 8.0.
</span><span class="cx" style="display: block; padding: 0 10px">     command: --default-authentication-plugin=mysql_native_password
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  ##
+  # The WP CLI container.
+  ##
+  cli:
+    image: wordpressdevelop/cli:${LOCAL_PHP-latest}
+
+    networks:
+      - wpdevnet
+
+    environment:
+      LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false}
+      LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
+
+    volumes:
+      - ./:/var/www
+
+    # The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly.
+    init: true
+
+  ##
+  # The PHPUnit container.
+  ##
+  phpunit:
+    image: wordpressdevelop/phpunit:${LOCAL_PHP-latest}
+
+    networks:
+      - wpdevnet
+
+    environment:
+      LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false}
+      LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
+
+    volumes:
+      - ./tools/local-env/phpunit-config.ini:/usr/local/etc/php/conf.d/phpunit-config.ini
+      - ./:/wordpress-develop
+      - phpunit-uploads:/wordpress-develop/${LOCAL_DIR-src}/wp-content/uploads
+
+    # The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly.
+    init: true
+
+    depends_on:
+      - mysql
+
</ins><span class="cx" style="display: block; padding: 0 10px"> volumes:
</span><span class="cx" style="display: block; padding: 0 10px">   # So that sites aren't wiped every time containers are restarted, MySQL uses a persistent volume.
</span><span class="cx" style="display: block; padding: 0 10px">   mysql: {}
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  # Using a volume for the uploads directory improves PHPUnit performance.
+  phpunit-uploads: {}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> networks:
</span><span class="cx" style="display: block; padding: 0 10px">   # Creating our own network allows us to connect between containers using their service name.
</span></span></pre></div>
<a id="trunktoolslocalenvscriptsdockerjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tools/local-env/scripts/docker.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tools/local-env/scripts/docker.js                           (rev 0)
+++ trunk/tools/local-env/scripts/docker.js     2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,6 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const dotenv = require( 'dotenv' );
+const { execSync } = require( 'child_process' );
+dotenv.config();
+
+// Execute any docker-compose command passed to this script.
+execSync( 'docker-compose ' + process.argv.slice( 2 ).join( ' ' ), { stdio: 'inherit' } );
</ins></span></pre></div>
<a id="trunktoolslocalenvscriptsinstalljs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tools/local-env/scripts/install.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tools/local-env/scripts/install.js                          (rev 0)
+++ trunk/tools/local-env/scripts/install.js    2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,45 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const dotenv = require( 'dotenv' );
+const wait_on = require( 'wait-on' );
+const { execSync } = require( 'child_process' );
+const { renameSync, readFileSync, writeFileSync } = require( 'fs' );
+
+dotenv.config();
+
+// Create wp-config.php.
+wp_cli( 'config create --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --path=/var/www/src --force' );
+
+// Add the debug settings to wp-config.php.
+// Windows requires this to be done as an additional step, rather than using the --extra-php option in the previous step.
+wp_cli( `config set WP_DEBUG ${process.env.LOCAL_WP_DEBUG} --raw` );
+wp_cli( `config set WP_DEBUG_LOG ${process.env.LOCAL_WP_DEBUG_LOG} --raw` );
+wp_cli( `config set WP_DEBUG_DISPLAY ${process.env.LOCAL_WP_DEBUG_DISPLAY} --raw` );
+wp_cli( `config set SCRIPT_DEBUG ${process.env.LOCAL_SCRIPT_DEBUG} --raw` );
+
+// Move wp-config.php to the base directory, so it doesn't get mixed up in the src or build directories.
+renameSync( 'src/wp-config.php', 'wp-config.php' );
+
+// Read in wp-tests-config-sample.php, edit it to work with our config, then write it to wp-tests-config.php.
+const testConfig = readFileSync( 'wp-tests-config-sample.php', 'utf8' )
+       .replace( 'youremptytestdbnamehere', 'wordpress_develop_tests' )
+       .replace( 'yourusernamehere', 'root' )
+       .replace( 'yourpasswordhere', 'password' )
+       .replace( 'localhost', 'mysql' )
+       .concat( "\ndefine( 'FS_METHOD', 'direct' );\n" );
+
+writeFileSync( 'wp-tests-config.php', testConfig );
+
+// Once the site is available, install WordPress!
+wait_on( { resources: [ `tcp:localhost:${process.env.LOCAL_PORT}`] } )
+       .then( () => {
+               wp_cli( 'db reset --yes' );
+               wp_cli( `core install --title="WordPress Develop" --admin_user=admin --admin_password=password --admin_email=test@test.com --skip-email --url=http://localhost:${process.env.LOCAL_PORT}` );
+       } );
+
+/**
+ * Runs WP-CLI commands in the Docker environment.
+ *
+ * @param {string} cmd The WP-CLI command to run.
+ */
+function wp_cli( cmd ) {
+       execSync( `docker-compose run --rm cli ${cmd}`, { stdio: 'inherit' } );
+}
</ins></span></pre></div>
<a id="trunktoolslocalenvscriptsstartjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tools/local-env/scripts/start.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tools/local-env/scripts/start.js                            (rev 0)
+++ trunk/tools/local-env/scripts/start.js      2019-08-12 08:28:33 UTC (rev 45783)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,14 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const dotenv = require( 'dotenv' );
+const { execSync } = require( 'child_process' );
+
+dotenv.config();
+
+// Start the local-env containers.
+execSync( 'docker-compose up -d wordpress-develop', { stdio: 'inherit' } );
+
+// If Docker Toolbox is being used, we need to manually forward LOCAL_PORT to the Docker VM.
+if ( process.env.DOCKER_TOOLBOX_INSTALL_PATH ) {
+       // VBoxManage is added to the PATH on every platform except Windows.
+       const vboxmanage = process.env.VBOX_MSI_INSTALL_PATH ? `${process.env.VBOX_MSI_INSTALL_PATH}/VBoxManage` : 'VBoxManage'
+       execSync( `"${vboxmanage}" controlvm "${process.env.DOCKER_MACHINE_NAME}" natpf1 "tcp-port${process.env.LOCAL_PORT},tcp,127.0.0.1,${process.env.LOCAL_PORT},,${process.env.LOCAL_PORT}"`, { stdio: 'inherit' } );
+}
</ins></span></pre>
</div>
</div>

</body>
</html>