Skip to content

Commit

Permalink
5.4.0: Project bootstrapping updates (#93)
Browse files Browse the repository at this point in the history
* Don't try to copy local config if there's no sample

* Add configuration to skip frontend building for plugin-starter and other projects

* Use laravel config repository for config going forward, add skip fe build

* Skip fe build in bootstrapping if configured

* Update tests, add skip fe tests

* Bump to 5.4.0

* Add message when skipping fe building. Change message type to warnings instead of info
  • Loading branch information
defunctl authored Nov 17, 2021
1 parent 1a6beb4 commit 4f31810
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 41 deletions.
13 changes: 9 additions & 4 deletions app/Commands/LocalDocker/Bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Bootstrap extends BaseLocalDocker {
*
* @return int
*/
public function handle( Config $config, ProjectBootstrapper $bootstrapper ) {
public function handle( Config $config, ProjectBootstrapper $bootstrapper ): int {
Artisan::call( GlobalStart::class, [], $this->output );

$this->info( 'Alright, let\'s get ready to configure WordPress!' );
Expand Down Expand Up @@ -122,12 +122,17 @@ public function bootstrap( Config $config, ProjectBootstrapper $bootstrapper ):

if ( ! $result ) {
// @codeCoverageIgnoreStart
$this->info( 'local-config.php already exists. Skipping...' );
$this->warn( 'local-config.php already exists or missing local-config-sample.php. Skipping.' );
// @codeCoverageIgnoreEnd
}

$bootstrapper->createLocalConfigJson( $projectRoot, $config->getProjectDomain() )
->buildFrontend( $projectRoot, $this->output );
$bootstrapper->createLocalConfigJson( $projectRoot, $config->getProjectDomain() );

if ( $config->skipFeBuild() ) {
$this->warn( 'Found build.skip-fe in squareone.yml. Skipping frontend building.' );
} else {
$bootstrapper->buildFrontend( $projectRoot, $this->output );
}
}

/**
Expand Down
4 changes: 0 additions & 4 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ public function register(): void {

$this->app->singleton( ResultRecorder::class );

$this->app->when( Config::class )
->needs( '$workdir' )
->give( config( 'squareone.docker.workdir' ) );

$this->app->singleton( Config::class );

$this->app->bind(
Expand Down
27 changes: 17 additions & 10 deletions app/Services/Docker/Local/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Services\Docker\Local;

use App\Contracts\Runner;
use Illuminate\Contracts\Config\Repository;
use RuntimeException;

/**
Expand Down Expand Up @@ -39,22 +40,19 @@ class Config {
protected $path = '';

/**
* The working directory in the docker container where the application
* files live.
*
* @var string
* @var \Illuminate\Contracts\Config\Repository
*/
protected $workdir = '';
protected $config;

/**
* Config constructor.
*
* @param \App\Contracts\Runner $runner
* @param string $workdir
* @param \App\Contracts\Runner $runner
* @param \Illuminate\Config\Repository $config
*/
public function __construct( Runner $runner, string $workdir ) {
public function __construct( Runner $runner, Repository $config ) {
$this->runner = $runner;
$this->workdir = $workdir;
$this->config = $config;
}

/**
Expand Down Expand Up @@ -202,7 +200,16 @@ public function getProjectUrl( string $tld = 'tribe', string $scheme = 'https' )
* @return string
*/
public function getWorkdir(): string {
return $this->workdir;
return $this->config->get( 'squareone.docker.workdir', '/application/www' );
}

/**
* Whether this project should skip frontend building when bootstrapping.
*
* @return bool
*/
public function skipFeBuild(): bool {
return $this->config->get( 'squareone.build.skip-fe', false );
}

}
2 changes: 1 addition & 1 deletion app/Services/ProjectBootstrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public function createLocalConfig( string $projectRoot ): bool {
$sample = $projectRoot . '/local-config-sample.php';
$config = $projectRoot . '/local-config.php';

if ( $this->filesystem->exists( $config ) ) {
if ( $this->filesystem->exists( $config ) || $this->filesystem->missing( $sample ) ) {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*/

//'version' => app('git.version'),
'version' => '5.3.1',
'version' => '5.4.0',

/*
|--------------------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions config/squareone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ local-docker:
# path to the composer auth file (relative to the docker directory)
composer-auth: "composer/auth.json"

# Build options for this project
build:
# Skip building frontend with "so bootstrap"
skip-fe: false

# Global Command Options
options:
project-path:
Expand Down
96 changes: 96 additions & 0 deletions tests/Feature/Commands/LocalDocker/BootstrapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public function test_it_bootstraps_a_project() {
$this->config->shouldReceive( 'getComposeFile' )->andReturn( $this->composeFile );
$this->config->shouldReceive( 'getProjectDomain' )->andReturn( 'squareone.tribe' );
$this->config->shouldReceive( 'getProjectUrl' )->andReturn( 'https://squareone.tribe' );
$this->config->shouldReceive( 'skipFeBuild' )->andReturnFalse();

$this->runner->shouldReceive( 'run' )
->with( 'docker run --privileged --rm phpdockerio/php7-fpm date -s "$(date -u "+%Y-%m-%d %H:%M:%S")"' )
Expand Down Expand Up @@ -149,6 +150,100 @@ public function test_it_bootstraps_a_project() {
$this->assertSame( '"proxy": "squareone.tribe", "certs_path": "/home/test/.config/squareone/global/certs"', file_get_contents( storage_path( 'tests/local-config.json' ) ) );
}

public function test_it_bootstraps_a_project_and_skips_frontend_building() {
Artisan::swap( $this->artisan );

$this->artisan->shouldReceive( 'call' )
->once()
->with( GlobalStart::class, [], OutputStyle::class );

$this->healthChecker->shouldReceive( 'healthy' )->once()->andReturnTrue();

$this->config->shouldReceive( 'getProjectName' )->andReturn( 'squareone' );
$this->config->shouldReceive( 'getProjectRoot' )->andReturn( storage_path( 'tests' ) );
$this->config->shouldReceive( 'getComposerVolume' )->andReturn( storage_path( 'tests/dev/docker/composer' ) );
$this->config->shouldReceive( 'getComposeFile' )->andReturn( $this->composeFile );
$this->config->shouldReceive( 'getProjectDomain' )->andReturn( 'squareone.tribe' );
$this->config->shouldReceive( 'getProjectUrl' )->andReturn( 'https://squareone.tribe' );

// Skip frontend building
$this->config->shouldReceive( 'skipFeBuild' )->andReturnTrue();

$this->runner->shouldReceive( 'run' )
->with( 'docker run --privileged --rm phpdockerio/php7-fpm date -s "$(date -u "+%Y-%m-%d %H:%M:%S")"' )
->andReturnSelf();
$this->runner->shouldReceive( 'throw' )->andReturnSelf();

$this->artisan->shouldReceive( 'call' )
->once()
->with( Start::class, [ '--skip-global' => true ], OutputStyle::class );

$this->runner->shouldReceive( 'run' )
->once()
->with( 'docker exec -i tribe-mysql mysql -uroot -ppassword -e "CREATE DATABASE tribe_squareone;"' )
->andReturnSelf();

$this->runner->shouldReceive( 'run' )
->once()
->with( 'docker exec -i tribe-mysql mysql -uroot -ppassword -e "CREATE DATABASE tribe_squareone_tests; CREATE DATABASE tribe_squareone_acceptance;"' )
->andReturnSelf();

$this->artisan->shouldReceive( 'call' )
->once()
->with( Wp::class, [
'args' => [
'core',
'install',
'--url' => 'squareone.tribe',
'--title' => 'Square One',
'--admin_email' => '[email protected]',
'--admin_user' => 'admin',
'--admin_password' => 'test',
'--skip-email',
],
] );

$this->artisan->shouldReceive( 'call' )
->once()
->with( Wp::class, [
'args' => [
'rewrite',
'structure',
'/%postname%/',
],
] );

$this->artisan->shouldReceive( 'call' )
->once()
->with( Open::class, [
'url' => 'https://squareone.tribe',
] );

$this->homedir->shouldReceive( 'get' )->once()->andReturn( '/home/test' );

$command = $this->app->make( Bootstrap::class );

$tester = $this->runCommand( $command, [], [
'Enter your email address' => '[email protected]',
'Enter your admin username' => 'admin',
'Enter your password' => 'test',
'Confirm your password' => 'test',
] );

$this->assertSame( BaseCommand::EXIT_SUCCESS, $tester->getStatusCode() );

$this->assertFileExists( storage_path( 'tests/wp-content/object-cache.php' ) );
$this->assertFileDoesNotExist( storage_path( 'tests/wp-content/object-cache.bak.php' ) );

$this->assertFileExists( storage_path( 'tests/local-config.php' ) );
$this->assertSame( "define( 'TRIBE_GLOMAR', false );", file_get_contents( storage_path( 'tests/local-config.php' ) ) );
$this->assertNotSame( "//define( 'TRIBE_GLOMAR', false );", file_get_contents( storage_path( 'tests/local-config.php' ) ) );

$this->assertFileExists( storage_path( 'tests/local-config.json') );
$this->assertSame( '"proxy": "squareone.tribe", "certs_path": "/home/test/.config/squareone/global/certs"', file_get_contents( storage_path( 'tests/local-config.json' ) ) );
}


public function test_it_bootstraps_a_multisite_project() {
Artisan::swap( $this->artisan );

Expand All @@ -164,6 +259,7 @@ public function test_it_bootstraps_a_multisite_project() {
$this->config->shouldReceive( 'getComposeFile' )->andReturn( $this->composeFile );
$this->config->shouldReceive( 'getProjectDomain' )->andReturn( 'squareone.tribe' );
$this->config->shouldReceive( 'getProjectUrl' )->andReturn( 'https://squareone.tribe' );
$this->config->shouldReceive( 'skipFeBuild' )->andReturnFalse();

$this->runner->shouldReceive( 'run' )
->with( 'docker run --privileged --rm phpdockerio/php7-fpm date -s "$(date -u "+%Y-%m-%d %H:%M:%S")"' )
Expand Down
15 changes: 9 additions & 6 deletions tests/Unit/Services/Docker/Local/ConfigExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@

namespace Tests\Unit\Services\Docker\Local;

use Tests\TestCase;
use RuntimeException;
use App\Runners\CommandRunner;
use phpmock\mockery\PHPMockery;
use App\Services\Docker\Local\Config;
use Illuminate\Config\Repository;
use Illuminate\Support\Facades\Storage;
use phpmock\mockery\PHPMockery;
use RuntimeException;
use Tests\TestCase;

class ConfigExceptionTest extends TestCase {
final class ConfigExceptionTest extends TestCase {

private $runner;
private $config;

protected function setUp(): void {
parent::setUp();

// Prevent Mockery from erroring out on Response::__call
error_reporting( 0 );

$this->runner = $this->mock( CommandRunner::class );
$this->runner = $this->mock( CommandRunner::class );
$this->config = $this->mock( Repository::class );
}

public function test_it_throws_exception_on_invalid_project_root() {
Expand All @@ -33,7 +36,7 @@ public function test_it_throws_exception_on_invalid_project_root() {
// Mock we already hit the operating system's root folder
PHPMockery::mock( 'App\Services\Docker\Local', 'getcwd' )->andReturn( '/' );

$config = new Config( $this->runner, '/application/www' );
$config = new Config( $this->runner, $this->config );

$config->getProjectRoot();
}
Expand Down
Loading

0 comments on commit 4f31810

Please sign in to comment.