<!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>[49530] branches/4.9: Build/Test Tools: Backport the local Docker environment to the 4.9 branch.</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/49530">49530</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/49530","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>desrosj</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2020-11-06 17:32:00 +0000 (Fri, 06 Nov 2020)</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/Test Tools: Backport the local Docker environment to the 4.9 branch.

This commit introduces the Docker-based local WordPress development environment to the 4.9 branch and converts the Travis test jobs to utilize this environment for easier and more consistent testing.

Until existing blockers with the PHP 5.2 Docker container can be solved, the PHP 5.2 test job will remain using the Travis `precise` image.

Merges [45745,45762,45783-45784,45800,45819,45885,46320,46999,47225,47912,48121,49335,49358,49360,49362] to the 4.9 branch.
See <a href="https://core.trac.wordpress.org/ticket/48301">#48301</a>, <a href="https://core.trac.wordpress.org/ticket/47767">#47767</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branches49travisyml">branches/4.9/.travis.yml</a></li>
<li><a href="#branches49npmshrinkwrapjson">branches/4.9/npm-shrinkwrap.json</a></li>
<li><a href="#branches49packagejson">branches/4.9/package.json</a></li>
<li><a href="#branches49testsphpunitincludesobjectcachephp">branches/4.9/tests/phpunit/includes/object-cache.php</a></li>
<li><a href="#branches49testsphpunittestsajaxCustomizeMenusphp">branches/4.9/tests/phpunit/tests/ajax/CustomizeMenus.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branches49env">branches/4.9/.env</a></li>
<li><a href="#branches49dockercomposeyml">branches/4.9/docker-compose.yml</a></li>
<li>branches/4.9/tools/local-env/</li>
<li><a href="#branches49toolslocalenvdefaulttemplate">branches/4.9/tools/local-env/default.template</a></li>
<li><a href="#branches49toolslocalenvmysqlinitsql">branches/4.9/tools/local-env/mysql-init.sql</a></li>
<li><a href="#branches49toolslocalenvphpconfigini">branches/4.9/tools/local-env/php-config.ini</a></li>
<li><a href="#branches49toolslocalenvphpunitconfigini">branches/4.9/tools/local-env/phpunit-config.ini</a></li>
<li>branches/4.9/tools/local-env/scripts/</li>
<li><a href="#branches49toolslocalenvscriptsdockerjs">branches/4.9/tools/local-env/scripts/docker.js</a></li>
<li><a href="#branches49toolslocalenvscriptsinstalljs">branches/4.9/tools/local-env/scripts/install.js</a></li>
<li><a href="#branches49toolslocalenvscriptsstartjs">branches/4.9/tools/local-env/scripts/start.js</a></li>
</ul>

<h3>Property Changed</h3>
<ul>
<li><a href="#branches49">branches/4.9/</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<span class="cx" style="display: block; padding: 0 10px">Index: branches/4.9
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- branches/4.9 2020-11-06 17:29:16 UTC (rev 49529)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ branches/4.9  2020-11-06 17:32:00 UTC (rev 49530)
</ins><a id="branches49"></a>
<div class="propset"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Property changes: branches/4.9</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: svn:mergeinfo</h4></div>
<span class="cx" style="display: block; padding: 0 10px"> /branches/4.8:42204
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/5.0:43807,43988,43994,44014,44017,44047,45005,49523
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/5.5:49373-49379,49381
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/trunk:18512,42132,42134,42136,42138,42140,42144,42146,42148,42150,42152-42153,42155,42157,42159,42161,42163,42169,42171,42173,42175,42177,42181,42183,42185,42187,42189,42191,42193,42199,42203,42210,42214,42220,42222,42226,42242,42244,42247,42251,42256-42261,42350,42358,42362,42364-42368,42374,42388,42390,42401,42417,42421,42423-42425,42430,42432-42433,42437,42441,42443,42446-42447,42449,42451,42453,42457,42459,42462,42491,42521,42529,42531,42533,42536,42538,42541,42543,42545,42549,42566,42568,42570,42572,42574,42576,42579,42581-42582,42584-42585,42587-42588,42590,42592,42594-42595,42598-42599,42602,42604,42606,42611-42613,42615,42617,42624-42625,42639,42648,42652-42653,42665,42676,42687,42695,42697,42702,42711,42713,42719,42722,42726,42728,42739-42740,42744,42758,42772,42791-42792,42801,42814-42815,42817-42818,42823,42830,42837,42839,42841,42844,42851-42852,42860,42864,42881,42888-42889
 ,42892-42894,42930,42964,42967,42971-42972,42977-42978,42980-42982,42985-42987,42989,42992,42994-42995,42998-42999,43001-43004,43007-43008,43011-43012,43014-43015,43025,43027,43030,43032,43034,43036,43039,43042,43044-43049,43051-43063,43065,43081,43085,43087-43089,43091,43104,43116,43118,43120-43121,43123,43125-43126,43131-43132,43135,43137,43139,43145-43148,43150,43154-43155,43158,43160,43162,43166,43168,43170,43172,43175,43180-43181,43183-43185,43189,43191,43193,43195,43197,43199,43201,43203,43206,43208,43210-43212,43216,43218,43220,43222-43223,43226,43228,43230,43232,43234,43236,43238,43242-43243,43245-43246,43248-43251,43256,43259-43260,43263,43265,43267,43269,43274-43275,43278-43279,43282,43284,43286,43290-43293,43299,43303-43304,43313,43315,43317,43331,43337,43343,43350,43353,43356,43361-43363,43365,43367,43370-43371,43373-43376,43379,43388,43390,43435,43437,43439-43440,43446-43447,43451,43454,43457,43460,43462-43467,43469,43471,43475,43477-43478,43480,43486,43491,43493,43495,
 43499,43504,43506,43508,43511-43513,43518,43525,43527,43529,43531,43541,43550,43559,43567,43580,43593,43597,43599,43609,43636,43638,43653,44021,44048,44833,44842,44993,45067,45936,45971,45990,45997,46893,46895,47341,47633-47635,47637-47638,47949-47951,48241,48338,48341,49380,49382-49388
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/trunk:18512,42132,42134,42136,42138,42140,42144,42146,42148,42150,42152-42153,42155,42157,42159,42161,42163,42169,42171,42173,42175,42177,42181,42183,42185,42187,42189,42191,42193,42199,42203,42210,42214,42220,42222,42226,42242,42244,42247,42251,42256-42261,42350,42358,42362,42364-42368,42374,42388,42390,42401,42417,42421,42423-42425,42430,42432-42433,42437,42441,42443,42446-42447,42449,42451,42453,42457,42459,42462,42491,42521,42529,42531,42533,42536,42538,42541,42543,42545,42549,42566,42568,42570,42572,42574,42576,42579,42581-42582,42584-42585,42587-42588,42590,42592,42594-42595,42598-42599,42602,42604,42606,42611-42613,42615,42617,42624-42625,42639,42648,42652-42653,42665,42676,42687,42695,42697,42702,42711,42713,42719,42722,42726,42728,42739-42740,42744,42758,42772,42791-42792,42801,42814-42815,42817-42818,42823,42830,42837,42839,42841,42844,42851-42852,42860,42864,42881,42888-42889
 ,42892-42894,42930,42964,42967,42971-42972,42977-42978,42980-42982,42985-42987,42989,42992,42994-42995,42998-42999,43001-43004,43007-43008,43011-43012,43014-43015,43025,43027,43030,43032,43034,43036,43039,43042,43044-43049,43051-43063,43065,43081,43085,43087-43089,43091,43104,43116,43118,43120-43121,43123,43125-43126,43131-43132,43135,43137,43139,43145-43148,43150,43154-43155,43158,43160,43162,43166,43168,43170,43172,43175,43180-43181,43183-43185,43189,43191,43193,43195,43197,43199,43201,43203,43206,43208,43210-43212,43216,43218,43220,43222-43223,43226,43228,43230,43232,43234,43236,43238,43242-43243,43245-43246,43248-43251,43256,43259-43260,43263,43265,43267,43269,43274-43275,43278-43279,43282,43284,43286,43290-43293,43299,43303-43304,43313,43315,43317,43331,43337,43343,43350,43353,43356,43361-43363,43365,43367,43370-43371,43373-43376,43379,43388,43390,43435,43437,43439-43440,43446-43447,43451,43454,43457,43460,43462-43467,43469,43471,43475,43477-43478,43480,43486,43491,43493,43495,
 43499,43504,43506,43508,43511-43513,43518,43525,43527,43529,43531,43541,43550,43559,43567,43580,43593,43597,43599,43609,43636,43638,43653,44021,44048,44833,44842,44993,45067,45745,45762,45783-45784,45800,45819,45885,45936,45971,45990,45997,46320,46893,46895,46999,47225,47341,47633-47635,47637-47638,47912,47949-47951,48121,48241,48338,48341,49335,49358,49360,49362,49380,49382-49388
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="branches49env"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/.env</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/.env                         (rev 0)
+++ branches/4.9/.env   2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,59 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+##
+# Default configuration options for the local dev environment.
+#
+# All of these options can be overridden by setting them as environment variables before starting
+# the environment. You will need to restart your environment when changing any of these.
+#
+# Below, the following substitutions can be made:
+# - '{version}': any major.minor PHP version from 5.2 onwards.
+# - '{phpunit_version}': any major PHPUnit version starting with 4.
+##
+
+# The site will be available at http://localhost:LOCAL_PORT
+LOCAL_PORT=8889
+
+# Where to run WordPress from. Valid options are 'src' and 'build'.
+LOCAL_DIR=src
+
+# The PHP version to use. Valid options are 'latest', and '{version}-fpm'.
+LOCAL_PHP=7.2-fpm
+
+##
+# The PHPUnit version to use when running tests.
+#
+# Support for new PHPUnit versions is not backported to past versions, so some old WordPress branches require an older
+# version to run tests.
+#
+# Valid versions are:
+# - 'latest' for the highest version of PHPUnit supported on the highest version of PHP supported.
+# - '{version}-fpm' for the highest version of PHPUnit supported on the specified version of PHP.
+# - '{phpunit_version}-php-{version}-fpm' for a specific version of PHPUnit on the specified version of PHP. This format
+# is only available for PHP versions 5.6 and higher.
+#
+# For the full list of available options, see https://hub.docker.com/r/wordpressdevelop/phpunit/tags.
+#
+# For full documentation on PHPUnit compatibility and WordPress versions, see
+# https://make.wordpress.org/core/handbook/references/phpunit-compatibility-and-wordpress-versions/.
+#
+# This defaults to the value assigned to the value of LOCAL_PHP.
+##
+LOCAL_PHPUNIT=6-php-${LOCAL_PHP}
+
+# Whether or not to enable XDebug.
+LOCAL_PHP_XDEBUG=false
+
+# Whether or not to enable Memcached.
+LOCAL_PHP_MEMCACHED=false
+
+# The MySQL version to use. See https://hub.docker.com/_/mysql/ for valid versions.
+LOCAL_MYSQL=5.7
+
+# The debug settings to add to `wp-config.php`.
+LOCAL_WP_DEBUG=true
+LOCAL_WP_DEBUG_LOG=true
+LOCAL_WP_DEBUG_DISPLAY=true
+LOCAL_SCRIPT_DEBUG=true
+LOCAL_WP_ENVIRONMENT_TYPE=local
+
+# The URL to use when running e2e tests.
+WP_BASE_URL=http://localhost:${LOCAL_PORT}
</ins></span></pre></div>
<a id="branches49travisyml"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.9/.travis.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/.travis.yml  2020-11-06 17:29:16 UTC (rev 49529)
+++ branches/4.9/.travis.yml    2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,96 +1,130 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-sudo: false
-dist: trusty
</del><span class="cx" style="display: block; padding: 0 10px"> language: php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+services:
+  - docker
+
</ins><span class="cx" style="display: block; padding: 0 10px"> cache:
</span><span class="cx" style="display: block; padding: 0 10px">   apt: true
</span><span class="cx" style="display: block; padding: 0 10px">   directories:
</span><span class="cx" style="display: block; padding: 0 10px">     - $HOME/.npm
</span><span class="cx" style="display: block; padding: 0 10px">     - vendor
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    - $HOME/.composer/cache
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> env:
</span><span class="cx" style="display: block; padding: 0 10px">   global:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    - WP_TRAVISCI=travis:phpunit
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    - LOCAL_DIR: build
+    - NPM_INSTALL: true
+    - WP_INSTALL: true
+    - PHP_FPM_UID: "`id -u`"
+    - PHP_FPM_GID: "`id -g`"
+
</ins><span class="cx" style="display: block; padding: 0 10px"> matrix:
</span><span class="cx" style="display: block; padding: 0 10px">   include:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  - php: 7.1
-    env: WP_TRAVISCI=travis:js
-  - php: 7.2
-  - php: 5.6
-    env: WP_TRAVIS_OBJECT_CACHE=true
-    services: memcached
-  - php: 5.2
-    dist: precise
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    - env: WP_TRAVISCI=travis:js LOCAL_PHP=7.1-fpm WP_INSTALL=false
+      name: "JS Tests"
+    - env: LOCAL_PHPUNIT=6-php-7.2-fpm WP_TRAVISCI=test:php
+      name: "PHPUnit Tests: PHP 7.2"
+    - env: LOCAL_PHP_MEMCACHED=true LOCAL_PHP=5.6-fpm LOCAL_PHPUNIT=4-php-5.6-fpm WP_TRAVISCI=test:php
+      name: "PHPUnit Tests: PHP 5.6 with Memcached"
+    - env: WP_TRAVISCI=travis:phpunit WP_INSTALL=false
+      php: 5.2
+      dist: precise
+      name: "PHPUnit Tests: PHP 5.2"
+  fast_finish: true
+
</ins><span class="cx" style="display: block; padding: 0 10px"> before_install:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-- |
-  if [[ "$WP_TRAVISCI" == "travis:phpunit" ]]; then
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  - |
+    if [[ "$WP_TRAVISCI" == "test:php" ]]; then
+      travis_retry svn checkout https://plugins.svn.wordpress.org/wordpress-importer/tags/0.6.3/ tests/phpunit/data/plugins/wordpress-importer
+    fi
+  - |
+    if [[ "$WP_TRAVISCI" != "travis:phpunit" ]]; then
+      curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
+      sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
+      sudo apt-get update
+      sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
+    fi
+  - |
+    sudo rm /usr/local/bin/docker-compose
+    curl -L https://github.com/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > docker-compose
+    chmod +x docker-compose
+    sudo mv docker-compose /usr/local/bin
+  - |
+    if [[ "$WP_TRAVISCI" == "travis:phpunit" ]]; then
</ins><span class="cx" style="display: block; padding: 0 10px">       mysql -u root -e "CREATE DATABASE wordpress_tests;"
</span><span class="cx" style="display: block; padding: 0 10px">       cp wp-tests-config-sample.php wp-tests-config.php
</span><span class="cx" style="display: block; padding: 0 10px">       sed -i "s/youremptytestdbnamehere/wordpress_tests/" wp-tests-config.php
</span><span class="cx" style="display: block; padding: 0 10px">       sed -i "s/yourusernamehere/root/" wp-tests-config.php
</span><span class="cx" style="display: block; padding: 0 10px">       sed -i "s/yourpasswordhere//" wp-tests-config.php
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-      svn checkout https://plugins.svn.wordpress.org/wordpress-importer/tags/0.6.3/ tests/phpunit/data/plugins/wordpress-importer
-  fi
-- |
-  if [[ "$WP_TRAVIS_OBJECT_CACHE" == "true" ]]; then
-    cp tests/phpunit/includes/object-cache.php src/wp-content/object-cache.php
-    echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
-  fi
</del><ins style="background-color: #dfd; text-decoration:none; 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
+    fi
+
</ins><span class="cx" style="display: block; padding: 0 10px"> before_script:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-- |
-  # Remove Xdebug for a huge performance increase:
-  if [ -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ]; then
-    phpenv config-rm xdebug.ini
-  else
-    echo "xdebug.ini does not exist"
-  fi
-- |
-  # Export Composer's global bin dir to PATH, but not on PHP 5.2:
-  if [[ ${TRAVIS_PHP_VERSION:0:3} != "5.2" ]]; then
-    composer config --list --global
-    export PATH=`composer config --list --global | grep '\[home\]' | { read a; echo "${a#* }/vendor/bin:$PATH"; }`
-  fi
-- |
-  # Install the specified version of PHPUnit depending on the PHP version:
-  if [[ "$WP_TRAVISCI" == "travis:phpunit" ]]; then
-    case "$TRAVIS_PHP_VERSION" in
-      7.2|7.1|7.0|nightly)
-        echo "Using PHPUnit 6.x"
-        composer global require "phpunit/phpunit:^6"
-        ;;
-      5.6|5.5|5.4|5.3)
-        echo "Using PHPUnit 4.x"
-        composer global require "phpunit/phpunit:^4"
-        ;;
-      5.2)
-        # Do nothing, use default PHPUnit 3.6.x
-        echo "Using default PHPUnit, hopefully 3.6"
-        ;;
-      *)
-        echo "No PHPUnit version handling for PHP version $TRAVIS_PHP_VERSION"
-        exit 1
-        ;;
-    esac
-  fi
-- npm --version
-- node --version
-- nvm install 6.9.1
-- npm install -g grunt-cli
-- npm install
-- npm prune
-- mysql --version
-- phpenv versions
-- php --version
-- php -m
-- npm --version
-- node --version
-- which phpunit
-- phpunit --version
-- curl --version
-- grunt --version
-- git --version
-- svn --version
-- locale -a
-script: grunt $WP_TRAVISCI
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  - npm --version
+  - node --version
+  - nvm install
+  - |
+    if [[ "$WP_TRAVISCI" == "travis:phpunit" ]]; then
+      phpenv config-rm xdebug.ini
+      mysql --version
+      phpenv versions
+      php --version
+      php -m
+    fi
+  - |
+    if [[ "$NPM_INSTALL" == "true" ]]; then
+      npm install
+    fi
+  - |
+    if [[ "$WP_TRAVISCI" == "test:php" ]]; then
+      npm run env:start
+      npm run build
+      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
+    fi
+  - |
+    if [[ "$LOCAL_PHP_MEMCACHED" == "true" ]]; then
+      cp tests/phpunit/includes/object-cache.php build/wp-content/object-cache.php
+      # The memcached server needs to start after `npm run env:start`, which sets up the Docker network.
+      docker run --name memcached --net $(basename "$PWD")_wpdevnet -d memcached
+    fi
+  - |
+    if [[ "$WP_INSTALL" == "true" ]]; then
+      # Run the install process after memcached has started.
+      npm run env:install
+    fi
+  - npm --version
+  - node --version
+  - curl --version
+  - git --version
+  - svn --version
+  - php --version
+  - php -i
+  - locale -a
+
+script:
+  - |
+    if [[ "$WP_TRAVISCI" == "test:php" ]]; then
+      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 &&
+      # __fakegroup__ is excluded to force PHPUnit to ignore the <exclude> settings in phpunit.xml.dist.
+      LOCAL_PHP_XDEBUG=true npm run test:php -- -v --group xdebug --exclude-group __fakegroup__
+    else
+      npm run grunt $WP_TRAVISCI
+    fi
+
+after_script:
+  - |
+    if [[ "$WP_TEST_REPORTER" == "true" ]]; then
+      git clone https://github.com/WordPress/phpunit-test-runner.git test-runner
+      docker-compose run --rm -e WPT_PREPARE_DIR=/var/www -e WPT_TEST_DIR=/var/www php php test-runner/report.php
+    fi
+
</ins><span class="cx" style="display: block; padding: 0 10px"> notifications:
</span><span class="cx" style="display: block; padding: 0 10px">   slack:
</span><span class="cx" style="display: block; padding: 0 10px">     rooms:
</span></span></pre></div>
<a id="branches49dockercomposeyml"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/docker-compose.yml</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/docker-compose.yml                           (rev 0)
+++ branches/4.9/docker-compose.yml     2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,136 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+version: '3.7'
+
+services:
+
+  ##
+  # The web server container.
+  ##
+  wordpress-develop:
+    image: nginx:alpine
+
+    networks:
+      - wpdevnet
+
+    ports:
+      - ${LOCAL_PORT-8889}:80
+
+    environment:
+      LOCAL_DIR: ${LOCAL_DIR-src}
+
+    volumes:
+      - ./tools/local-env/default.template:/etc/nginx/conf.d/default.template
+      - ./:/var/www
+
+    # Load our config file, substituting environment variables into the config.
+    command: /bin/sh -c "envsubst '$$LOCAL_DIR' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
+
+    depends_on:
+      - php
+
+  ##
+  # The PHP container.
+  ##
+  php:
+    image: wordpressdevelop/php:${LOCAL_PHP-7.2-fpm}
+
+    networks:
+      - wpdevnet
+
+    environment:
+      LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false}
+      LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
+      PHP_FPM_UID: ${PHP_FPM_UID-1000}
+      PHP_FPM_GID: ${PHP_FPM_GID-1000}
+
+    volumes:
+      - ./tools/local-env/php-config.ini:/usr/local/etc/php/conf.d/php-config.ini
+      - ./:/var/www
+
+    depends_on:
+      - mysql
+
+  ##
+  # The MySQL container.
+  ##
+  mysql:
+    image: mysql:${LOCAL_MYSQL-5.7}
+
+    networks:
+      - wpdevnet
+
+    ports:
+      - "3306"
+
+    environment:
+      MYSQL_ROOT_PASSWORD: password
+
+    volumes:
+      - ./tools/local-env/mysql-init.sql:/docker-entrypoint-initdb.d/mysql-init.sql
+      - mysql:/var/lib/mysql
+
+    # For compatibility with PHP versions that don't support the caching_sha2_password auth plugin used in MySQL 8.0.
+    command: --default-authentication-plugin=mysql_native_password
+
+  ##
+  # The WP CLI container.
+  ##
+  cli:
+    image: wordpressdevelop/cli:${LOCAL_PHP-7.2-fpm}
+
+    networks:
+      - wpdevnet
+
+    environment:
+      LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false}
+      LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
+      PHP_FPM_UID: ${PHP_FPM_UID-1000}
+      PHP_FPM_GID: ${PHP_FPM_GID-1000}
+
+    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_PHPUNIT-6-php-7.2-fpm}
+
+    networks:
+      - wpdevnet
+
+    environment:
+      LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false}
+      LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
+      LOCAL_DIR: ${LOCAL_DIR-src}
+      WP_MULTISITE: ${WP_MULTISITE-false}
+      PHP_FPM_UID: ${PHP_FPM_UID-1000}
+      PHP_FPM_GID: ${PHP_FPM_GID-1000}
+      TRAVIS_BRANCH: ${TRAVIS_BRANCH-false}
+      TRAVIS_PULL_REQUEST: ${TRAVIS_PULL_REQUEST-false}
+      GITHUB_REF: ${GITHUB_REF-false}
+      GITHUB_EVENT_NAME: ${GITHUB_EVENT_NAME-false}
+
+    volumes:
+      - ./tools/local-env/phpunit-config.ini:/usr/local/etc/php/conf.d/phpunit-config.ini
+      - ./:/var/www
+      - phpunit-uploads:/var/www/${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:
+  # So that sites aren't wiped every time containers are restarted, MySQL uses a persistent volume.
+  mysql: {}
+  # Using a volume for the uploads directory improves PHPUnit performance.
+  phpunit-uploads: {}
+
+networks:
+  # Creating our own network allows us to connect between containers using their service name.
+  wpdevnet:
+    driver: bridge
</ins></span></pre></div>
<a id="branches49npmshrinkwrapjson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.9/npm-shrinkwrap.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/npm-shrinkwrap.json  2020-11-06 17:29:16 UTC (rev 49529)
+++ branches/4.9/npm-shrinkwrap.json    2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,6 +1,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px">   "name": "WordPress",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  "version": "4.9.0",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  "version": "4.9.16",
</ins><span class="cx" style="display: block; padding: 0 10px">   "dependencies": {
</span><span class="cx" style="display: block; padding: 0 10px">     "abbrev": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "1.1.1",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -947,6 +947,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "core-js": {
+      "version": "2.6.11",
+      "from": "core-js@>=2.5.7 <3.0.0",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+      "dev": true
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "core-util-is": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "1.0.2",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "core-util-is@>=1.0.0 <1.1.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1338,6 +1344,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "dotenv": {
+      "version": "8.2.0",
+      "from": "dotenv@>=8.2.0 <9.0.0",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
+      "dev": true
+    },
+    "dotenv-expand": {
+      "version": "5.1.0",
+      "from": "dotenv-expand@>=5.1.0 <6.0.0",
+      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
+      "dev": true
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "download": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "4.4.3",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "download@>=4.1.2 <5.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2198,6 +2216,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/grunt-banner/-/grunt-banner-0.6.0.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "grunt-cli": {
+      "version": "0.1.13",
+      "from": "grunt-cli@0.1.13",
+      "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-0.1.13.tgz",
+      "dev": true,
+      "dependencies": {
+        "resolve": {
+          "version": "0.3.1",
+          "from": "resolve@>=0.3.1 <0.4.0",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz",
+          "dev": true
+        }
+      }
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "grunt-contrib-clean": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "1.0.0",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "grunt-contrib-clean@>=1.0.0 <1.1.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3303,6 +3335,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "isemail": {
+      "version": "3.2.0",
+      "from": "isemail@>=3.0.0 <4.0.0",
+      "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
+      "dev": true,
+      "dependencies": {
+        "punycode": {
+          "version": "2.1.1",
+          "from": "punycode@>=2.0.0 <3.0.0",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+          "dev": true
+        }
+      }
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "isexe": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "2.0.0",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "isexe@>=2.0.0 <3.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3321,6 +3367,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "joi": {
+      "version": "13.7.0",
+      "from": "joi@>=13.0.0 <14.0.0",
+      "resolved": "https://registry.npmjs.org/joi/-/joi-13.7.0.tgz",
+      "dev": true,
+      "dependencies": {
+        "hoek": {
+          "version": "5.0.4",
+          "from": "hoek@>=5.0.0 <6.0.0",
+          "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz",
+          "dev": true
+        }
+      }
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "jpegtran-bin": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "3.2.0",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "jpegtran-bin@>=3.0.0 <4.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4566,6 +4626,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "psl": {
+      "version": "1.8.0",
+      "from": "psl@>=1.1.28 <2.0.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+      "dev": true
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "public-encrypt": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "4.0.0",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "public-encrypt@>=4.0.0 <5.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4923,6 +4989,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "rx": {
+      "version": "4.1.0",
+      "from": "rx@>=4.1.0 <5.0.0",
+      "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
+      "dev": true
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "rx-lite": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "3.1.2",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "rx-lite@>=3.1.2 <4.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5581,6 +5653,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "topo": {
+      "version": "3.0.3",
+      "from": "topo@>=3.0.0 <4.0.0",
+      "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz",
+      "dev": true,
+      "dependencies": {
+        "hoek": {
+          "version": "6.1.3",
+          "from": "hoek@>=6.0.0 <7.0.0",
+          "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
+          "dev": true
+        }
+      }
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "tough-cookie": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "2.3.3",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "tough-cookie@>=2.3.3 <2.4.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5708,6 +5794,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "uri-js": {
+      "version": "4.4.0",
+      "from": "uri-js@>=4.2.2 <5.0.0",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
+      "dev": true,
+      "dependencies": {
+        "punycode": {
+          "version": "2.1.1",
+          "from": "punycode@^2.1.0",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+          "dev": true
+        }
+      }
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "uri-path": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "1.0.0",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "uri-path@>=1.0.0 <2.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5849,6 +5949,122 @@
</span><span class="cx" style="display: block; padding: 0 10px">       "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
</span><span class="cx" style="display: block; padding: 0 10px">       "dev": true
</span><span class="cx" style="display: block; padding: 0 10px">     },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "wait-on": {
+      "version": "3.2.0",
+      "from": "wait-on@>=3.2.0 <3.3.0",
+      "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-3.2.0.tgz",
+      "dev": true,
+      "dependencies": {
+        "ajv": {
+          "version": "6.12.6",
+          "from": "ajv@>=6.12.3 <7.0.0",
+          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+          "dev": true
+        },
+        "aws4": {
+          "version": "1.11.0",
+          "from": "aws4@>=1.8.0 <2.0.0",
+          "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+          "dev": true
+        },
+        "combined-stream": {
+          "version": "1.0.8",
+          "from": "combined-stream@>=1.0.6 <1.1.0",
+          "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+          "dev": true
+        },
+        "extend": {
+          "version": "3.0.2",
+          "from": "extend@>=3.0.2 <3.1.0",
+          "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+          "dev": true
+        },
+        "fast-deep-equal": {
+          "version": "3.1.3",
+          "from": "fast-deep-equal@>=3.1.1 <4.0.0",
+          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+          "dev": true
+        },
+        "form-data": {
+          "version": "2.3.3",
+          "from": "form-data@>=2.3.2 <2.4.0",
+          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+          "dev": true
+        },
+        "har-validator": {
+          "version": "5.1.5",
+          "from": "har-validator@>=5.1.3 <5.2.0",
+          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+          "dev": true
+        },
+        "json-schema-traverse": {
+          "version": "0.4.1",
+          "from": "json-schema-traverse@>=0.4.1 <0.5.0",
+          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+          "dev": true
+        },
+        "mime-db": {
+          "version": "1.44.0",
+          "from": "mime-db@1.44.0",
+          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+          "dev": true
+        },
+        "mime-types": {
+          "version": "2.1.27",
+          "from": "mime-types@>=2.1.19 <2.2.0",
+          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+          "dev": true
+        },
+        "oauth-sign": {
+          "version": "0.9.0",
+          "from": "oauth-sign@>=0.9.0 <0.10.0",
+          "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+          "dev": true
+        },
+        "punycode": {
+          "version": "2.1.1",
+          "from": "punycode@^2.1.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+          "dev": true
+        },
+        "qs": {
+          "version": "6.5.2",
+          "from": "qs@>=6.5.2 <6.6.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+          "dev": true
+        },
+        "request": {
+          "version": "2.88.2",
+          "from": "request@>=2.88.0 <3.0.0",
+          "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+          "dev": true
+        },
+        "safe-buffer": {
+          "version": "5.2.1",
+          "from": "safe-buffer@>=5.1.2 <6.0.0",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+          "dev": true
+        },
+        "tough-cookie": {
+          "version": "2.5.0",
+          "from": "tough-cookie@>=2.5.0 <2.6.0",
+          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+          "dev": true
+        },
+        "tunnel-agent": {
+          "version": "0.6.0",
+          "from": "tunnel-agent@>=0.6.0 <0.7.0",
+          "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+          "dev": true
+        },
+        "uuid": {
+          "version": "3.4.0",
+          "from": "uuid@>=3.3.2 <4.0.0",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+          "dev": true
+        }
+      }
+    },
</ins><span class="cx" style="display: block; padding: 0 10px">     "walkdir": {
</span><span class="cx" style="display: block; padding: 0 10px">       "version": "0.0.11",
</span><span class="cx" style="display: block; padding: 0 10px">       "from": "walkdir@>=0.0.11 <0.0.12",
</span></span></pre></div>
<a id="branches49packagejson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.9/package.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/package.json 2020-11-06 17:29:16 UTC (rev 49529)
+++ branches/4.9/package.json   2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,9 +13,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">   "license": "GPL-2.0+",
</span><span class="cx" style="display: block; padding: 0 10px">   "devDependencies": {
</span><span class="cx" style="display: block; padding: 0 10px">     "autoprefixer": "^6.5.1",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "dotenv": "^8.2.0",
+    "dotenv-expand": "^5.1.0",
</ins><span class="cx" style="display: block; padding: 0 10px">     "grunt": "~0.4.5",
</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": "~1.0.0",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "grunt-cli": "0.1.13",
</ins><span class="cx" style="display: block; padding: 0 10px">     "grunt-contrib-compress": "~1.3.0",
</span><span class="cx" style="display: block; padding: 0 10px">     "grunt-contrib-concat": "~1.0.0",
</span><span class="cx" style="display: block; padding: 0 10px">     "grunt-contrib-copy": "~1.0.0",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -34,10 +37,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">     "grunt-replace": "~1.0.1",
</span><span class="cx" style="display: block; padding: 0 10px">     "grunt-rtlcss": "~2.0.1",
</span><span class="cx" style="display: block; padding: 0 10px">     "grunt-sass": "~1.2.1",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "grunt-webpack": "^3.0.2",
</ins><span class="cx" style="display: block; padding: 0 10px">     "ink-docstrap": "^1.3.0",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    "grunt-webpack": "^3.0.2",
</del><span class="cx" style="display: block; padding: 0 10px">     "matchdep": "~1.0.0",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    "wait-on": "~3.2.0",
</ins><span class="cx" style="display: block; padding: 0 10px">     "webpack": "^3.6.0",
</span><span class="cx" style="display: block; padding: 0 10px">     "webpack-dev-server": "^2.9.1"
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  },
+  "scripts": {
+    "build": "grunt build",
+    "build:dev": "grunt build --dev",
+    "dev": "grunt watch --dev",
+    "test": "grunt test",
+    "watch": "grunt watch",
+    "grunt": "grunt",
+    "env:start": "node ./tools/local-env/scripts/start.js",
+    "env:stop": "node ./tools/local-env/scripts/docker.js down",
+    "env:restart": "npm run env:stop && npm run env:start",
+    "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"
</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="branches49testsphpunitincludesobjectcachephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.9/tests/phpunit/includes/object-cache.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tests/phpunit/includes/object-cache.php      2020-11-06 17:29:16 UTC (rev 49529)
+++ branches/4.9/tests/phpunit/includes/object-cache.php        2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -829,7 +829,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if ( isset( $memcached_servers ) )
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->servers = $memcached_servers;
</span><span class="cx" style="display: block; padding: 0 10px">                else
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->servers = array( array( '127.0.0.1', 11211 ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->servers = array( array( 'memcached', 11211 ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->addServers( $this->servers );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="branches49testsphpunittestsajaxCustomizeMenusphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.9/tests/phpunit/tests/ajax/CustomizeMenus.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tests/phpunit/tests/ajax/CustomizeMenus.php  2020-11-06 17:29:16 UTC (rev 49529)
+++ branches/4.9/tests/phpunit/tests/ajax/CustomizeMenus.php    2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -54,7 +54,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'administrator' != $role ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        // If we're not an admin, we should get a wp_die(-1).
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->setExpectedException( 'WPAjaxDieStopException' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->setExpectedException( 'WPAjaxDieStopException', '-1' );
</ins><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">                wp_set_current_user( self::factory()->user->create( array( 'role' => $role ) ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -429,7 +429,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'administrator' != $role ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        // If we're not an admin, we should get a wp_die(-1).
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->setExpectedException( 'WPAjaxDieStopException' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->setExpectedException( 'WPAjaxDieStopException', '-1' );
</ins><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">                wp_set_current_user( self::factory()->user->create( array( 'role' => $role ) ) );
</span></span></pre></div>
<a id="branches49toolslocalenvdefaulttemplate"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/tools/local-env/default.template</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tools/local-env/default.template                             (rev 0)
+++ branches/4.9/tools/local-env/default.template       2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,32 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+server {
+       index index.php index.html;
+
+       listen 80 default_server;
+       listen [::]:80 default_server;
+
+       server_name localhost;
+
+       client_max_body_size 1g;
+
+       error_log  /var/log/nginx/error.log;
+       access_log /var/log/nginx/access.log;
+
+       root /var/www/${LOCAL_DIR};
+
+       absolute_redirect off;
+
+       location / {
+               try_files $uri $uri/ /index.php?$args;
+       }
+
+       location ~ \.php$ {
+               try_files $uri =404;
+               fastcgi_split_path_info ^(.+\.php)(/.+)$;
+               fastcgi_pass php:9000;
+               fastcgi_index index.php;
+               include fastcgi_params;
+               fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+               fastcgi_param PATH_INFO $fastcgi_path_info;
+               fastcgi_pass_header Authorization;
+       }
+}
</ins></span></pre></div>
<a id="branches49toolslocalenvmysqlinitsql"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/tools/local-env/mysql-init.sql</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tools/local-env/mysql-init.sql                               (rev 0)
+++ branches/4.9/tools/local-env/mysql-init.sql 2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,8 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * MySQL server init.
+ *
+ * SQL queries in this file will be executed the first time the MySQL server is started.
+ */
+
+CREATE DATABASE IF NOT EXISTS wordpress_develop;
+CREATE DATABASE IF NOT EXISTS wordpress_develop_tests;
</ins></span></pre></div>
<a id="branches49toolslocalenvphpconfigini"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/tools/local-env/php-config.ini</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tools/local-env/php-config.ini                               (rev 0)
+++ branches/4.9/tools/local-env/php-config.ini 2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,2 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+upload_max_filesize = 1G
+post_max_size = 1G
</ins></span></pre></div>
<a id="branches49toolslocalenvphpunitconfigini"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/tools/local-env/phpunit-config.ini</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tools/local-env/phpunit-config.ini                           (rev 0)
+++ branches/4.9/tools/local-env/phpunit-config.ini     2020-11-06 17:32:00 UTC (rev 49530)
</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">+upload_max_filesize = 1G
+post_max_size = 1G
+
+opcache.enable = 1
+opcache.enable_cli = 1
+opache.file_cache = /tmp/php-opcache
</ins></span></pre></div>
<a id="branches49toolslocalenvscriptsdockerjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/tools/local-env/scripts/docker.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tools/local-env/scripts/docker.js                            (rev 0)
+++ branches/4.9/tools/local-env/scripts/docker.js      2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,8 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const dotenv       = require( 'dotenv' );
+const dotenvExpand = require( 'dotenv-expand' );
+const { execSync } = require( 'child_process' );
+
+dotenvExpand( 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="branches49toolslocalenvscriptsinstalljs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/tools/local-env/scripts/install.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tools/local-env/scripts/install.js                           (rev 0)
+++ branches/4.9/tools/local-env/scripts/install.js     2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,47 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const dotenv       = require( 'dotenv' );
+const dotenvExpand = require( 'dotenv-expand' );
+const wait_on = require( 'wait-on' );
+const { execSync } = require( 'child_process' );
+const { renameSync, readFileSync, writeFileSync } = require( 'fs' );
+
+dotenvExpand( 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 --type=constant` );
+wp_cli( `config set WP_DEBUG_LOG ${process.env.LOCAL_WP_DEBUG_LOG} --raw --type=constant` );
+wp_cli( `config set WP_DEBUG_DISPLAY ${process.env.LOCAL_WP_DEBUG_DISPLAY} --raw --type=constant` );
+wp_cli( `config set SCRIPT_DEBUG ${process.env.LOCAL_SCRIPT_DEBUG} --raw --type=constant` );
+wp_cli( `config set WP_ENVIRONMENT_TYPE ${process.env.LOCAL_WP_ENVIRONMENT_TYPE} --type=constant` );
+
+// 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="branches49toolslocalenvscriptsstartjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: branches/4.9/tools/local-env/scripts/start.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.9/tools/local-env/scripts/start.js                             (rev 0)
+++ branches/4.9/tools/local-env/scripts/start.js       2020-11-06 17:32:00 UTC (rev 49530)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,36 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+const dotenv       = require( 'dotenv' );
+const dotenvExpand = require( 'dotenv-expand' );
+const { execSync } = require( 'child_process' );
+
+dotenvExpand( 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'
+
+       // Check if the port forwarding is already configured for this port.
+       const vminfoBuffer = execSync( `"${ vboxmanage }" showvminfo "${ process.env.DOCKER_MACHINE_NAME }" --machinereadable` );
+       const vminfo = vminfoBuffer.toString().split( /[\r\n]+/ );
+
+       vminfo.forEach( ( info ) => {
+               if ( ! info.startsWith( 'Forwarding' ) ) {
+                       return;
+               }
+
+               // `info` is in the format: Forwarding(1)="tcp-port8889,tcp,127.0.0.1,8889,,8889"
+               // Parse it down so `rule` only contains the data inside quotes, split by ','.
+               const rule = info.replace( /(^.*?"|"$)/, '' ).split( ',' );
+
+               // Delete rules that are using the port we need.
+               if ( rule[ 3 ] === process.env.LOCAL_PORT || rule[ 5 ] === process.env.LOCAL_PORT ) {
+                       execSync( `"${ vboxmanage }" controlvm "${ process.env.DOCKER_MACHINE_NAME }" natpf1 delete ${ rule[ 0 ] }`, { stdio: 'inherit' } );
+               }
+       } );
+
+       // Add our port forwarding rule.
+       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>