Skip to content

Commit

Permalink
feat: add retry for installation
Browse files Browse the repository at this point in the history
  • Loading branch information
shyim committed Dec 13, 2024
1 parent dfdfa91 commit 8a4a22f
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 4 deletions.
59 changes: 57 additions & 2 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,62 @@ jobs:
run: ./vendor/bin/shopware-deployment-helper run

- name: Start Webserver
run: symfony server:start -d
run: symfony server:start -d --no-tls --allow-all-ip

- name: PayPal plugin should be installed
run: ./bin/console plugin:list | grep SwagPayPal

- name: Default Storefront should be available
run: curl -q --fail http://localhost:8000

installation-with-retry:
name: Install a Shopware Shop with Retry
runs-on: ubuntu-latest
env:
SHOPWARE_DEPLOYMENT_FORCE_REINSTALL: 1
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: symfony-cli

- name: Start Default MySQL
run: |
sudo mv /var/lib/mysql /var/lib/mysql-old
sudo mkdir /var/lib/mysql
sudo mount -t tmpfs tmpfs /var/lib/mysql -o size=1G
sudo -u mysql mysqld --datadir=/var/lib/mysql --default-time-zone=SYSTEM --initialize-insecure
sudo systemctl start mysql
- name: Create new Shopware Project
run: composer create-project shopware/production . --no-interaction

- name: Checkout
uses: actions/checkout@v4
with:
path: ./custom/plugins/deployment-helper

- name: Set fake version into deployment helper
run: composer -d custom/plugins/deployment-helper config version 999.9.9

- name: Install Deployment Helper
run: composer require --dev 'shopware/deployment-helper:*'

- name: Install PayPal
run: composer require 'swag/paypal:*'

- name: Install Shopware and kill it after some seconds
run: timeout 10 ./vendor/bin/shopware-deployment-helper run || true

- name: Retry the Installation
run: ./vendor/bin/shopware-deployment-helper run

- name: Ensure the admin user exists
run: ./bin/console user:list | grep [email protected]

- name: Start Webserver
run: symfony server:start -d --no-tls --allow-all-ip

- name: PayPal plugin should be installed
run: ./bin/console plugin:list | grep SwagPayPal
Expand Down Expand Up @@ -98,7 +153,7 @@ jobs:
run: ./vendor/bin/shopware-deployment-helper run

- name: Start Webserver
run: symfony server:start -d
run: symfony server:start -d --no-tls --allow-all-ip

- name: PayPal plugin should be installed
run: ./bin/console plugin:list | grep SwagPayPal
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: '${{ matrix.php }}'
tools: composer:2.8.3
coverage: xdebug

- name: Install dependencies
Expand Down
6 changes: 6 additions & 0 deletions src/Command/RunCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Shopware\Deployment\Command;

use Shopware\Deployment\Event\PostDeploy;
use Shopware\Deployment\Helper\EnvironmentHelper;
use Shopware\Deployment\Services\HookExecutor;
use Shopware\Deployment\Services\InstallationManager;
use Shopware\Deployment\Services\ShopwareState;
Expand Down Expand Up @@ -46,10 +47,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
skipThemeCompile: (bool) $input->getOption('skip-theme-compile'),
skipAssetsInstall: ((bool) $input->getOption('skip-asset-install') || (bool) $input->getOption('skip-assets-install')),
timeout: is_numeric($timeout) ? (float) $timeout : null,
forceReinstallation: EnvironmentHelper::getVariable('SHOPWARE_DEPLOYMENT_FORCE_REINSTALL', '0') === '1',
);

$installed = $this->state->isInstalled();

if ($config->forceReinstallation && $this->state->getPreviousVersion() === 'unknown') {
$installed = false;
}

$this->hookExecutor->execute(HookExecutor::HOOK_PRE);

if ($installed) {
Expand Down
7 changes: 6 additions & 1 deletion src/Services/InstallationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ public function run(RunConfiguration $configuration, OutputInterface $output): v
$additionalInstallParameters[] = '--skip-assets-install';
}

if ($configuration->forceReinstallation) {
$additionalInstallParameters[] = '--drop-database';
}

$this->processHelper->console(['system:install', '--create-database', '--shop-locale=' . $shopLocale, '--shop-currency=' . $shopCurrency, '--force', ...$additionalInstallParameters]);
$this->processHelper->console(['user:create', $adminUser, '--password=' . $adminPassword]);

Expand All @@ -76,7 +80,6 @@ public function run(RunConfiguration $configuration, OutputInterface $output): v
}

$this->state->disableFirstRunWizard();
$this->state->setVersion($this->state->getCurrentVersion());

$this->processHelper->console(['plugin:refresh']);
$this->pluginHelper->installPlugins($configuration->skipAssetsInstall);
Expand All @@ -93,6 +96,8 @@ public function run(RunConfiguration $configuration, OutputInterface $output): v
$this->appHelper->deactivateApps();
$this->appHelper->removeApps();

$this->state->setVersion($this->state->getCurrentVersion());

$this->hookExecutor->execute(HookExecutor::HOOK_POST_INSTALL);
}

Expand Down
6 changes: 5 additions & 1 deletion src/Services/ShopwareState.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ public function isStorefrontInstalled(): bool

public function getPreviousVersion(): string
{
$data = $this->connection->fetchOne('SELECT configuration_value FROM system_config WHERE configuration_key = "deployment.version" AND sales_channel_id IS NULL');
try {
$data = $this->connection->fetchOne('SELECT configuration_value FROM system_config WHERE configuration_key = "deployment.version" AND sales_channel_id IS NULL');
} catch (\Throwable) {
return 'unknown';
}

if ($data === false) {
return 'unknown';
Expand Down
1 change: 1 addition & 0 deletions src/Struct/RunConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public function __construct(
public bool $skipThemeCompile = false,
public bool $skipAssetsInstall = false,
public ?float $timeout = 60,
public bool $forceReinstallation = false,
) {
}
}
41 changes: 41 additions & 0 deletions tests/Command/RunCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Shopware\Deployment\Services\UpgradeManager;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Zalas\PHPUnit\Globals\Attribute\Env;

#[CoversClass(RunCommand::class)]
class RunCommandTest extends TestCase
Expand Down Expand Up @@ -101,4 +102,44 @@ public function testUpdate(): void
'--timeout' => 600,
]);
}

#[Env('SHOPWARE_DEPLOYMENT_FORCE_REINSTALL', '1')]
public function testRunWithoutFullyInstalled(): void
{
$state = $this->createMock(ShopwareState::class);
$state
->expects($this->once())
->method('isInstalled')
->willReturn(true);
$state
->expects($this->once())
->method('getPreviousVersion')
->willReturn('unknown');

$hookExecutor = $this->createMock(HookExecutor::class);
$hookExecutor
->expects($this->exactly(2))
->method('execute');

$installationManager = $this->createMock(InstallationManager::class);
$installationManager
->expects($this->once())
->method('run')
->with(self::callback(function ($config) {
static::assertTrue($config->forceReinstallation);

return true;
}));

$command = new RunCommand(
$state,
$installationManager,
$this->createMock(UpgradeManager::class),
$hookExecutor,
new EventDispatcher()
);

$tester = new CommandTester($command);
$tester->execute([]);
}
}
31 changes: 31 additions & 0 deletions tests/Services/InstallationManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,35 @@ public function testRunWithLicenseDomain(): void

$manager->run(new RunConfiguration(), $this->createMock(OutputInterface::class));
}

public function testRunWithForceReinstall(): void
{
$processHelper = $this->createMock(ProcessHelper::class);
$consoleCommands = [];

$processHelper
->method('console')
->willReturnCallback(function (array $command) use (&$consoleCommands): void {
$consoleCommands[] = $command;
});

$accountService = $this->createMock(AccountService::class);
$accountService->expects(static::never())->method('refresh');

$manager = new InstallationManager(
$this->createMock(ShopwareState::class),
$this->createMock(Connection::class),
$processHelper,
$this->createMock(PluginHelper::class),
$this->createMock(AppHelper::class),
$this->createMock(HookExecutor::class),
new ProjectConfiguration(),
$accountService,
);

$manager->run(new RunConfiguration(true, true, forceReinstallation: true), $this->createMock(OutputInterface::class));

static::assertCount(4, $consoleCommands);
static::assertSame(['system:install', '--create-database', '--shop-locale=en-GB', '--shop-currency=EUR', '--force', '--no-assign-theme', '--skip-assets-install', '--drop-database'], $consoleCommands[0]);
}
}
9 changes: 9 additions & 0 deletions tests/Services/ShopwareStateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public function testStorefrontInstalled(): void
InstalledVersions::reload($before);
}

public function testGetPreviousVersionTableDoesNotExistYet(): void
{
$this->connection
->expects($this->once())
->method('fetchOne')
->willThrowException(new \Exception());
static::assertSame('unknown', $this->state->getPreviousVersion());
}

public function testGetPreviousVersionNotExisting(): void
{
$this->connection
Expand Down

0 comments on commit 8a4a22f

Please sign in to comment.