diff --git a/qit b/qit
index 5eeddabf..f4be07d3 100755
Binary files a/qit and b/qit differ
diff --git a/src/src/Commands/Environment/DownEnvironmentCommand.php b/src/src/Commands/Environment/DownEnvironmentCommand.php
index b8bf21ac..520c6ca7 100644
--- a/src/src/Commands/Environment/DownEnvironmentCommand.php
+++ b/src/src/Commands/Environment/DownEnvironmentCommand.php
@@ -9,6 +9,7 @@
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use function QIT_CLI\format_elapsed_time;
@@ -43,44 +44,58 @@ protected function execute( InputInterface $input, OutputInterface $output ): in
return Command::SUCCESS;
}
- if ( count( $running_environments ) === 1 ) {
- $this->stop_environment( array_shift( $running_environments ), $output );
+ $selected_environment = null;
- return Command::SUCCESS;
+ if ( count( $running_environments ) === 1 ) {
+ $selected_environment = array_shift( $running_environments );
}
- $environment_choices = array_map( function ( EnvInfo $environment ) {
- return sprintf( 'Created: %s, Status: %s',
- format_elapsed_time( time() - $environment->created_at ),
- $environment->status );
- }, $running_environments );
-
- $environment_choices['all'] = 'Stop all environments';
-
- // More than one environment running, let user choose which one to stop.
- $helper = new QuestionHelper();
- $question = new ChoiceQuestion(
- 'Please select the environment to stop (or choose to stop all):',
- $environment_choices,
- 'all'
- );
- $question->setErrorMessage( 'Environment %s is invalid.' );
-
- $selected_environment = $helper->ask( $input, $output, $question );
+ if ( is_null( $selected_environment ) ) {
+ $environment_choices = array_map( function ( EnvInfo $environment ) {
+ return sprintf( 'Created: %s, Status: %s',
+ format_elapsed_time( time() - $environment->created_at ),
+ $environment->status );
+ }, $running_environments );
+
+ $environment_choices['all'] = 'Stop all environments';
+
+ // More than one environment running, let user choose which one to stop.
+ $helper = new QuestionHelper();
+ $question = new ChoiceQuestion(
+ 'Please select the environment to stop (or choose to stop all):',
+ $environment_choices,
+ 'all'
+ );
+ $question->setErrorMessage( 'Environment %s is invalid.' );
+
+ $selected_environment = $helper->ask( $input, $output, $question );
+ }
if ( $selected_environment === 'all' ) {
+ $total_environments = count( $running_environments );
+ $counter = 1;
+
foreach ( $running_environments as $environment ) {
- $this->stop_environment( $environment, $output );
+ $output->write( "\rStopping all environments... [{$counter}/{$total_environments}]" );
+ $this->stop_environment( $environment, $output->isVerbose() ? $output : new NullOutput() );
+ ++$counter;
}
} else {
- $this->stop_environment( $this->environment_monitor->get_env_info_by_id( $selected_environment ), $output );
+ $total_environments = 1;
+ if ( ! $selected_environment instanceof EnvInfo ) {
+ $selected_environment = $this->environment_monitor->get_env_info_by_id( $selected_environment );
+ }
+ $output->write( "\rStopping all environments... [1/1]" );
+ $this->stop_environment( $selected_environment, $output->isVerbose() ? $output : new NullOutput() );
}
+ $output->write( "\rStopped all environments [{$total_environments}/{$total_environments}]." );
+
return Command::SUCCESS;
}
private function stop_environment( EnvInfo $environment, OutputInterface $output ): void {
- Environment::down( $environment );
+ Environment::down( $environment, $output );
$environment_id = $environment->env_id;
$output->writeln( "Environment '$environment_id' stopped." );
}
diff --git a/src/src/Commands/Environment/UpEnvironmentCommand.php b/src/src/Commands/Environment/UpEnvironmentCommand.php
index 4d32952b..dda52cdc 100644
--- a/src/src/Commands/Environment/UpEnvironmentCommand.php
+++ b/src/src/Commands/Environment/UpEnvironmentCommand.php
@@ -252,7 +252,9 @@ protected function execute( InputInterface $input, OutputInterface $output ): in
$env_info = App::make( EnvConfigLoader::class )->init_env_info( $options_to_env_info );
- $this->output->writeln( json_encode( $env_info, JSON_PRETTY_PRINT ) );
+ if ( $output->isVeryVerbose() ) {
+ $this->output->writeln( 'Environment info: ' . json_encode( $env_info, JSON_PRETTY_PRINT ) );
+ }
$this->e2e_environment->init( $env_info );
$this->e2e_environment->up();
diff --git a/src/src/Environment/Docker.php b/src/src/Environment/Docker.php
index 80e06e88..7ccbff81 100644
--- a/src/src/Environment/Docker.php
+++ b/src/src/Environment/Docker.php
@@ -113,7 +113,7 @@ public function run_inside_docker( EnvInfo $env_info, array $command, array $env
$docker_image = $env_info->get_docker_container( $image );
$docker_command = [ $this->find_docker(), 'exec' ];
- if ( use_tty() ) {
+ if ( $this->output->isVerbose() && use_tty() ) {
$docker_command = array_merge( $docker_command, [ '-it' ] );
}
@@ -157,7 +157,7 @@ public function run_inside_docker( EnvInfo $env_info, array $command, array $env
}
$process = new Process( $docker_command );
- $process->setTty( use_tty() );
+ $process->setTty( $this->output->isVerbose() && use_tty() );
$process->setTimeout( $timeout );
$process->setIdleTimeout( $timeout );
@@ -167,7 +167,9 @@ public function run_inside_docker( EnvInfo $env_info, array $command, array $env
}
$process->run( function ( $type, $buffer ) {
- $this->output->write( $buffer );
+ if ( $this->output->isVerbose() ) {
+ $this->output->write( $buffer );
+ }
} );
if ( ! $process->isSuccessful() ) {
diff --git a/src/src/Environment/EnvironmentDanglingCleanup.php b/src/src/Environment/EnvironmentDanglingCleanup.php
index 0366c30c..9502e8e5 100644
--- a/src/src/Environment/EnvironmentDanglingCleanup.php
+++ b/src/src/Environment/EnvironmentDanglingCleanup.php
@@ -76,7 +76,7 @@ public function cleanup_dangling(): void {
}
if ( ! $this->header_printed ) {
- $this->output->writeln( 'Cleaning up dangling temp environments...' );
+ $this->output->writeln( 'Cleaning up dangling temporary environments...' );
$this->header_printed = true;
}
@@ -119,7 +119,7 @@ public function cleanup_dangling(): void {
// Skip asking the user permission to delete in this directory if they answer with an "A".
$always_delete_from_this_directory = $this->cache->get( 'always_delete_from_this_directory' );
- $parent_dir = $this->get_parent_dir_to_delete();
+ $parent_dir = $this->get_parent_dir_to_delete();
if ( $always_delete_from_this_directory !== $parent_dir && ! is_ci() ) {
$this->output->writeln( "Found dangling temporary environments in directory: $parent_dir" );
@@ -140,7 +140,7 @@ public function cleanup_dangling(): void {
break;
case 'n':
default:
- $this->output->writeln( 'Action cancelled by user.' );
+ $this->output->writeln( 'Please delete the dangling environments in that directory manually.' );
return;
}
@@ -339,12 +339,12 @@ protected function remove_dangling_environments(): void {
}
if ( ! empty( $containers_not_running ) ) {
if ( ! $this->header_printed ) {
- $this->output->writeln( 'Dangling Temporary Environments found.' );
+ $this->output->writeln( 'Cleaning up dangling temporary environments...' );
$this->header_printed = true;
}
- $this->output->writeln( "Removing dangling environment: {$env_info->env_id}" );
- if ( $this->output->isVerbose() ) {
+ $this->debug_output( "Removing dangling environment: {$env_info->env_id}" );
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( 'Expected containers: ' . implode( ', ', $env_info->docker_images ) );
$this->output->writeln( 'Missing containers: ' . implode( ', ', $containers_not_running ) );
}
diff --git a/src/src/Environment/EnvironmentDownloader.php b/src/src/Environment/EnvironmentDownloader.php
index 85a9cc4c..7fb28271 100644
--- a/src/src/Environment/EnvironmentDownloader.php
+++ b/src/src/Environment/EnvironmentDownloader.php
@@ -87,6 +87,15 @@ public function maybe_download( string $env_name ): void {
if ( ! $zip->extractTo( $environments_dir . '/' . $env_name ) ) {
throw new \RuntimeException( 'Could not extract environment zip.' );
}
+
+ // Ensure .sh files in the extracted directory are executable, just in case.
+ $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $environments_dir . '/' . $env_name ) );
+ foreach ( $iterator as $file ) {
+ if ( $file->isFile() && $file->getExtension() === 'sh' ) {
+ chmod( $file->getPathname(), 0755 );
+ }
+ }
+
$zip->close();
$this->cache->set( "{$env_name}_environment_hash", $manager_hashes[ $env_name ]['checksum'], MONTH_IN_SECONDS );
} else {
diff --git a/src/src/Environment/Environments/E2E/E2EEnvironment.php b/src/src/Environment/Environments/E2E/E2EEnvironment.php
index b8253789..c75376b3 100644
--- a/src/src/Environment/Environments/E2E/E2EEnvironment.php
+++ b/src/src/Environment/Environments/E2E/E2EEnvironment.php
@@ -61,7 +61,7 @@ protected function post_up(): void {
// Setup WordPress.
$this->output->writeln( 'Setting up WordPress...' );
- $this->docker->run_inside_docker( $this->env_info, [ '/bin/bash', '/qit/bin/wordpress-setup.sh' ], [
+ $this->docker->run_inside_docker( $this->env_info, [ '/bin/bash', '-c', '/qit/bin/wordpress-setup.sh 2>&1' ], [
'WORDPRESS_VERSION' => $this->env_info->wordpress_version,
'WOOCOMMERCE_VERSION' => $this->env_info->woocommerce_version,
'PLUGINS_TO_INSTALL' => json_encode( $this->env_info->plugins ),
diff --git a/src/src/Environment/Environments/Environment.php b/src/src/Environment/Environments/Environment.php
index 76978e5a..a159c76f 100644
--- a/src/src/Environment/Environments/Environment.php
+++ b/src/src/Environment/Environments/Environment.php
@@ -109,14 +109,20 @@ public function up( bool $attached = false ): void {
$this->maybe_create_cache_dir();
$this->copy_environment();
$this->environment_monitor->environment_added_or_updated( $this->env_info );
+ if ( ! empty( $this->env_info->plugins ) || ! empty( $this->env_info->themes ) ) {
+ $this->output->writeln( 'Downloading plugins and themes...' );
+ }
$this->extension_downloader->download( $this->env_info, $this->cache_dir, $this->env_info->plugins, $this->env_info->themes );
+ $this->output->writeln( 'Setting up Docker...' );
$this->generate_docker_compose();
$this->post_generate_docker_compose();
$this->up_docker_compose( $attached );
$this->post_up();
- $this->output->writeln( 'Server started at ' . round( microtime( true ) - $start, 2 ) . ' seconds' );
- $this->output->writeln( "Temporary environment: {$this->env_info->temporary_env}\n" );
+ if ( $this->output->isVerbose() ) {
+ $this->output->writeln( 'Server started in ' . round( microtime( true ) - $start, 2 ) . ' seconds' );
+ }
+
$this->additional_output();
}
@@ -194,13 +200,14 @@ protected function generate_docker_compose(): void {
'QIT_DOCKER_REDIS' => 'no', // Default. Might be overridden by the concrete environment.
], $this->get_generate_docker_compose_envs() ) );
- if ( $this->output->isVerbose() ) {
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( $process->getCommandLine() );
- $this->output->writeln( json_encode( $process->getEnv(), JSON_PRETTY_PRINT ) );
}
$process->run( function ( $type, $buffer ) {
- $this->output->write( $buffer );
+ if ( $this->output->isVerbose() || $type === Process::ERR ) {
+ $this->output->write( $buffer );
+ }
} );
if ( ! $process->isSuccessful() ) {
@@ -233,10 +240,12 @@ protected function up_docker_compose( bool $attached ): void {
$up_process->setTimeout( 300 );
$up_process->setIdleTimeout( 300 );
- $up_process->setTty( use_tty() );
+ $up_process->setPty( use_tty() );
$up_process->run( function ( $type, $buffer ) {
- $this->output->write( $buffer );
+ if ( $this->output->isVerbose() ) {
+ $this->output->write( $buffer );
+ }
} );
if ( ! $up_process->isSuccessful() ) {
@@ -249,8 +258,8 @@ protected function up_docker_compose( bool $attached ): void {
$this->environment_monitor->environment_added_or_updated( $this->env_info );
}
- public static function down( EnvInfo $env_info ): void {
- $output = App::make( OutputInterface::class );
+ public static function down( EnvInfo $env_info, ?OutputInterface $output = null ): void {
+ $output = $output ?? App::make( OutputInterface::class );
$environment_monitor = App::make( EnvironmentMonitor::class );
if ( ! file_exists( $env_info->temporary_env ) ) {
@@ -267,7 +276,7 @@ public static function down( EnvInfo $env_info ): void {
$down_process = new Process( array_merge( App::make( Docker::class )->find_docker_compose(), [ '-f', $env_info->temporary_env . '/docker-compose.yml', 'down' ] ) );
$down_process->setTimeout( 300 );
$down_process->setIdleTimeout( 300 );
- $down_process->setTty( use_tty() );
+ $down_process->setPty( use_tty() );
$down_process->run( static function ( $type, $buffer ) use ( $output ) {
$output->write( $buffer );
diff --git a/src/src/Environment/ExtensionDownload/ExtensionZip.php b/src/src/Environment/ExtensionDownload/ExtensionZip.php
index 7a4ce7ff..f97c55d8 100644
--- a/src/src/Environment/ExtensionDownload/ExtensionZip.php
+++ b/src/src/Environment/ExtensionDownload/ExtensionZip.php
@@ -52,13 +52,13 @@ public function extract_zip( string $zip_file, string $extract_to ): void {
$zip->extractTo( $extract_to );
$zip->close();
- if ( $this->output->isVerbose() ) {
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( sprintf( 'ZipArchive extraction of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) );
}
return;
} else {
- if ( $this->output->isVerbose() ) {
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( sprintf( 'ZipArchive extraction of %s failed, falling back to Docker (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) );
}
}
@@ -86,7 +86,7 @@ public function extract_zip( string $zip_file, string $extract_to ): void {
'Docker ZIP Extraction: ' . $this->output->writeln( $out );
}
} );
- if ( $this->output->isVerbose() ) {
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( sprintf( 'Docker ZIP extraction of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) );
}
}
@@ -104,13 +104,13 @@ public function validate_zip( string $zip_file ): void {
if ( $zip->open( $zip_file, \ZipArchive::CHECKCONS ) === true ) {
$zip->close();
- if ( $this->output->isVerbose() ) {
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( sprintf( 'ZipArchive validation of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) );
}
return;
} else {
- if ( $this->output->isVerbose() ) {
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( sprintf( 'ZipArchive validation of %s failed, falling back to Docker (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) );
}
}
@@ -140,7 +140,7 @@ public function validate_zip( string $zip_file ): void {
}
} );
- if ( $this->output->isVerbose() ) {
+ if ( $this->output->isVeryVerbose() ) {
$this->output->writeln( sprintf( 'Docker ZIP validation of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) );
}
}
diff --git a/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php b/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php
index 969cf5c9..cf18aabf 100644
--- a/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php
+++ b/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php
@@ -30,7 +30,9 @@ public function populate_extension_versions( array $extensions ): void {
'extensions' => $extensions_to_download,
] )
->request();
- $output->writeln( sprintf( 'Fetched versions for %d extensions from QIT in %f seconds.', count( $extensions ), microtime( true ) - $start ) );
+ if ( $output->isVerbose() ) {
+ $output->writeln( sprintf( 'Fetched versions for %d extensions from QIT in %f seconds.', count( $extensions ), microtime( true ) - $start ) );
+ }
/**
* @param $download_urls array{
diff --git a/src/src/RequestBuilder.php b/src/src/RequestBuilder.php
index 71b1872b..894e47ae 100644
--- a/src/src/RequestBuilder.php
+++ b/src/src/RequestBuilder.php
@@ -175,7 +175,7 @@ public function request(): string {
}
}
- if ( App::make( Output::class )->isVeryVerbose() ) {
+ if ( getenv( 'QIT_DEBUG_REQUESTS' ) ) {
$curl_parameters[ CURLOPT_VERBOSE ] = true;
}