From 78aba16084f1476af294f8d47529ecb4f64f0576 Mon Sep 17 00:00:00 2001 From: Anton Evers Date: Fri, 21 Apr 2017 11:27:57 +0200 Subject: [PATCH 1/7] Make deployed_version.txt editor friendly In production environments with a CDN for static files it comes in handy that you can force a browser cache refresh by changing the number manually without having to go into maintenance for a full deploy. If you edit the `pub/static/deployed_version.txt` with vim, nano or `echo '123456789' > pub/static/deployed_version.txt` you can unintentionally create a newline at the end of the file. This will result in: ```html var BASE_URL = 'https://magento2.dev/sitemanager/admin/index/index/key/ec38dd3ded42b71db14166d6bcdfc56d4e7d4b7801b9808373ae4b3563b65513/'; var FORM_KEY = 'dKArsQU6NhimXr6Z'; var require = { "baseUrl": "https://magento2.dev/pub/static/version1492766286 /adminhtml/Magento/backend/en_US" }; ``` With that baseUrl all resources using baseUrl will return the 404 page. Adding a simple `trim()` here will remove that risk. --- .../Framework/App/View/Deployment/Version/Storage/File.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php b/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php index 8099b6864b3a1..21dc6dd1fc214 100644 --- a/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php +++ b/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php @@ -41,7 +41,7 @@ public function __construct( public function load() { if ($this->directory->isReadable($this->fileName)) { - return $this->directory->readFile($this->fileName); + return trim($this->directory->readFile($this->fileName)); } return false; } From 89e006754b6e8811a972e9b70c4a0e1868cfbc5f Mon Sep 17 00:00:00 2001 From: Anton Evers Date: Sun, 11 Jun 2017 13:04:01 +0600 Subject: [PATCH 2/7] PATCH-1 Revert "Make deployed_version.txt editor friendly" This reverts commit 78aba16084f1476af294f8d47529ecb4f64f0576. --- .../Framework/App/View/Deployment/Version/Storage/File.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php b/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php index 21dc6dd1fc214..8099b6864b3a1 100644 --- a/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php +++ b/lib/internal/Magento/Framework/App/View/Deployment/Version/Storage/File.php @@ -41,7 +41,7 @@ public function __construct( public function load() { if ($this->directory->isReadable($this->fileName)) { - return trim($this->directory->readFile($this->fileName)); + return $this->directory->readFile($this->fileName); } return false; } From 17a44e252ee0ffabf2362cafb3031b7379f142ba Mon Sep 17 00:00:00 2001 From: Anton Evers Date: Sun, 11 Jun 2017 13:04:26 +0600 Subject: [PATCH 3/7] Add --refresh-content-version-only option to deploy With this option you can quickly force a browser cache refresh or a CDN cache refresh without having to generate all static content. This comes in handy especially when you have made no code changes, but the CDN failed to update it's cache the last time you deployed or when you have made a manual change in one of the static files as a hotfix on your deployment server, awaiting a suitable moment for deployment to finalize it. This reopens #9338. --- .../Deploy/Console/DeployStaticOptions.php | 12 ++++++++++++ .../Deploy/Service/DeployStaticContent.php | 15 ++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Deploy/Console/DeployStaticOptions.php b/app/code/Magento/Deploy/Console/DeployStaticOptions.php index 7bf522f7ca355..9a73dd5d65fc7 100644 --- a/app/code/Magento/Deploy/Console/DeployStaticOptions.php +++ b/app/code/Magento/Deploy/Console/DeployStaticOptions.php @@ -131,6 +131,11 @@ class DeployStaticOptions */ const CONTENT_VERSION = 'content-version'; + /** + * Key for refresh content version only mode + */ + const REFRESH_CONTENT_VERSION_ONLY = 'refresh-content-version-only'; + /** * Deploy static command options list * @@ -225,6 +230,13 @@ private function getBasicOptions() 'Custom version of static content can be used if running deployment on multiple nodes ' . 'to ensure that static content version is identical and caching works properly.' ), + new InputOption( + self::REFRESH_CONTENT_VERSION_ONLY, + null, + InputOption::VALUE_NONE, + 'Refreshing the version of static content only can be used to refresh static content ' + . 'in browser cache and CDN cache.' + ), new InputArgument( self::LANGUAGES_ARGUMENT, InputArgument::IS_ARRAY, diff --git a/app/code/Magento/Deploy/Service/DeployStaticContent.php b/app/code/Magento/Deploy/Service/DeployStaticContent.php index 5f087ca6bb7ff..092321146734d 100644 --- a/app/code/Magento/Deploy/Service/DeployStaticContent.php +++ b/app/code/Magento/Deploy/Service/DeployStaticContent.php @@ -75,6 +75,16 @@ public function __construct( */ public function deploy(array $options) { + $version = !empty($options[Options::CONTENT_VERSION]) && is_string($options[Options::CONTENT_VERSION]) + ? $options[Options::CONTENT_VERSION] + : (new \DateTime())->getTimestamp(); + $this->versionStorage->save($version); + + if ($options[Options::REFRESH_CONTENT_VERSION_ONLY]) { + $this->logger->warning(PHP_EOL . "New content version: " . $version); + return; + } + $queue = $this->queueFactory->create( [ 'logger' => $this->logger, @@ -96,11 +106,6 @@ public function deploy(array $options) ] ); - $version = !empty($options[Options::CONTENT_VERSION]) && is_string($options[Options::CONTENT_VERSION]) - ? $options[Options::CONTENT_VERSION] - : (new \DateTime())->getTimestamp(); - $this->versionStorage->save($version); - $packages = $deployStrategy->deploy($options); if ($options[Options::NO_JAVASCRIPT] !== true) { From fbc9db37d12889637f1b7cfe5fdfebb0e56133f6 Mon Sep 17 00:00:00 2001 From: Anton Evers Date: Tue, 13 Jun 2017 10:15:23 +0600 Subject: [PATCH 4/7] Add unit tests --- .../Deploy/Service/DeployStaticContent.php | 13 ++- .../Unit/Service/DeployStaticContentTest.php | 104 +++++++++++------- 2 files changed, 78 insertions(+), 39 deletions(-) diff --git a/app/code/Magento/Deploy/Service/DeployStaticContent.php b/app/code/Magento/Deploy/Service/DeployStaticContent.php index 092321146734d..2b58751bb695f 100644 --- a/app/code/Magento/Deploy/Service/DeployStaticContent.php +++ b/app/code/Magento/Deploy/Service/DeployStaticContent.php @@ -80,7 +80,7 @@ public function deploy(array $options) : (new \DateTime())->getTimestamp(); $this->versionStorage->save($version); - if ($options[Options::REFRESH_CONTENT_VERSION_ONLY]) { + if ($this->getRefreshContentVersionOnly($options)) { $this->logger->warning(PHP_EOL . "New content version: " . $version); return; } @@ -140,4 +140,15 @@ private function getProcessesAmount(array $options) { return isset($options[Options::JOBS_AMOUNT]) ? (int)$options[Options::JOBS_AMOUNT] : 0; } + + /** + * @param array $options + * @return bool + */ + private function getRefreshContentVersionOnly(array $options) + { + return isset($options[Options::REFRESH_CONTENT_VERSION_ONLY]) + ? (bool)$options[Options::REFRESH_CONTENT_VERSION_ONLY] + : false; + } } diff --git a/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php b/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php index 04bfea068cabb..c42d503206b03 100644 --- a/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php @@ -114,11 +114,17 @@ protected function setUp() public function testDeploy($options, $expectedContentVersion) { $package = $this->getMock(Package::class, [], [], '', false); - $package->expects($this->exactly(1))->method('isVirtual')->willReturn(false); - $package->expects($this->exactly(3))->method('getArea')->willReturn('area'); - $package->expects($this->exactly(3))->method('getTheme')->willReturn('theme'); - $package->expects($this->exactly(2))->method('getLocale')->willReturn('locale'); - + if ($options['refresh-content-version-only']) { + $package->expects($this->never())->method('isVirtual'); + $package->expects($this->never())->method('getArea'); + $package->expects($this->never())->method('getTheme'); + $package->expects($this->never())->method('getLocale'); + } else { + $package->expects($this->exactly(1))->method('isVirtual')->willReturn(false); + $package->expects($this->exactly(3))->method('getArea')->willReturn('area'); + $package->expects($this->exactly(3))->method('getTheme')->willReturn('theme'); + $package->expects($this->exactly(2))->method('getLocale')->willReturn('locale'); + } $packages = [ 'package' => $package ]; @@ -132,20 +138,28 @@ public function testDeploy($options, $expectedContentVersion) $queue = $this->getMockBuilder(Queue::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $this->queueFactory->expects($this->once())->method('create')->willReturn($queue); + if ($options['refresh-content-version-only']) { + $this->queueFactory->expects($this->never())->method('create'); + } else { + $this->queueFactory->expects($this->once())->method('create')->willReturn($queue); + } $strategy = $this->getMockBuilder(CompactDeploy::class) ->setMethods(['deploy']) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $strategy->expects($this->once())->method('deploy') - ->with($options) - ->willReturn($packages); - $this->deployStrategyFactory->expects($this->once()) - ->method('create') - ->with('compact', ['queue' => $queue]) - ->willReturn($strategy); - + if ($options['refresh-content-version-only']) { + $strategy->expects($this->never())->method('deploy'); + $this->deployStrategyFactory->expects($this->never())->method('create'); + } else { + $strategy->expects($this->once())->method('deploy') + ->with($options) + ->willReturn($packages); + $this->deployStrategyFactory->expects($this->once()) + ->method('create') + ->with('compact', ['queue' => $queue]) + ->willReturn($strategy); + } $deployPackageService = $this->getMockBuilder(DeployPackage::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); @@ -166,29 +180,34 @@ public function testDeploy($options, $expectedContentVersion) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $this->objectManager->expects($this->exactly(4)) - ->method('create') - ->withConsecutive( - [DeployPackage::class, ['logger' => $this->logger]], - [DeployRequireJsConfig::class, ['logger' => $this->logger]], - [DeployTranslationsDictionary::class, ['logger' => $this->logger]], - [Bundle::class, ['logger' => $this->logger]] - ) - ->willReturnOnConsecutiveCalls( - $deployPackageService, - $deployRjsConfig, - $deployI18n, - $deployBundle - ); - - $this->objectManager->expects($this->exactly(1)) - ->method('get') - ->withConsecutive( - [MinifyTemplates::class] - ) - ->willReturnOnConsecutiveCalls( - $minifyTemplates - ); + if ($options['refresh-content-version-only']) { + $this->objectManager->expects($this->never())->method('create'); + $this->objectManager->expects($this->never())->method('get'); + } else { + $this->objectManager->expects($this->exactly(4)) + ->method('create') + ->withConsecutive( + [DeployPackage::class, ['logger' => $this->logger]], + [DeployRequireJsConfig::class, ['logger' => $this->logger]], + [DeployTranslationsDictionary::class, ['logger' => $this->logger]], + [Bundle::class, ['logger' => $this->logger]] + ) + ->willReturnOnConsecutiveCalls( + $deployPackageService, + $deployRjsConfig, + $deployI18n, + $deployBundle + ); + + $this->objectManager->expects($this->exactly(1)) + ->method('get') + ->withConsecutive( + [MinifyTemplates::class] + ) + ->willReturnOnConsecutiveCalls( + $minifyTemplates + ); + } $this->assertEquals( null, @@ -203,7 +222,8 @@ public function deployDataProvider() [ 'strategy' => 'compact', 'no-javascript' => false, - 'no-html-minify' => false + 'no-html-minify' => false, + 'refresh-content-version-only' => false, ], null // content version value should not be asserted in this case ], @@ -212,9 +232,17 @@ public function deployDataProvider() 'strategy' => 'compact', 'no-javascript' => false, 'no-html-minify' => false, + 'refresh-content-version-only' => false, 'content-version' => '123456', ], '123456' + ], + [ + [ + 'refresh-content-version-only' => true, + 'content-version' => '654321', + ], + '654321' ] ]; } From 4499b6f444b87e18950ee9eb8df243e047f6f916 Mon Sep 17 00:00:00 2001 From: Anton Evers Date: Tue, 13 Jun 2017 10:36:50 +0600 Subject: [PATCH 5/7] Don't display deploy strategy and execution time when only changeing the version number --- .../Magento/Deploy/Service/DeployStaticContent.php | 5 ++--- .../Console/Command/DeployStaticContentCommand.php | 10 ++++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Deploy/Service/DeployStaticContent.php b/app/code/Magento/Deploy/Service/DeployStaticContent.php index 2b58751bb695f..e70c4ca30152f 100644 --- a/app/code/Magento/Deploy/Service/DeployStaticContent.php +++ b/app/code/Magento/Deploy/Service/DeployStaticContent.php @@ -81,7 +81,7 @@ public function deploy(array $options) $this->versionStorage->save($version); if ($this->getRefreshContentVersionOnly($options)) { - $this->logger->warning(PHP_EOL . "New content version: " . $version); + $this->logger->warning("New content version: " . $version); return; } @@ -148,7 +148,6 @@ private function getProcessesAmount(array $options) private function getRefreshContentVersionOnly(array $options) { return isset($options[Options::REFRESH_CONTENT_VERSION_ONLY]) - ? (bool)$options[Options::REFRESH_CONTENT_VERSION_ONLY] - : false; + && $options[Options::REFRESH_CONTENT_VERSION_ONLY]; } } diff --git a/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php b/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php index d2a0ddce1b422..4217c9ea5c650 100644 --- a/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php +++ b/setup/src/Magento/Setup/Console/Command/DeployStaticContentCommand.php @@ -120,11 +120,15 @@ protected function execute(InputInterface $input, OutputInterface $output) $options = $input->getOptions(); $options[Options::LANGUAGE] = $input->getArgument(Options::LANGUAGES_ARGUMENT) ?: ['all']; + $refreshOnly = isset($options[Options::REFRESH_CONTENT_VERSION_ONLY]) + && $options[Options::REFRESH_CONTENT_VERSION_ONLY]; $verbose = $output->getVerbosity() > 1 ? $output->getVerbosity() : OutputInterface::VERBOSITY_VERBOSE; $logger = $this->consoleLoggerFactory->getLogger($output, $verbose); - $logger->alert(PHP_EOL . "Deploy using {$options[Options::STRATEGY]} strategy"); + if (!$refreshOnly) { + $logger->alert(PHP_EOL . "Deploy using {$options[Options::STRATEGY]} strategy"); + } $this->mockCache(); @@ -135,7 +139,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $deployService->deploy($options); - $logger->alert(PHP_EOL . "Execution time: " . (microtime(true) - $time)); + if (!$refreshOnly) { + $logger->alert(PHP_EOL . "Execution time: " . (microtime(true) - $time)); + } return \Magento\Framework\Console\Cli::RETURN_SUCCESS; } From cc8e8fd488d48cc747907e3b44c4644344d33adf Mon Sep 17 00:00:00 2001 From: Anton Evers Date: Tue, 13 Jun 2017 11:14:59 +0600 Subject: [PATCH 6/7] Fix phpmd test failure, rename method from get to is --- app/code/Magento/Deploy/Service/DeployStaticContent.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Deploy/Service/DeployStaticContent.php b/app/code/Magento/Deploy/Service/DeployStaticContent.php index e70c4ca30152f..092e4b0fc238d 100644 --- a/app/code/Magento/Deploy/Service/DeployStaticContent.php +++ b/app/code/Magento/Deploy/Service/DeployStaticContent.php @@ -80,7 +80,7 @@ public function deploy(array $options) : (new \DateTime())->getTimestamp(); $this->versionStorage->save($version); - if ($this->getRefreshContentVersionOnly($options)) { + if ($this->isRefreshContentVersionOnly($options)) { $this->logger->warning("New content version: " . $version); return; } @@ -145,7 +145,7 @@ private function getProcessesAmount(array $options) * @param array $options * @return bool */ - private function getRefreshContentVersionOnly(array $options) + private function isRefreshContentVersionOnly(array $options) { return isset($options[Options::REFRESH_CONTENT_VERSION_ONLY]) && $options[Options::REFRESH_CONTENT_VERSION_ONLY]; From 9de25f59b9de4757e42e26e1479da22668224ff6 Mon Sep 17 00:00:00 2001 From: Anton Evers Date: Tue, 13 Jun 2017 11:25:04 +0600 Subject: [PATCH 7/7] Shorten DeployStaticContentTest::testDeploy to be within 100 lines --- .../Unit/Service/DeployStaticContentTest.php | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php b/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php index c42d503206b03..3d263c7a0a69f 100644 --- a/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Service/DeployStaticContentTest.php @@ -125,9 +125,7 @@ public function testDeploy($options, $expectedContentVersion) $package->expects($this->exactly(3))->method('getTheme')->willReturn('theme'); $package->expects($this->exactly(2))->method('getLocale')->willReturn('locale'); } - $packages = [ - 'package' => $package - ]; + $packages = ['package' => $package]; if ($expectedContentVersion) { $this->versionStorage->expects($this->once())->method('save')->with($expectedContentVersion); @@ -150,7 +148,6 @@ public function testDeploy($options, $expectedContentVersion) ->getMockForAbstractClass(); if ($options['refresh-content-version-only']) { $strategy->expects($this->never())->method('deploy'); - $this->deployStrategyFactory->expects($this->never())->method('create'); } else { $strategy->expects($this->once())->method('deploy') ->with($options) @@ -201,18 +198,11 @@ public function testDeploy($options, $expectedContentVersion) $this->objectManager->expects($this->exactly(1)) ->method('get') - ->withConsecutive( - [MinifyTemplates::class] - ) - ->willReturnOnConsecutiveCalls( - $minifyTemplates - ); + ->withConsecutive([MinifyTemplates::class]) + ->willReturnOnConsecutiveCalls($minifyTemplates); } - $this->assertEquals( - null, - $this->service->deploy($options) - ); + $this->assertEquals(null, $this->service->deploy($options)); } public function deployDataProvider()