diff --git a/changelog.md b/changelog.md index a55fe05..2dc8de3 100644 --- a/changelog.md +++ b/changelog.md @@ -4,7 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.5.8] - 2020-09-23 +## [0.5.9] - 2020-10-07 +### Changed + +- Add the `site-cli` command to start a wp-cli container on a running and ready WordPress stack. + +## [0.5.8] - 2020-10-06 ### Changed - Add a check to ensure a target is set for commands that require it. diff --git a/src/commands/site-cli.php b/src/commands/site-cli.php new file mode 100644 index 0000000..e79a028 --- /dev/null +++ b/src/commands/site-cli.php @@ -0,0 +1,76 @@ +{$cli_name} site-cli [ssh] [...]\n" ); + echo colorize( "example: {$cli_name} site-cli plugin list --status=active\n" ); + echo colorize( "example: {$cli_name} site-cli theme install twentytwenty\n" ); + echo colorize( "example: {$cli_name} site-cli _install" ); + + return; +} + +setup_id(); +$command = $args( '...' ); + +if ( 'wp' === reset( $command ) ) { + // If there's an initial `wp` remove it; the user might have called the command with `tric site-cli wp ...`. + array_shift( $command ); +} + +/* + * wp-cli already comes with a `shell` command that will open a PHP shell, same as `php -a`, in it. + * As much as it would be ideal to use the `shell` sub-command to open a shell... we cannot use the `shell` word. + */ +$open_bash_shell = reset( $command ) === 'bash'; + +/* + * This is an "internal" shortcut to quickly install WordPress for the purpose of performing some operations on its + * structure. + */ +$_install = reset( $command ) === '_install'; + +if ( ! $open_bash_shell ) { + if ( $_install ) { + $confirm = ask( "The _install sub-command is meant for CI use, " . + "if you want to install WordPress use the '{$cli_name} site-cli core install' command. " . + "\nDo you really want to run it?", 'yes' ); + + if ( ! $confirm ) { + exit( 0 ); + } + + // Drop the `_install` subcommand, build the rest of the command. + array_shift( $command ); + // Set up for the quick installation. + array_push( $command, 'core', 'install', '--path=/var/www/html', '--url=http://wordpress.test', + '--title=Tric', '--admin_user=admin', '--admin_password=admin', '--admin_email=admin@wordpress.test', + '--skip-email' ); + } + + // Make sure to prepend with `wp --allow-root`. + array_unshift( $command, 'wp', '--allow-root' ); + + /* + * Due to how docker-compose works, the default `CMD` for the `wordpress:cli` image will be overridden as a + * consequence of overriding the `entrypoint` configuration parameter of the service. + * We cannot, thus, pass the user command directly, we use an env var, `TRIC_SITE_CLI_COMMAND`, to embed the + * command we're running into the entrypoint call arguments. + * + * @link https://docs.docker.com/compose/compose-file/#entrypoint + */ + putenv( 'TRIC_SITE_CLI_COMMAND=' . implode( ' ', $command ) ); + + $status = tric_realtime()( [ 'run', '--rm', 'site-cli' ] ); +} else { + // What user ID are we running this as? + $user = getenv( 'DOCKER_RUN_UID' ); + // Do not run the wp-cli container as `root` to avoid a number of file mode issues, run as `www-data` instead. + $user = empty( $user ) ? 'www-data' : $user; + $status = tric_realtime()( [ 'run', '--rm', "--user={$user}", '--entrypoint', 'bash', 'site-cli' ] ); +} + +exit( $status ); diff --git a/src/tric.php b/src/tric.php index 33a6fd4..fd28435 100644 --- a/src/tric.php +++ b/src/tric.php @@ -900,11 +900,12 @@ function execute_command_pool( $pool ) { * Returns an array of arguments to correctly run a wp-cli commann in the tric stack. * * @param array $command The wp-cli command to run, anything after the `wp`; e.g. `[ 'plugin', 'list' ]`. + * @param string $service The wp-cli service to target; defaults to the `cli` one. * * @return array The complete command arguments, ready to be used in the `tric` or `tric_realtime` functions. */ -function cli_command( array $command = [] ) { - return array_merge( [ 'run', '--rm', 'cli', 'wp', '--allow-root' ], $command ); +function cli_command( array $command = [], $service = 'cli' ) { + return array_merge( [ 'run', '--rm', $service, 'wp', '--allow-root' ], $command ); } /** diff --git a/src/wordpress.php b/src/wordpress.php index df7bd67..2007c0d 100644 --- a/src/wordpress.php +++ b/src/wordpress.php @@ -14,7 +14,7 @@ */ function maybe_generate_htaccess() { $htaccess_path = root( '_wordpress/.htaccess' ); - $htaccess = file_get_contents( $htaccess_path ); + $htaccess = is_file( $htaccess_path ) && file_get_contents( $htaccess_path ); if ( $htaccess ) { return; diff --git a/tric b/tric index 304c9b9..bf450c4 100755 --- a/tric +++ b/tric @@ -25,7 +25,7 @@ $args = args( [ ] ); $cli_name = basename( $argv[0] ); -const CLI_VERSION = '0.5.7'; +const CLI_VERSION = '0.5.9'; $cli_header = implode( ' - ', [ light_cyan( $cli_name ) . ' version ' . light_cyan( CLI_VERSION ), @@ -63,6 +63,7 @@ Available commands: cc Runs a Codeception command in the stack, the equivalent of 'codecept ...'. shell Opens a shell in a stack service, defaults to the 'codeception' one. cli Runs a wp-cli command in the stack or opens a session into the wp-cli container. +site-cli Waits for WordPress to be correctly set up to run a wp-cli command in the stack. reset Resets {$cli_name} to the initial state as configured by the env files. update Updates the tool and the images used in its services. upgrade Upgrades the {$cli_name} repo. @@ -136,6 +137,7 @@ switch ( $subcommand ) { case 'run': case 'serve': case 'shell': + case 'site-cli': case 'target': case 'up': case 'update': diff --git a/tric-stack.yml b/tric-stack.yml index e236afd..a9946c9 100644 --- a/tric-stack.yml +++ b/tric-stack.yml @@ -105,6 +105,48 @@ services: - ${TRIC_PLUGINS_DIR}:/var/www/html/wp-content/plugins:cached - ${TRIC_THEMES_DIR}:/var/www/html/wp-content/themes:cached + site-cli: + image: wordpress:cli + user: "${DOCKER_RUN_UID:-}:${DOCKER_RUN_GID:-}" + networks: + - tric + extra_hosts: + - "wordpress.test:172.${TRIC_TEST_SUBNET:-28}.1.1" + environment: + FIXUID: "${FIXUID:-1}" + # Configure this to debug the tests with XDebug. + # Map the `_wordpress` directory to `/var/www/html' directory in your IDE of choice. + # Map the `_plugins` directory to `/plugins' directory in your IDE of choice. + PHP_IDE_CONFIG: "serverName=${XDK:-tric}" + # The `remote_host` is set to `host.docker.internal` that will resolve to the host machine IP address, from + # within the container, on macOS and Windows. + # On Linux set the host machine IP address before calling the stack: + # XDH=$(ip route | grep docker0 | awk '{print $9}') docker-compose ... + XDEBUG_CONFIG: "idekey=${XDK:-tric} remote_enable=${XDE:-1} remote_host=${XDH:-host.docker.internal} remote_port=${XDP:-9001}" + depends_on: + - wordpress + # Override the default entrypoint to wait for the WordPress container, and required services to be up and running. + # Then run the default entrypoint with a command read from the environment variables. + # When overriding the `entrypoint` the `CMD` defined in the image, and an overriding `command`, will be ignored + # and this requires the entrypoint to contain the command we want to run (`TRIC_SITE_CLI_COMMAND`) already. + # see https://docs.docker.com/compose/compose-file/#entrypoint + entrypoint: + - /bin/bash + - -c + - | + printf "Waiting for WordPress site "; + until $$(curl -o /dev/null -f -s -I wordpress.test:80); do printf '.' && sleep 1; done + echo -e -n " \e[32mdone\e[0m\n" + echo "Executing command: ${TRIC_SITE_CLI_COMMAND:-core version}" + docker-entrypoint.sh ${TRIC_SITE_CLI_COMMAND:-core version} + volumes: + # Paths are relative to the directory that contains this file, NOT the current working directory. + # Share the WordPress core installation files in the `_wordpress` directory. + - ${TRIC_WP_DIR}:/var/www/html:cached + # Share the WordPress core installation files in the `_plugins` directory. + - ${TRIC_PLUGINS_DIR}:/var/www/html/wp-content/plugins:cached + - ${TRIC_THEMES_DIR}:/var/www/html/wp-content/themes:cached + site_waiter: # Waits for the WordPress site to be available. image: curlimages/curl