From e5e70dd87ef26aff2d49d1d56e14a4205e26a9c6 Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Wed, 7 Oct 2020 08:38:58 -0500 Subject: [PATCH 1/7] Refactor code to use composer autoload with psr4 - Add namespace to classes - Use composer autoload to load files --- app/autoload.php | 11 ++++++++ app/bootstrap.php | 2 ++ app/code/Cache/File.php | 11 ++++++-- app/code/Deploy/Instance.php | 9 ++++++- app/code/Deploy/InstanceManager.php | 11 +++++--- app/code/Design.php | 11 ++++++-- app/code/File/Filesystem.php | 7 ++++++ app/code/File/Uploader.php | 14 ++++++++--- .../Patch/Check/Strategy/AbstractStrategy.php | 13 ++++++++-- .../Patch/Check/Strategy/GitApplyStrategy.php | 7 ++++++ .../Patch/Check/Strategy/PatchStrategy.php | 7 ++++++ .../Check/Strategy/StrategyInterface.php | 7 ++++++ app/code/Patch/Check/StrategyManager.php | 14 ++++++++--- app/code/Patch/Checker.php | 25 ++++++++++++------- app/code/Patch/Converter.php | 11 ++++++-- composer.json | 6 +++++ index.php | 9 +++---- 17 files changed, 141 insertions(+), 34 deletions(-) create mode 100644 app/autoload.php diff --git a/app/autoload.php b/app/autoload.php new file mode 100644 index 0000000..2256f74 --- /dev/null +++ b/app/autoload.php @@ -0,0 +1,11 @@ +validateWritablePath($cachePath)) { - throw new Exception('Cache dir is not writable.'); + throw new \Exception('Cache dir is not writable.'); } } } diff --git a/app/code/Deploy/Instance.php b/app/code/Deploy/Instance.php index 1a840ee..67c632e 100644 --- a/app/code/Deploy/Instance.php +++ b/app/code/Deploy/Instance.php @@ -1,6 +1,13 @@ $instancePath) { $this->instanceList[$groupName][] = is_int($instancePath) ? $instancePath - : new Deploy_Instance($instanceName, $instancePath); + : new Instance($instanceName, $instancePath); } } diff --git a/app/code/Design.php b/app/code/Design.php index 7342523..af355cd 100644 --- a/app/code/Design.php +++ b/app/code/Design.php @@ -1,6 +1,13 @@ loadCache(self::STATIC_HASH_CACHE_ID); if (!$content) { $content = $this->generateStaticHash(); diff --git a/app/code/File/Filesystem.php b/app/code/File/Filesystem.php index 495cbbe..48ba244 100644 --- a/app/code/File/Filesystem.php +++ b/app/code/File/Filesystem.php @@ -1,4 +1,11 @@ getHashedFileName($name) . '.patch'; $patchPath = $this->_uploadPath . $newFileName[$fileId]; if (move_uploaded_file($_FILES[$fileElementName]['tmp_name'][$fileId], $patchPath)) { - require_once 'app/code/Patch/Converter.php'; - $converter = new Patch_Converter(); + $converter = new Converter(); $converter->preparePatch($patchPath); } else { $error[$fileId][] = 'Unable to move uploaded file from tmp folder.'; diff --git a/app/code/Patch/Check/Strategy/AbstractStrategy.php b/app/code/Patch/Check/Strategy/AbstractStrategy.php index 010017d..6d89e4e 100644 --- a/app/code/Patch/Check/Strategy/AbstractStrategy.php +++ b/app/code/Patch/Check/Strategy/AbstractStrategy.php @@ -1,4 +1,13 @@ executeCommand($this->getCommand($patchPath, $instancePath)); if (!$result) { - return Patch_Checker::PATCH_APPLY_RESULT_SUCCESSFUL; + return Checker::PATCH_APPLY_RESULT_SUCCESSFUL; } $result = $this->executeCommand($this->getCommand($patchPath, $instancePath, true)); if (!$result) { - return Patch_Checker::PATCH_APPLY_RESULT_MERGED; + return Checker::PATCH_APPLY_RESULT_MERGED; } } } diff --git a/app/code/Patch/Check/Strategy/GitApplyStrategy.php b/app/code/Patch/Check/Strategy/GitApplyStrategy.php index 7bcfeef..9eafb5b 100644 --- a/app/code/Patch/Check/Strategy/GitApplyStrategy.php +++ b/app/code/Patch/Check/Strategy/GitApplyStrategy.php @@ -1,4 +1,11 @@ originalPatchPath = $patchPath; - $this->instanceManager = new Deploy_InstanceManager(); + $this->instanceManager = new InstanceManager(); $this->strategyManager = new StrategyManager(); - $this->patchConverter = new Patch_Converter(); + $this->patchConverter = new Converter(); } private function getPatchForInstanceType($instanceType) { if (!isset($this->patchPerInstanceType[$instanceType])) { $patchPath = false; - if ($instanceType == Deploy_Instance::INSTANCE_TYPE_GIT) { + if ($instanceType == Instance::INSTANCE_TYPE_GIT) { $patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.git.patch'; $isConverted = $this->patchConverter->convertFromComposerToGitFormat($this->originalPatchPath, $patchPath); if (!$isConverted) { $patchPath = false; } - } elseif ($instanceType == Deploy_Instance::INSTANCE_TYPE_COMPOSER) { + } elseif ($instanceType == Instance::INSTANCE_TYPE_COMPOSER) { $patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.composer.patch'; $isConverted = $this->patchConverter->convertFromGitToComposerFormat($this->originalPatchPath, $patchPath); if (!$isConverted) { @@ -65,7 +72,7 @@ public function checkPatchForAllReleases() } continue; } - if ($instance->getInstanceType() == Deploy_Instance::INSTANCE_TYPE_INVALID) { + if ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) { $result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'check_strategy' => 'n/a']; continue; } diff --git a/app/code/Patch/Converter.php b/app/code/Patch/Converter.php index 0bbd1f9..34455e6 100644 --- a/app/code/Patch/Converter.php +++ b/app/code/Patch/Converter.php @@ -1,8 +1,15 @@ BP . UPLOAD_PATH]); + $fileUploader = new \Magento\PatchChecker\File\Uploader(['upload_path' => BP . UPLOAD_PATH]); $result = $fileUploader->upload(); - require_once 'app/code/Patch/Checker.php'; - $patchChecker = new Patch_Checker(BP . UPLOAD_PATH . $result['new_file_name'][0]); + $patchChecker = new \Magento\PatchChecker\Patch\Checker(BP . UPLOAD_PATH . $result['new_file_name'][0]); $checkResults = $patchChecker->checkPatchForAllReleases(); $result = $result['result']; $result['check_results'] = $checkResults; @@ -34,7 +32,6 @@ // @TODO Implement logging } -require_once 'app/code/Design.php'; -$design = new Design(); +$design = new \Magento\PatchChecker\Design(); require_once 'design/templates/index.phtml'; From a6edfbe8ac6b6ddfa1c9d941426a0e4791b3c5cb Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Wed, 7 Oct 2020 17:29:33 -0500 Subject: [PATCH 2/7] MC-38191: Implement check for patch availability in MQP --- app/bootstrap.php | 2 +- app/code/Patch/AbstractChecker.php | 94 ++++++++++++ .../Patch/Check/Strategy/AbstractStrategy.php | 4 +- app/code/Patch/Checker.php | 113 ++++----------- app/code/Patch/InstancePatchConverter.php | 65 +++++++++ app/code/Patch/MQP/Checker.php | 68 +++++++++ app/code/Patch/MQP/Data/AggregatedPatch.php | 52 +++++++ app/code/Patch/MQP/Data/Patch.php | 72 ++++++++++ app/code/Patch/MQP/PatchRepository.php | 65 +++++++++ app/code/Patch/MQP/VersionsManager.php | 59 ++++++++ app/code/Util.php | 31 ++++ app/config/magento_package_versions.json | 135 ++++++++++++++++++ composer.json | 7 +- design/js/script.js | 106 +++++++++++++- design/js/uploader.js | 58 +------- design/style/style.css | 27 ++++ design/templates/index.phtml | 9 ++ index.php | 27 +++- 18 files changed, 845 insertions(+), 149 deletions(-) create mode 100644 app/code/Patch/AbstractChecker.php create mode 100644 app/code/Patch/InstancePatchConverter.php create mode 100644 app/code/Patch/MQP/Checker.php create mode 100644 app/code/Patch/MQP/Data/AggregatedPatch.php create mode 100644 app/code/Patch/MQP/Data/Patch.php create mode 100644 app/code/Patch/MQP/PatchRepository.php create mode 100644 app/code/Patch/MQP/VersionsManager.php create mode 100644 app/code/Util.php create mode 100644 app/config/magento_package_versions.json diff --git a/app/bootstrap.php b/app/bootstrap.php index b8071d0..b83344e 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -13,4 +13,4 @@ define('UPLOAD_PATH', 'var/uploads/'); define('STATS_PATH', 'var/stats/'); -require_once __DIR__ . '/autoload.php'; \ No newline at end of file +require_once __DIR__ . '/autoload.php'; diff --git a/app/code/Patch/AbstractChecker.php b/app/code/Patch/AbstractChecker.php new file mode 100644 index 0000000..79fc098 --- /dev/null +++ b/app/code/Patch/AbstractChecker.php @@ -0,0 +1,94 @@ +instanceManager = $instanceManager; + $this->strategyManager = $strategyManager; + } + + /** + * Return patch status for each configured version. + * + * @param string $patch + * @return array + */ + public function check(string $patch) + { + $result = []; + foreach ($this->instanceManager->getInstanceList() as $groupName => $groupInstanceList) { + foreach ($groupInstanceList as $instance) { + if (is_int($instance)) { + for ($i = 0; $i < $instance; $i++) { + $result[$groupName][] = ['instance_name' => 'n/a', 'check_strategy' => 'n/a']; + } + } else if ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) { + $result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'check_strategy' => 'n/a']; + } else { + $checkResult = []; + foreach ($this->strategyManager->getStrategyList() as $strategy) { + $strategyResult = $this->getResult($patch, $instance, $strategy); + + if ($strategyResult == self::PATCH_APPLY_RESULT_MERGED) { + $checkResult = 'merged'; + break; + } + + $checkResult[$strategy->getStrategyName()] = $strategyResult; + } + $result[$groupName][] = [ + 'instance_name' => $instance->getInstanceName(), + 'check_strategy' => $checkResult + ]; + } + } + } + + return $result; + } + + /** + * Get status of the patch + * + * @param string $patch + * @param Instance $instance + * @param StrategyInterface $strategy + * @return int + */ + abstract public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int; +} diff --git a/app/code/Patch/Check/Strategy/AbstractStrategy.php b/app/code/Patch/Check/Strategy/AbstractStrategy.php index 6d89e4e..d65ffe6 100644 --- a/app/code/Patch/Check/Strategy/AbstractStrategy.php +++ b/app/code/Patch/Check/Strategy/AbstractStrategy.php @@ -56,7 +56,7 @@ protected function executeCommand($command) public function check($patchPath, $instancePath) { if (!$patchPath) { - return false; + return Checker::PATCH_APPLY_RESULT_FAILED; } $result = $this->executeCommand($this->getCommand($patchPath, $instancePath)); @@ -68,5 +68,7 @@ public function check($patchPath, $instancePath) if (!$result) { return Checker::PATCH_APPLY_RESULT_MERGED; } + + return Checker::PATCH_APPLY_RESULT_FAILED; } } diff --git a/app/code/Patch/Checker.php b/app/code/Patch/Checker.php index 388ce82..fb92f7a 100644 --- a/app/code/Patch/Checker.php +++ b/app/code/Patch/Checker.php @@ -9,98 +9,43 @@ use Magento\PatchChecker\Deploy\Instance; use Magento\PatchChecker\Deploy\InstanceManager; +use Magento\PatchChecker\Patch\Check\Strategy\StrategyInterface; use Magento\PatchChecker\Patch\Check\StrategyManager; -class Checker +/** + * Patch checker + */ +class Checker extends AbstractChecker { - const PATCH_APPLY_RESULT_FAILED = 0; - const PATCH_APPLY_RESULT_SUCCESSFUL = 1; - const PATCH_APPLY_RESULT_MERGED = 2; - - - private $instanceManager; - - private $strategyManager; - + /** + * @var InstancePatchConverter + */ private $patchConverter; - private $originalPatchPath; - - private $patchPerInstanceType = []; - - - public function __construct($patchPath) - { - $this->originalPatchPath = $patchPath; - $this->instanceManager = new InstanceManager(); - $this->strategyManager = new StrategyManager(); - $this->patchConverter = new Converter(); - } - - private function getPatchForInstanceType($instanceType) - { - if (!isset($this->patchPerInstanceType[$instanceType])) { - $patchPath = false; - if ($instanceType == Instance::INSTANCE_TYPE_GIT) { - $patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.git.patch'; - $isConverted = $this->patchConverter->convertFromComposerToGitFormat($this->originalPatchPath, $patchPath); - if (!$isConverted) { - $patchPath = false; - } - } elseif ($instanceType == Instance::INSTANCE_TYPE_COMPOSER) { - $patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.composer.patch'; - $isConverted = $this->patchConverter->convertFromGitToComposerFormat($this->originalPatchPath, $patchPath); - if (!$isConverted) { - $patchPath = false; - } - } - - $this->patchPerInstanceType[$instanceType] = $patchPath; - } - - return $this->patchPerInstanceType[$instanceType]; + /** + * @param InstanceManager $instanceManager + * @param StrategyManager $strategyManager + * @param InstancePatchConverter $patchConverter + */ + public function __construct( + InstanceManager $instanceManager, + StrategyManager $strategyManager, + InstancePatchConverter $patchConverter + ) { + parent::__construct($instanceManager, $strategyManager); + $this->patchConverter = $patchConverter; } - public function checkPatchForAllReleases() + /** + * @inheritDoc + */ + public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int { - $result = []; - foreach ($this->instanceManager->getInstanceList() as $groupName => $groupInstanceList) { - foreach ($groupInstanceList as $instance) { - if (is_int($instance)) { - for ($i = 0; $i < $instance; $i++) { - $result[$groupName][] = ['instance_name' => 'n/a', 'check_strategy' => 'n/a']; - } - continue; - } - if ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) { - $result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'check_strategy' => 'n/a']; - continue; - } - - $patchForInstancePath = $this->getPatchForInstanceType($instance->getInstanceType()); - $checkResult = []; - foreach ($this->strategyManager->getStrategyList() as $strategy) { - $patchPath = ($strategy->getIsPreserveOriginalFileFormat()) - ? $this->originalPatchPath - : $patchForInstancePath; - - $strategyResult = $strategy->check($patchPath, $instance->getInstancePath()); - - if ($strategyResult == self::PATCH_APPLY_RESULT_MERGED) { - $checkResult = 'merged'; - break; - } - - $checkResult[$strategy->getStrategyName()] = $strategyResult; - } - - $result[$groupName][] = [ - 'instance_name' => $instance->getInstanceName(), - 'check_strategy' => $checkResult - ]; - } - } + $patchForInstancePath = $this->patchConverter->convert($patch, $instance->getInstanceType()); + $patchPath = $strategy->getIsPreserveOriginalFileFormat() + ? $patch + : $patchForInstancePath; - return $result; + return $strategy->check($patchPath, $instance->getInstancePath()); } } diff --git a/app/code/Patch/InstancePatchConverter.php b/app/code/Patch/InstancePatchConverter.php new file mode 100644 index 0000000..9e3d03e --- /dev/null +++ b/app/code/Patch/InstancePatchConverter.php @@ -0,0 +1,65 @@ +patchConverter = $patchConverter; + } + + /** + * Convert patch to the format compatible with given instance type + * + * @param string $originalPatchPath + * @param string $instanceType + * @return false|string + */ + public function convert(string $originalPatchPath, string $instanceType) + { + if (!isset($this->cache[$originalPatchPath]) || !isset($this->cache[$originalPatchPath][$instanceType])) { + $patchPath = false; + if ($instanceType === Instance::INSTANCE_TYPE_GIT) { + $patchPath = BP . UPLOAD_PATH . pathinfo($originalPatchPath, PATHINFO_FILENAME) . '.git.patch'; + $isConverted = $this->patchConverter->convertFromComposerToGitFormat($originalPatchPath, $patchPath); + if (!$isConverted) { + $patchPath = false; + } + } elseif ($instanceType === Instance::INSTANCE_TYPE_COMPOSER) { + $patchPath = BP . UPLOAD_PATH . pathinfo($originalPatchPath, PATHINFO_FILENAME) . '.composer.patch'; + $isConverted = $this->patchConverter->convertFromGitToComposerFormat($originalPatchPath, $patchPath); + if (!$isConverted) { + $patchPath = false; + } + } + + $this->cache[$originalPatchPath][$instanceType] = $patchPath; + } + + return $this->cache[$originalPatchPath][$instanceType]; + } +} diff --git a/app/code/Patch/MQP/Checker.php b/app/code/Patch/MQP/Checker.php new file mode 100644 index 0000000..f1d9464 --- /dev/null +++ b/app/code/Patch/MQP/Checker.php @@ -0,0 +1,68 @@ +versionsManager = $versionsManager; + $this->patchRepository = $patchRepository; + } + + /** + * @inheritDoc + */ + public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int + { + $aggregatedPatch = $this->patchRepository->findOne($patch); + $status = self::PATCH_APPLY_RESULT_FAILED; + foreach ($aggregatedPatch->getPatches() as $patch) { + $packageVersion = $this->versionsManager->getPackageVersion( + $instance->getInstanceName(), + $patch->getPackageName() + ); + if ($packageVersion && Semver::satisfies($packageVersion, $patch->getPackageConstraint())) { + $status = self::PATCH_APPLY_RESULT_SUCCESSFUL; + break; + } + } + return $status; + } +} diff --git a/app/code/Patch/MQP/Data/AggregatedPatch.php b/app/code/Patch/MQP/Data/AggregatedPatch.php new file mode 100644 index 0000000..1bda868 --- /dev/null +++ b/app/code/Patch/MQP/Data/AggregatedPatch.php @@ -0,0 +1,52 @@ +config = $config; + } + + /** + * Get patch items + * + * @return Patch[] + */ + public function getPatches(): array + { + if ($this->patches === null) { + $this->patches = []; + foreach ($this->config as $packageName => $packageConfiguration) { + foreach ($packageConfiguration as $patchTitle => $patchInfo) { + foreach ($patchInfo as $packageConstraint => $patchData) { + $this->patches[] = new Patch($packageName, $packageConstraint, $patchData['file']); + } + } + } + } + + return $this->patches; + } +} diff --git a/app/code/Patch/MQP/Data/Patch.php b/app/code/Patch/MQP/Data/Patch.php new file mode 100644 index 0000000..db9a0a0 --- /dev/null +++ b/app/code/Patch/MQP/Data/Patch.php @@ -0,0 +1,72 @@ +packageName = $packageName; + $this->packageConstraint = $packageConstraint; + $this->filename = $filename; + } + + /** + * Get package name + * + * @return string + */ + public function getPackageName(): string + { + return $this->packageName; + } + + /** + * Get package constraints + * + * @return string + */ + public function getPackageConstraint(): string + { + return $this->packageConstraint; + } + + /** + * Get patch filename + * + * @return string + */ + public function getFilename(): string + { + return $this->filename; + } +} diff --git a/app/code/Patch/MQP/PatchRepository.php b/app/code/Patch/MQP/PatchRepository.php new file mode 100644 index 0000000..873cb2f --- /dev/null +++ b/app/code/Patch/MQP/PatchRepository.php @@ -0,0 +1,65 @@ +info = $info; + } + + + /** + * Find patch by ID + * + * @param string $id + * @return AggregatedPatch + * @throws \Exception + */ + public function findOne(string $id): AggregatedPatch + { + $config = $this->getConfiguration(); + if (isset($config[$id])) { + return new AggregatedPatch($config[$id]); + } + throw new \Exception("Patch '$id' cannot be found."); + } + + /** + * Get patches configuration + * + * @return array + * @throws \Exception + */ + private function getConfiguration(): array + { + $result = []; + $configPath = $this->info->getPatchesConfig(); + if (file_exists($configPath)) { + $result = Util::getJsonFile($configPath); + } + + return $result; + } +} diff --git a/app/code/Patch/MQP/VersionsManager.php b/app/code/Patch/MQP/VersionsManager.php new file mode 100644 index 0000000..9f1e37c --- /dev/null +++ b/app/code/Patch/MQP/VersionsManager.php @@ -0,0 +1,59 @@ +getConfiguration()[$coreVersion][$packageName] ?? null; + } + + /** + * Get versions configuration + * + * @return array + */ + private function getConfiguration(): array + { + if ($this->configuration === null) { + $this->configuration = []; + $configPath = $this->getConfigurationPath(); + if (file_exists($configPath)) { + $this->configuration = Util::getJsonFile($configPath); + } + } + + return $this->configuration; + } + + /** + * Get versions configuration path + * + * @return string + */ + private function getConfigurationPath(): string + { + return BP . 'app/config/magento_package_versions.json'; + } +} diff --git a/app/code/Util.php b/app/code/Util.php new file mode 100644 index 0000000..6e95e4e --- /dev/null +++ b/app/code/Util.php @@ -0,0 +1,31 @@ +' + + '' + + '' + + '' + groupName + '' + + '' + + '' + + 'Version' + + 'Patch' + + 'Git' + + '' + + ''; + + for (release in groupResults) { + release = groupResults[release]; + + output += '' + + 'Merged'; + } else { + var falseResultClass = 'td_fail'; + for (var strategyResult in release.check_strategy) { + if (release.check_strategy[strategyResult] == 1) { + falseResultClass = 'td_adaptation_required'; + break; + } + } + + output += '>' + release.instance_name + ''; + if (release.check_strategy['patch'] == 1) { + output += 'Ok'; + } else { + output += 'No'; + } + if (release.check_strategy['git_apply'] == 1) { + output += 'Ok'; + } else { + output += 'No'; + } + } + output += ''; + } + output += ''; + + $('#results_div').append(output); + } + } }) diff --git a/design/js/uploader.js b/design/js/uploader.js index 2e82c7b..4785adb 100755 --- a/design/js/uploader.js +++ b/design/js/uploader.js @@ -28,63 +28,7 @@ $().ready(function() { loaded : function(result) { $('#PRO' + result.fileno).remove(); $('#FILE' + result.fileno).html('Uploaded: ' + result.filename + ' (' + result.size + ')'); - - for (var groupName in result.check_results) { - var groupResults = result.check_results[groupName]; - - var output = '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + ''; - - for (var release in groupResults) { - var release = groupResults[release]; - - output += '' - + ''; - if (release.check_strategy['patch'] == 1) { - output += ''; - } - output += '
' + groupName + '
VersionEECloud
Merged'; - } else { - var falseResultClass = 'td_fail'; - for (var strategyResult in release.check_strategy) { - if (release.check_strategy[strategyResult] == 1) { - falseResultClass = 'td_adaptation_required'; - break; - } - } - - output += '>' + release.instance_name + 'Ok'; - } else { - output += 'No'; - } - if (release.check_strategy['git_apply'] == 1) { - output += 'Ok'; - } else { - output += 'No'; - } - } - output += '
'; - - $('#results_div').append(output); - } + $('#upload').trigger('uploaded', [result]); }, progress : function(result) { diff --git a/design/style/style.css b/design/style/style.css index 6088c50..9a1826a 100755 --- a/design/style/style.css +++ b/design/style/style.css @@ -9,6 +9,33 @@ div { float: left; } +div#mqp_form_container, div#separator { + clear: both; + margin-top: 10px; +} + +div#mqp_form_container { + width: 760px; + border: 1px solid #ddd; + padding: 10px; +} + +div#separator { + width: 760px; + text-align: center; +} + +form#mqp_form{ + margin-top: 10px; +} + +span#mqp_error_patch_id { + display: block; + margin: 5px 0; + font-size: 12px; + color: red; +} + div#results_div { clear: both; padding: 32px; diff --git a/design/templates/index.phtml b/design/templates/index.phtml index 1c2969f..d906116 100755 --- a/design/templates/index.phtml +++ b/design/templates/index.phtml @@ -21,6 +21,15 @@
+
-OR-
+
+ Enter MQP Patch ID +
+ + + +
+
$group): ?> diff --git a/index.php b/index.php index 38e5788..a0509ca 100755 --- a/index.php +++ b/index.php @@ -9,8 +9,12 @@ $fileUploader = new \Magento\PatchChecker\File\Uploader(['upload_path' => BP . UPLOAD_PATH]); $result = $fileUploader->upload(); - $patchChecker = new \Magento\PatchChecker\Patch\Checker(BP . UPLOAD_PATH . $result['new_file_name'][0]); - $checkResults = $patchChecker->checkPatchForAllReleases(); + $patchChecker = new \Magento\PatchChecker\Patch\Checker( + new \Magento\PatchChecker\Deploy\InstanceManager(), + new \Magento\PatchChecker\Patch\Check\StrategyManager(), + new \Magento\PatchChecker\Patch\InstancePatchConverter(new \Magento\PatchChecker\Patch\Converter()) + ); + $checkResults = $patchChecker->check(BP . UPLOAD_PATH . $result['new_file_name'][0]); $result = $result['result']; $result['check_results'] = $checkResults; @@ -25,6 +29,25 @@ } } + echo json_encode($result); + die; + } elseif (!empty($_POST['patch_id'])) { + $result = [ + 'check_results' => [], + 'error' => '', + ]; + try { + $patchChecker = new \Magento\PatchChecker\Patch\MQP\Checker( + new \Magento\PatchChecker\Deploy\InstanceManager(), + new \Magento\PatchChecker\Patch\Check\StrategyManager(), + new \Magento\PatchChecker\Patch\MQP\PatchRepository(new \Magento\QualityPatches\Info()), + new \Magento\PatchChecker\Patch\MQP\VersionsManager + ); + $result['check_results'] = $patchChecker->check($_POST['patch_id']); + } catch (\Exception $exception) { + $result['error'] = "Invalid Patch ID"; + } + echo json_encode($result); die; } From acac7c10311766547044b103945bf91965fcb3cc Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Thu, 8 Oct 2020 16:27:02 -0500 Subject: [PATCH 3/7] Improve user experience - Display MQP version - Change No to Fail - Fix styling - Fix b2b package version --- app/code/Patch/MQP/Version.php | 32 ++++++++++++++++++++++++ app/code/Patch/MQP/VersionsManager.php | 2 +- app/code/Util.php | 18 ++++++++++++- app/config/magento_package_versions.json | 2 +- design/js/script.js | 10 ++++---- design/style/style.css | 10 ++++++++ design/templates/index.phtml | 9 ++++--- index.php | 1 + 8 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 app/code/Patch/MQP/Version.php diff --git a/app/code/Patch/MQP/Version.php b/app/code/Patch/MQP/Version.php new file mode 100644 index 0000000..defee78 --- /dev/null +++ b/app/code/Patch/MQP/Version.php @@ -0,0 +1,32 @@ +' + var output = '' + '' + '' + '' + '' + '' + '' - + '' - + '' + + '' + + '' + '' + ''; @@ -96,12 +96,12 @@ $().ready(function () { if (release.check_strategy['patch'] == 1) { output += ''; diff --git a/design/style/style.css b/design/style/style.css index 9a1826a..6aa28b0 100755 --- a/design/style/style.css +++ b/design/style/style.css @@ -36,6 +36,12 @@ span#mqp_error_patch_id { color: red; } +span#mqp_version { + display: block; + margin: 5px 0; + font-size: 10px; +} + div#results_div { clear: both; padding: 32px; @@ -72,6 +78,7 @@ table.result_table { display: block; float: left; margin-right: 40px; + margin-top: 20px; border-collapse: collapse; } td.td_fail { @@ -87,6 +94,9 @@ td.td_merged { background-color: #C899D7; } +table.release_table td { + width: 60px; +} table.result_table tr td { padding: 2px 10px; } diff --git a/design/templates/index.phtml b/design/templates/index.phtml index d906116..1f0560e 100755 --- a/design/templates/index.phtml +++ b/design/templates/index.phtml @@ -27,13 +27,14 @@ + MQP version
$group): ?> -
' + groupName + '
VersionPatchGitApplied using PatchApplied using Git
Ok'; } else { - output += 'No'; + output += 'Fail'; } if (release.check_strategy['git_apply'] == 1) { output += 'Ok'; } else { - output += 'No'; + output += 'Fail'; } } output += '
+
@@ -82,7 +83,7 @@ - + - + @@ -112,7 +113,7 @@ - + diff --git a/index.php b/index.php index a0509ca..7e24386 100755 --- a/index.php +++ b/index.php @@ -56,5 +56,6 @@ } $design = new \Magento\PatchChecker\Design(); +$mqpVersion = new \Magento\PatchChecker\Patch\MQP\Version(); require_once 'design/templates/index.phtml'; From 0131b35a0707451243442c2517e3643a28d163ab Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Mon, 12 Oct 2020 09:29:16 -0500 Subject: [PATCH 4/7] Change MQP result format --- app/code/Patch/AbstractChecker.php | 37 ++++-------------- app/code/Patch/Checker.php | 28 ++++++++++---- app/code/Patch/MQP/Checker.php | 9 +---- design/js/script.js | 61 +++++++++++++++++------------- design/style/style.css | 3 ++ design/templates/index.phtml | 43 ++------------------- index.php | 5 ++- 7 files changed, 76 insertions(+), 110 deletions(-) diff --git a/app/code/Patch/AbstractChecker.php b/app/code/Patch/AbstractChecker.php index 79fc098..8827643 100644 --- a/app/code/Patch/AbstractChecker.php +++ b/app/code/Patch/AbstractChecker.php @@ -9,8 +9,6 @@ use Magento\PatchChecker\Deploy\Instance; use Magento\PatchChecker\Deploy\InstanceManager; -use Magento\PatchChecker\Patch\Check\Strategy\StrategyInterface; -use Magento\PatchChecker\Patch\Check\StrategyManager; /** * Abstract patch checker @@ -25,21 +23,14 @@ abstract class AbstractChecker * @var InstanceManager */ private $instanceManager; - /** - * @var StrategyManager - */ - private $strategyManager; /** * @param InstanceManager $instanceManager - * @param StrategyManager $strategyManager */ public function __construct( - InstanceManager $instanceManager, - StrategyManager $strategyManager + InstanceManager $instanceManager ) { $this->instanceManager = $instanceManager; - $this->strategyManager = $strategyManager; } /** @@ -55,25 +46,14 @@ public function check(string $patch) foreach ($groupInstanceList as $instance) { if (is_int($instance)) { for ($i = 0; $i < $instance; $i++) { - $result[$groupName][] = ['instance_name' => 'n/a', 'check_strategy' => 'n/a']; + $result[$groupName][] = ['instance_name' => 'n/a', 'result' => 'n/a']; } - } else if ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) { - $result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'check_strategy' => 'n/a']; + } elseif ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) { + $result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'result' => 'n/a']; } else { - $checkResult = []; - foreach ($this->strategyManager->getStrategyList() as $strategy) { - $strategyResult = $this->getResult($patch, $instance, $strategy); - - if ($strategyResult == self::PATCH_APPLY_RESULT_MERGED) { - $checkResult = 'merged'; - break; - } - - $checkResult[$strategy->getStrategyName()] = $strategyResult; - } $result[$groupName][] = [ 'instance_name' => $instance->getInstanceName(), - 'check_strategy' => $checkResult + 'result' => $this->getResult($instance, $patch) ]; } } @@ -85,10 +65,9 @@ public function check(string $patch) /** * Get status of the patch * - * @param string $patch * @param Instance $instance - * @param StrategyInterface $strategy - * @return int + * @param string $patch + * @return array|string */ - abstract public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int; + abstract public function getResult(Instance $instance, string $patch); } diff --git a/app/code/Patch/Checker.php b/app/code/Patch/Checker.php index fb92f7a..d7278f0 100644 --- a/app/code/Patch/Checker.php +++ b/app/code/Patch/Checker.php @@ -9,7 +9,6 @@ use Magento\PatchChecker\Deploy\Instance; use Magento\PatchChecker\Deploy\InstanceManager; -use Magento\PatchChecker\Patch\Check\Strategy\StrategyInterface; use Magento\PatchChecker\Patch\Check\StrategyManager; /** @@ -21,6 +20,10 @@ class Checker extends AbstractChecker * @var InstancePatchConverter */ private $patchConverter; + /** + * @var StrategyManager + */ + private $strategyManager; /** * @param InstanceManager $instanceManager @@ -32,20 +35,31 @@ public function __construct( StrategyManager $strategyManager, InstancePatchConverter $patchConverter ) { - parent::__construct($instanceManager, $strategyManager); + parent::__construct($instanceManager); $this->patchConverter = $patchConverter; + $this->strategyManager = $strategyManager; } /** * @inheritDoc */ - public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int + public function getResult(Instance $instance, string $patch) { $patchForInstancePath = $this->patchConverter->convert($patch, $instance->getInstanceType()); - $patchPath = $strategy->getIsPreserveOriginalFileFormat() - ? $patch - : $patchForInstancePath; + $checkResult = []; + foreach ($this->strategyManager->getStrategyList() as $strategy) { + $patchPath = ($strategy->getIsPreserveOriginalFileFormat()) + ? $patch + : $patchForInstancePath; + $strategyResult = $strategy->check($patchPath, $instance->getInstancePath()); + + if ($strategyResult === self::PATCH_APPLY_RESULT_MERGED) { + $checkResult = 'merged'; + break; + } + $checkResult[$strategy->getStrategyName()] = $strategyResult; + } - return $strategy->check($patchPath, $instance->getInstancePath()); + return $checkResult; } } diff --git a/app/code/Patch/MQP/Checker.php b/app/code/Patch/MQP/Checker.php index f1d9464..37e8759 100644 --- a/app/code/Patch/MQP/Checker.php +++ b/app/code/Patch/MQP/Checker.php @@ -11,9 +11,6 @@ use Magento\PatchChecker\Deploy\Instance; use Magento\PatchChecker\Deploy\InstanceManager; use Magento\PatchChecker\Patch\AbstractChecker; -use Magento\PatchChecker\Patch\Check\Strategy\StrategyInterface; -use Magento\PatchChecker\Patch\Check\StrategyManager; -use Magento\QualityPatches\Info; /** * MQP patch checker @@ -31,17 +28,15 @@ class Checker extends AbstractChecker /** * @param InstanceManager $instanceManager - * @param StrategyManager $strategyManager * @param PatchRepository $patchRepository * @param VersionsManager $versionsManager */ public function __construct( InstanceManager $instanceManager, - StrategyManager $strategyManager, PatchRepository $patchRepository, VersionsManager $versionsManager ) { - parent::__construct($instanceManager, $strategyManager); + parent::__construct($instanceManager); $this->versionsManager = $versionsManager; $this->patchRepository = $patchRepository; } @@ -49,7 +44,7 @@ public function __construct( /** * @inheritDoc */ - public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int + public function getResult(Instance $instance, string $patch): int { $aggregatedPatch = $this->patchRepository->findOne($patch); $status = self::PATCH_APPLY_RESULT_FAILED; diff --git a/design/js/script.js b/design/js/script.js index 00d3cc4..c6e4cc6 100644 --- a/design/js/script.js +++ b/design/js/script.js @@ -5,12 +5,11 @@ $().ready(function () { }) .mouseleave(function () { $('#legend_fold_icon').css('filter', 'brightness(0.85)'); - }); - - $('#legend_header_div').click(function () { - $('#legend_body_div').toggle(); - $('#legend_fold_icon').toggleClass('rotate180'); - }) + }) + .click(function () { + $('#legend_body_div').toggle(); + $('#legend_fold_icon').toggleClass('rotate180'); + }) $('#upload').on('uploaded', function (e, result) { render_result(result); @@ -53,55 +52,65 @@ $().ready(function () { } function render_result(result) { - var release, groupName, groupResults + var output, release, groupName, groupResults, falseResultClass, strategyResult for (groupName in result.check_results) { groupResults = result.check_results[groupName]; - var output = '
Patch is applicable.
NoFail Patch failed to apply by specific apply strategy, however it was successfully applied by other automated strategy. It means it can be easily ported without complete workflow escalation process. @@ -93,7 +94,7 @@ Solution is already merged to a release.
NoFail Patch failed to apply.
2.1.0 OkNoFail Validation was made for the specific release and the results are provided.
' + output = '
' + '' + '' + '' + '' + '' - + '' - + '' - + '' + + (result.check_method !== 'mqp' + ? '' + : '' + ) + + (result.check_method !== 'mqp' + ? '' + : '' + ) + '' + + (result.check_method !== 'mqp' + ? '' + : '' + ) + ''; for (release in groupResults) { release = groupResults[release]; output += '' + '' + + '' + + ''; - if (release.check_strategy['patch'] == 1) { + if (release.result['patch'] === 1) { output += ''; diff --git a/design/style/style.css b/design/style/style.css index 6aa28b0..697e2d6 100755 --- a/design/style/style.css +++ b/design/style/style.css @@ -97,6 +97,9 @@ td.td_merged { table.release_table td { width: 60px; } +table.release_table td.colspan_2 { + width: 131px; +} table.result_table tr td { padding: 2px 10px; } diff --git a/design/templates/index.phtml b/design/templates/index.phtml index 1f0560e..7dcb65b 100755 --- a/design/templates/index.phtml +++ b/design/templates/index.phtml @@ -31,42 +31,7 @@ -
- - $group): ?> -
' + groupName + '
VersionApplied using PatchApplied using GitVersionVersionIs CompatibleIs Compatible
using Patchusing Git
Merged'; + } else if (release.result === 1) { + output += '>' + release.instance_name + 'Ok'; + } else if (release.result === 0) { + output += '>' + release.instance_name + 'No'; } else { - var falseResultClass = 'td_fail'; - for (var strategyResult in release.check_strategy) { - if (release.check_strategy[strategyResult] == 1) { + falseResultClass = 'td_fail'; + for (strategyResult in release.result) { + if (release.result[strategyResult] === 1) { falseResultClass = 'td_adaptation_required'; break; } } output += '>' + release.instance_name + 'Ok'; } else { - output += 'Fail'; + output += 'No'; } - if (release.check_strategy['git_apply'] == 1) { + if (release.result['git_apply'] === 1) { output += 'Ok'; } else { - output += 'Fail'; + output += 'No'; } } output += '
- - - - - - - - - - - - - - - - - - -
- - - - - - - - -
- - -
- +
Legend
@@ -83,7 +48,7 @@ Patch is applicable. - Fail + No Patch failed to apply by specific apply strategy, however it was successfully applied by other automated strategy. It means it can be easily ported without complete workflow escalation process. @@ -94,7 +59,7 @@ Solution is already merged to a release. - Fail + No Patch failed to apply. @@ -113,7 +78,7 @@ 2.1.0 Ok - Fail + No Validation was made for the specific release and the results are provided. diff --git a/index.php b/index.php index 7e24386..54b6f4d 100755 --- a/index.php +++ b/index.php @@ -17,7 +17,7 @@ $checkResults = $patchChecker->check(BP . UPLOAD_PATH . $result['new_file_name'][0]); $result = $result['result']; $result['check_results'] = $checkResults; - + $result['check_method'] = 'file'; // checked patches statistic collection if (isset($result['filename'])) { $statsPath = BP . STATS_PATH; @@ -34,16 +34,17 @@ } elseif (!empty($_POST['patch_id'])) { $result = [ 'check_results' => [], + 'check_method' => 'mqp', 'error' => '', ]; try { $patchChecker = new \Magento\PatchChecker\Patch\MQP\Checker( new \Magento\PatchChecker\Deploy\InstanceManager(), - new \Magento\PatchChecker\Patch\Check\StrategyManager(), new \Magento\PatchChecker\Patch\MQP\PatchRepository(new \Magento\QualityPatches\Info()), new \Magento\PatchChecker\Patch\MQP\VersionsManager ); $result['check_results'] = $patchChecker->check($_POST['patch_id']); + $result['check_method'] = 'mqp'; } catch (\Exception $exception) { $result['error'] = "Invalid Patch ID"; } From f9196c41404376c6df56f3b0e2f6d0eb0d321f7f Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Mon, 12 Oct 2020 10:16:34 -0500 Subject: [PATCH 5/7] Fix MQP 'patch not found' error message --- index.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index 54b6f4d..6942bc6 100755 --- a/index.php +++ b/index.php @@ -46,7 +46,8 @@ $result['check_results'] = $patchChecker->check($_POST['patch_id']); $result['check_method'] = 'mqp'; } catch (\Exception $exception) { - $result['error'] = "Invalid Patch ID"; + $mqpVersion = new \Magento\PatchChecker\Patch\MQP\Version(); + $result['error'] = "Patch ID '{$_POST['patch_id']}' is not found in MQP $mqpVersion"; } echo json_encode($result); From 5ca760e58401375a5a9fbb169b6d77528c22c35b Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Mon, 12 Oct 2020 12:20:41 -0500 Subject: [PATCH 6/7] Change 'ok' to 'yes' --- design/js/script.js | 6 +++--- design/templates/index.phtml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/design/js/script.js b/design/js/script.js index c6e4cc6..ae4a73e 100644 --- a/design/js/script.js +++ b/design/js/script.js @@ -88,7 +88,7 @@ $().ready(function () { + 'Merged'; } else if (release.result === 1) { output += '>' + release.instance_name + '' - + 'Ok'; + + 'Yes'; } else if (release.result === 0) { output += '>' + release.instance_name + '' + 'No'; @@ -103,12 +103,12 @@ $().ready(function () { output += '>' + release.instance_name + ''; if (release.result['patch'] === 1) { - output += 'Ok'; + output += 'Yes'; } else { output += 'No'; } if (release.result['git_apply'] === 1) { - output += 'Ok'; + output += 'Yes'; } else { output += 'No'; } diff --git a/design/templates/index.phtml b/design/templates/index.phtml index 7dcb65b..2440e76 100755 --- a/design/templates/index.phtml +++ b/design/templates/index.phtml @@ -44,7 +44,7 @@ - Ok + Yes Patch is applicable. @@ -77,7 +77,7 @@ 2.1.0 - Ok + Yes No Validation was made for the specific release and the results are provided. From 20b0e60cd28c43150d4c14d3cda1e9acde471d33 Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Tue, 13 Oct 2020 09:53:56 -0500 Subject: [PATCH 7/7] Remove fixed width from table columns --- design/style/style.css | 6 ------ 1 file changed, 6 deletions(-) diff --git a/design/style/style.css b/design/style/style.css index 697e2d6..230276b 100755 --- a/design/style/style.css +++ b/design/style/style.css @@ -94,12 +94,6 @@ td.td_merged { background-color: #C899D7; } -table.release_table td { - width: 60px; -} -table.release_table td.colspan_2 { - width: 131px; -} table.result_table tr td { padding: 2px 10px; }