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 #47767.



git-svn-id: https://develop.svn.wordpress.org/trunk@45783 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Gary Pendergast 2019-08-12 08:28:33 +00:00
parent 83eb411e27
commit 13d356691b
12 changed files with 166 additions and 679 deletions

3
.env
View File

@ -29,3 +29,6 @@ LOCAL_WP_DEBUG=true
LOCAL_WP_DEBUG_LOG=true
LOCAL_WP_DEBUG_DISPLAY=true
LOCAL_SCRIPT_DEBUG=true
# The URL to use when running e2e tests.
WP_BASE_URL=http://localhost:${LOCAL_PORT}

3
.gitignore vendored
View File

@ -73,3 +73,6 @@ wp-tests-config.php
*.diff
.svn
!/src/js/_enqueues/vendor
# Files for local environment config
/docker-compose.override.yml

View File

@ -1,7 +1,7 @@
language: php
language: generic
services:
- docker
- mysql
addons:
apt:
@ -51,12 +51,6 @@ matrix:
before_install:
- |
if [[ "$WP_TRAVISCI" == "test:php" ]]; then
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
travis_retry svn checkout https://plugins.svn.wordpress.org/wordpress-importer/tags/0.6.3/ tests/phpunit/data/plugins/wordpress-importer
fi
- |
@ -73,16 +67,6 @@ before_script:
else
echo "xdebug.ini does not exist"
fi
- |
# 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
- |
# We only need to run composer install on the PHP coding standards job.
if [[ "$WP_TRAVISCI" == "travis:phpcs" ]]; then
@ -98,18 +82,20 @@ before_script:
if [[ "$WP_TRAVISCI" == "test:e2e" ]] || [[ "$WP_TRAVISCI" == "test:php" ]]; then
npm run env:start
npm run build
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
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
docker run --name memcached --net local-env_wpdevnet -d memcached
# 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
fi
- |
if [[ "$WP_TRAVISCI" == "test:e2e" ]]; then
if [[ "$WP_TRAVISCI" == "test:e2e" ]] || [[ "$WP_TRAVISCI" == "test:php" ]]; then
# Run the install process after memcached has started.
npm run env:install
fi
- npm --version
@ -124,12 +110,12 @@ script:
if [[ "$WP_TRAVISCI" == "test:e2e" ]]; then
npm run test:e2e
elif [[ "$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
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
else
npm run grunt $WP_TRAVISCI
fi
@ -138,9 +124,7 @@ after_script:
- |
if [[ "$WP_TEST_REPORTER" == "true" ]]; then
git clone https://github.com/WordPress/phpunit-test-runner.git test-runner
export WPT_PREPARE_DIR=$(pwd)
export WPT_TEST_DIR=$(pwd)
php test-runner/report.php
docker-compose run --rm -e WPT_PREPARE_DIR=/var/www -e WPT_TEST_DIR=/var/www php php test-runner/report.php
fi
notifications:

568
package-lock.json generated
View File

@ -3719,28 +3719,6 @@
"trim-right": "^1.0.1"
}
},
"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"
}
},
"babel-helper-call-delegate": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
@ -3763,29 +3741,6 @@
"lodash": "^4.17.4"
}
},
"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"
}
},
"babel-helper-function-name": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
@ -3835,19 +3790,6 @@
"lodash": "^4.17.4"
}
},
"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"
}
},
"babel-helper-replace-supers": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
@ -4015,146 +3957,6 @@
"@types/babel__traverse": "^7.0.6"
}
},
"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"
}
},
"babel-plugin-transform-es2015-arrow-functions": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
@ -4367,47 +4169,6 @@
"regexpu-core": "^2.0.0"
}
},
"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"
}
},
"babel-plugin-transform-regenerator": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
@ -4466,53 +4227,6 @@
"babel-plugin-jest-hoist": "^24.6.0"
}
},
"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"
}
},
"babel-register": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
@ -6170,174 +5884,6 @@
}
}
},
"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"
}
}
}
},
"core-js": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.1.4.tgz",
@ -6451,31 +5997,6 @@
"sha.js": "^2.4.8"
}
},
"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"
}
}
}
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@ -6486,19 +6007,6 @@
"which": "^1.2.9"
}
},
"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"
}
},
"crypto-browserify": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
@ -7609,41 +7117,11 @@
"is-obj": "^1.0.0"
}
},
"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
}
}
"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
},
"dotenv-expand": {
"version": "5.1.0",
@ -16143,42 +15621,6 @@
"dev": true,
"optional": true
},
"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
}
}
},
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",

View File

@ -22,12 +22,10 @@
"babel-jest": "24.8.0",
"check-node-version": "3.2.0",
"copy-webpack-plugin": "^4.6.0",
"copyfiles": "2.1.1",
"core-js": "3.1.4",
"cross-env": "5.2.0",
"cross-var": "1.1.0",
"cssnano": "4.1.8",
"dotenv-cli": "2.0.1",
"dotenv": "8.0.0",
"dotenv-expand": "5.1.0",
"grunt": "~1.0.3",
"grunt-banner": "^0.6.0",
"grunt-contrib-clean": "~2.0.0",
@ -129,29 +127,15 @@
"test": "grunt test",
"watch": "grunt watch",
"grunt": "grunt",
"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"
"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"
}
}

9
tests/e2e/run-tests.js Normal file
View File

@ -0,0 +1,9 @@
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' } );

View File

@ -13,6 +13,8 @@ server {
root /var/www/${LOCAL_DIR};
absolute_redirect off;
location / {
try_files $uri $uri/ /index.php?$args;
}

View File

@ -1,50 +0,0 @@
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: {}

View File

@ -18,8 +18,8 @@ services:
LOCAL_DIR: ${LOCAL_DIR-src}
volumes:
- ./default.template:/etc/nginx/conf.d/default.template
- ../../:/var/www
- ./tools/local-env/default.template:/etc/nginx/conf.d/default.template
- ./:/var/www
# Load our config file, substituning 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;'"
@ -41,8 +41,8 @@ services:
LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false}
volumes:
- ./php-config.ini:/usr/local/etc/php/conf.d/php-config.ini
- ../../:/var/www
- ./tools/local-env/php-config.ini:/usr/local/etc/php/conf.d/php-config.ini
- ./:/var/www
depends_on:
- mysql
@ -60,15 +60,60 @@ services:
MYSQL_ROOT_PASSWORD: password
volumes:
- ./mysql-init.sql:/docker-entrypoint-initdb.d/mysql-init.sql
- ./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-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
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.

View File

@ -0,0 +1,6 @@
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' } );

View File

@ -0,0 +1,45 @@
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' } );
}

View File

@ -0,0 +1,14 @@
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' } );
}