Skip to content

Commit 3c9ed6e

Browse files
MC-36231: setup:static-content:deploy exits with success exit code even if not all themes are deployed
1 parent 31b939f commit 3c9ed6e

File tree

4 files changed

+124
-46
lines changed

4 files changed

+124
-46
lines changed

app/code/Magento/Deploy/Process/Queue.php

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class Queue
2929
/**
3030
* Default max execution time
3131
*/
32-
const DEFAULT_MAX_EXEC_TIME = 400;
32+
const DEFAULT_MAX_EXEC_TIME = 900;
3333

3434
/**
3535
* @var array
@@ -96,6 +96,11 @@ class Queue
9696
*/
9797
private $lastJobStarted = 0;
9898

99+
/**
100+
* @var int
101+
*/
102+
private $logDelay;
103+
99104
/**
100105
* @param AppState $appState
101106
* @param LocaleResolver $localeResolver
@@ -157,11 +162,12 @@ public function getPackages()
157162
* Process jobs
158163
*
159164
* @return int
165+
* @throws TimeoutException
160166
*/
161167
public function process()
162168
{
163169
$returnStatus = 0;
164-
$logDelay = 10;
170+
$this->logDelay = 10;
165171
$this->start = $this->lastJobStarted = time();
166172
$packages = $this->packages;
167173
while (count($packages) && $this->checkTimeout()) {
@@ -170,13 +176,7 @@ public function process()
170176
$this->assertAndExecute($name, $packages, $packageJob);
171177
}
172178

173-
// refresh current status in console once in 10 iterations (once in 5 sec)
174-
if ($logDelay >= 10) {
175-
$this->logger->info('.');
176-
$logDelay = 0;
177-
} else {
178-
$logDelay++;
179-
}
179+
$this->refreshStatus();
180180

181181
if ($this->isCanBeParalleled()) {
182182
// in parallel mode sleep before trying to check status and run new jobs
@@ -193,9 +193,28 @@ public function process()
193193

194194
$this->awaitForAllProcesses();
195195

196+
if (!empty($packages)) {
197+
throw new TimeoutException('Not all packages are deployed.');
198+
}
199+
196200
return $returnStatus;
197201
}
198202

203+
/**
204+
* Refresh current status in console once in 10 iterations (once in 5 sec)
205+
*
206+
* @return void
207+
*/
208+
private function refreshStatus(): void
209+
{
210+
if ($this->logDelay >= 10) {
211+
$this->logger->info('.');
212+
$this->logDelay = 0;
213+
} else {
214+
$this->logDelay++;
215+
}
216+
}
217+
199218
/**
200219
* Check that all depended packages deployed and execute
201220
*
@@ -204,7 +223,7 @@ public function process()
204223
* @param array $packageJob
205224
* @return void
206225
*/
207-
private function assertAndExecute($name, array & $packages, array $packageJob)
226+
private function assertAndExecute($name, array &$packages, array $packageJob)
208227
{
209228
/** @var Package $package */
210229
$package = $packageJob['package'];
@@ -256,21 +275,14 @@ private function executePackage(Package $package, string $name, array &$packages
256275
*/
257276
private function awaitForAllProcesses()
258277
{
259-
$logDelay = 10;
260278
while ($this->inProgress && $this->checkTimeout()) {
261279
foreach ($this->inProgress as $name => $package) {
262280
if ($this->isDeployed($package)) {
263281
unset($this->inProgress[$name]);
264282
}
265283
}
266284

267-
// refresh current status in console once in 10 iterations (once in 5 sec)
268-
if ($logDelay >= 10) {
269-
$this->logger->info('.');
270-
$logDelay = 0;
271-
} else {
272-
$logDelay++;
273-
}
285+
$this->refreshStatus();
274286

275287
// sleep before checking parallel jobs status
276288
// phpcs:ignore Magento2.Functions.DiscouragedFunction
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Deploy\Process;
9+
10+
/**
11+
* Exception is thrown if deploy process is finished due to timeout.
12+
*/
13+
class TimeoutException extends \RuntimeException
14+
{
15+
}

setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use Magento\Deploy\Console\ConsoleLoggerFactory;
1010
use Magento\Deploy\Console\DeployStaticOptions as Options;
1111
use Magento\Framework\App\State;
12+
use Magento\Framework\Console\Cli;
13+
use Psr\Log\LogLevel;
1214
use Symfony\Component\Console\Command\Command;
1315
use Symfony\Component\Console\Input\InputInterface;
1416
use Symfony\Component\Console\Output\OutputInterface;
@@ -55,16 +57,16 @@ class DeployStaticContentCommand extends Command
5557
private $objectManager;
5658

5759
/**
58-
* @var \Magento\Framework\App\State
60+
* @var State
5961
*/
6062
private $appState;
6163

6264
/**
6365
* StaticContentCommand constructor
6466
*
65-
* @param InputValidator $inputValidator
66-
* @param ConsoleLoggerFactory $consoleLoggerFactory
67-
* @param Options $options
67+
* @param InputValidator $inputValidator
68+
* @param ConsoleLoggerFactory $consoleLoggerFactory
69+
* @param Options $options
6870
* @param ObjectManagerProvider $objectManagerProvider
6971
*/
7072
public function __construct(
@@ -107,18 +109,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
107109
{
108110
$time = microtime(true);
109111

110-
if (!$input->getOption(Options::FORCE_RUN) && $this->getAppState()->getMode() !== State::MODE_PRODUCTION) {
111-
throw new LocalizedException(
112-
__(
113-
'NOTE: Manual static content deployment is not required in "default" and "developer" modes.'
114-
. PHP_EOL . 'In "default" and "developer" modes static contents are being deployed '
115-
. 'automatically on demand.'
116-
. PHP_EOL . 'If you still want to deploy in these modes, use -f option: '
117-
. "'bin/magento setup:static-content:deploy -f'"
118-
)
119-
);
120-
}
121-
112+
$this->checkAppMode($input);
122113
$this->inputValidator->validate($input);
123114

124115
$options = $input->getOptions();
@@ -136,18 +127,44 @@ protected function execute(InputInterface $input, OutputInterface $output)
136127

137128
$this->mockCache();
138129

139-
/** @var DeployStaticContent $deployService */
140-
$deployService = $this->objectManager->create(DeployStaticContent::class, [
141-
'logger' => $logger
142-
]);
143-
144-
$deployService->deploy($options);
130+
$exitCode = Cli::RETURN_SUCCESS;
131+
try {
132+
/** @var DeployStaticContent $deployService */
133+
$deployService = $this->objectManager->create(DeployStaticContent::class, [
134+
'logger' => $logger
135+
]);
136+
$deployService->deploy($options);
137+
} catch (\Throwable $e) {
138+
$logger->error('Error happened during deploy process: ' . $e->getMessage());
139+
$exitCode = Cli::RETURN_FAILURE;
140+
}
145141

146142
if (!$refreshOnly) {
147143
$logger->notice(PHP_EOL . "Execution time: " . (microtime(true) - $time));
148144
}
149145

150-
return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
146+
return $exitCode;
147+
}
148+
149+
/**
150+
* Check application mode
151+
*
152+
* @param InputInterface $input
153+
* @throws LocalizedException
154+
*/
155+
private function checkAppMode(InputInterface $input): void
156+
{
157+
if (!$input->getOption(Options::FORCE_RUN) && $this->getAppState()->getMode() !== State::MODE_PRODUCTION) {
158+
throw new LocalizedException(
159+
__(
160+
'NOTE: Manual static content deployment is not required in "default" and "developer" modes.'
161+
. PHP_EOL . 'In "default" and "developer" modes static contents are being deployed '
162+
. 'automatically on demand.'
163+
. PHP_EOL . 'If you still want to deploy in these modes, use -f option: '
164+
. "'bin/magento setup:static-content:deploy -f'"
165+
)
166+
);
167+
}
151168
}
152169

153170
/**

setup/src/Magento/Setup/Test/Unit/Console/Command/DeployStaticContentCommandTest.php

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,24 @@
1010
use Magento\Deploy\Console\ConsoleLogger;
1111
use Magento\Deploy\Console\ConsoleLoggerFactory;
1212
use Magento\Deploy\Console\DeployStaticOptions;
13-
1413
use Magento\Deploy\Console\InputValidator;
14+
use Magento\Deploy\Process\TimeoutException;
1515
use Magento\Deploy\Service\DeployStaticContent;
1616
use Magento\Framework\App\State;
17+
use Magento\Framework\Console\Cli;
1718
use Magento\Framework\ObjectManagerInterface;
1819
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
19-
2020
use Magento\Setup\Console\Command\DeployStaticContentCommand;
2121
use Magento\Setup\Model\ObjectManagerProvider;
2222
use PHPUnit\Framework\MockObject\MockObject as Mock;
23-
2423
use PHPUnit\Framework\TestCase;
25-
2624
use Symfony\Component\Console\Tester\CommandTester;
2725

26+
/**
27+
* Test for static content deploy command
28+
*
29+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
30+
*/
2831
class DeployStaticContentCommandTest extends TestCase
2932
{
3033
/**
@@ -111,7 +114,8 @@ public function testExecute($input)
111114
$this->deployService->expects($this->once())->method('deploy');
112115

113116
$tester = new CommandTester($this->command);
114-
$tester->execute($input);
117+
$exitCode = $tester->execute($input);
118+
$this->assertEquals(Cli::RETURN_SUCCESS, $exitCode);
115119
}
116120

117121
/**
@@ -129,6 +133,36 @@ public function executeDataProvider()
129133
];
130134
}
131135

136+
/**
137+
* @return void
138+
*/
139+
public function testExecuteWithError()
140+
{
141+
$this->appState->expects($this->once())
142+
->method('getMode')
143+
->willReturn(State::MODE_PRODUCTION);
144+
145+
$this->inputValidator->expects($this->once())
146+
->method('validate');
147+
148+
$this->consoleLoggerFactory->expects($this->once())
149+
->method('getLogger')
150+
->willReturn($this->logger);
151+
$this->logger->expects($this->once())
152+
->method('error');
153+
154+
$this->objectManager->expects($this->once())
155+
->method('create')
156+
->willReturn($this->deployService);
157+
$this->deployService->expects($this->once())
158+
->method('deploy')
159+
->willThrowException(new TimeoutException());
160+
161+
$tester = new CommandTester($this->command);
162+
$exitCode = $tester->execute([]);
163+
$this->assertEquals(Cli::RETURN_FAILURE, $exitCode);
164+
}
165+
132166
/**
133167
* @param string $mode
134168
* @return void

0 commit comments

Comments
 (0)