Skip to content

Commit a6edfbe

Browse files
committed
MC-38191: Implement check for patch availability in MQP
1 parent e5e70dd commit a6edfbe

18 files changed

+845
-149
lines changed

app/bootstrap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
define('UPLOAD_PATH', 'var/uploads/');
1414
define('STATS_PATH', 'var/stats/');
1515

16-
require_once __DIR__ . '/autoload.php';
16+
require_once __DIR__ . '/autoload.php';

app/code/Patch/AbstractChecker.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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\PatchChecker\Patch;
9+
10+
use Magento\PatchChecker\Deploy\Instance;
11+
use Magento\PatchChecker\Deploy\InstanceManager;
12+
use Magento\PatchChecker\Patch\Check\Strategy\StrategyInterface;
13+
use Magento\PatchChecker\Patch\Check\StrategyManager;
14+
15+
/**
16+
* Abstract patch checker
17+
*/
18+
abstract class AbstractChecker
19+
{
20+
const PATCH_APPLY_RESULT_FAILED = 0;
21+
const PATCH_APPLY_RESULT_SUCCESSFUL = 1;
22+
const PATCH_APPLY_RESULT_MERGED = 2;
23+
24+
/**
25+
* @var InstanceManager
26+
*/
27+
private $instanceManager;
28+
/**
29+
* @var StrategyManager
30+
*/
31+
private $strategyManager;
32+
33+
/**
34+
* @param InstanceManager $instanceManager
35+
* @param StrategyManager $strategyManager
36+
*/
37+
public function __construct(
38+
InstanceManager $instanceManager,
39+
StrategyManager $strategyManager
40+
) {
41+
$this->instanceManager = $instanceManager;
42+
$this->strategyManager = $strategyManager;
43+
}
44+
45+
/**
46+
* Return patch status for each configured version.
47+
*
48+
* @param string $patch
49+
* @return array
50+
*/
51+
public function check(string $patch)
52+
{
53+
$result = [];
54+
foreach ($this->instanceManager->getInstanceList() as $groupName => $groupInstanceList) {
55+
foreach ($groupInstanceList as $instance) {
56+
if (is_int($instance)) {
57+
for ($i = 0; $i < $instance; $i++) {
58+
$result[$groupName][] = ['instance_name' => 'n/a', 'check_strategy' => 'n/a'];
59+
}
60+
} else if ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) {
61+
$result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'check_strategy' => 'n/a'];
62+
} else {
63+
$checkResult = [];
64+
foreach ($this->strategyManager->getStrategyList() as $strategy) {
65+
$strategyResult = $this->getResult($patch, $instance, $strategy);
66+
67+
if ($strategyResult == self::PATCH_APPLY_RESULT_MERGED) {
68+
$checkResult = 'merged';
69+
break;
70+
}
71+
72+
$checkResult[$strategy->getStrategyName()] = $strategyResult;
73+
}
74+
$result[$groupName][] = [
75+
'instance_name' => $instance->getInstanceName(),
76+
'check_strategy' => $checkResult
77+
];
78+
}
79+
}
80+
}
81+
82+
return $result;
83+
}
84+
85+
/**
86+
* Get status of the patch
87+
*
88+
* @param string $patch
89+
* @param Instance $instance
90+
* @param StrategyInterface $strategy
91+
* @return int
92+
*/
93+
abstract public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int;
94+
}

app/code/Patch/Check/Strategy/AbstractStrategy.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ protected function executeCommand($command)
5656
public function check($patchPath, $instancePath)
5757
{
5858
if (!$patchPath) {
59-
return false;
59+
return Checker::PATCH_APPLY_RESULT_FAILED;
6060
}
6161

6262
$result = $this->executeCommand($this->getCommand($patchPath, $instancePath));
@@ -68,5 +68,7 @@ public function check($patchPath, $instancePath)
6868
if (!$result) {
6969
return Checker::PATCH_APPLY_RESULT_MERGED;
7070
}
71+
72+
return Checker::PATCH_APPLY_RESULT_FAILED;
7173
}
7274
}

app/code/Patch/Checker.php

Lines changed: 29 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -9,98 +9,43 @@
99

1010
use Magento\PatchChecker\Deploy\Instance;
1111
use Magento\PatchChecker\Deploy\InstanceManager;
12+
use Magento\PatchChecker\Patch\Check\Strategy\StrategyInterface;
1213
use Magento\PatchChecker\Patch\Check\StrategyManager;
1314

14-
class Checker
15+
/**
16+
* Patch checker
17+
*/
18+
class Checker extends AbstractChecker
1519
{
16-
const PATCH_APPLY_RESULT_FAILED = 0;
17-
const PATCH_APPLY_RESULT_SUCCESSFUL = 1;
18-
const PATCH_APPLY_RESULT_MERGED = 2;
19-
20-
21-
private $instanceManager;
22-
23-
private $strategyManager;
24-
20+
/**
21+
* @var InstancePatchConverter
22+
*/
2523
private $patchConverter;
2624

27-
private $originalPatchPath;
28-
29-
private $patchPerInstanceType = [];
30-
31-
32-
public function __construct($patchPath)
33-
{
34-
$this->originalPatchPath = $patchPath;
35-
$this->instanceManager = new InstanceManager();
36-
$this->strategyManager = new StrategyManager();
37-
$this->patchConverter = new Converter();
38-
}
39-
40-
private function getPatchForInstanceType($instanceType)
41-
{
42-
if (!isset($this->patchPerInstanceType[$instanceType])) {
43-
$patchPath = false;
44-
if ($instanceType == Instance::INSTANCE_TYPE_GIT) {
45-
$patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.git.patch';
46-
$isConverted = $this->patchConverter->convertFromComposerToGitFormat($this->originalPatchPath, $patchPath);
47-
if (!$isConverted) {
48-
$patchPath = false;
49-
}
50-
} elseif ($instanceType == Instance::INSTANCE_TYPE_COMPOSER) {
51-
$patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.composer.patch';
52-
$isConverted = $this->patchConverter->convertFromGitToComposerFormat($this->originalPatchPath, $patchPath);
53-
if (!$isConverted) {
54-
$patchPath = false;
55-
}
56-
}
57-
58-
$this->patchPerInstanceType[$instanceType] = $patchPath;
59-
}
60-
61-
return $this->patchPerInstanceType[$instanceType];
25+
/**
26+
* @param InstanceManager $instanceManager
27+
* @param StrategyManager $strategyManager
28+
* @param InstancePatchConverter $patchConverter
29+
*/
30+
public function __construct(
31+
InstanceManager $instanceManager,
32+
StrategyManager $strategyManager,
33+
InstancePatchConverter $patchConverter
34+
) {
35+
parent::__construct($instanceManager, $strategyManager);
36+
$this->patchConverter = $patchConverter;
6237
}
6338

64-
public function checkPatchForAllReleases()
39+
/**
40+
* @inheritDoc
41+
*/
42+
public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int
6543
{
66-
$result = [];
67-
foreach ($this->instanceManager->getInstanceList() as $groupName => $groupInstanceList) {
68-
foreach ($groupInstanceList as $instance) {
69-
if (is_int($instance)) {
70-
for ($i = 0; $i < $instance; $i++) {
71-
$result[$groupName][] = ['instance_name' => 'n/a', 'check_strategy' => 'n/a'];
72-
}
73-
continue;
74-
}
75-
if ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) {
76-
$result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'check_strategy' => 'n/a'];
77-
continue;
78-
}
79-
80-
$patchForInstancePath = $this->getPatchForInstanceType($instance->getInstanceType());
81-
$checkResult = [];
82-
foreach ($this->strategyManager->getStrategyList() as $strategy) {
83-
$patchPath = ($strategy->getIsPreserveOriginalFileFormat())
84-
? $this->originalPatchPath
85-
: $patchForInstancePath;
86-
87-
$strategyResult = $strategy->check($patchPath, $instance->getInstancePath());
88-
89-
if ($strategyResult == self::PATCH_APPLY_RESULT_MERGED) {
90-
$checkResult = 'merged';
91-
break;
92-
}
93-
94-
$checkResult[$strategy->getStrategyName()] = $strategyResult;
95-
}
96-
97-
$result[$groupName][] = [
98-
'instance_name' => $instance->getInstanceName(),
99-
'check_strategy' => $checkResult
100-
];
101-
}
102-
}
44+
$patchForInstancePath = $this->patchConverter->convert($patch, $instance->getInstanceType());
45+
$patchPath = $strategy->getIsPreserveOriginalFileFormat()
46+
? $patch
47+
: $patchForInstancePath;
10348

104-
return $result;
49+
return $strategy->check($patchPath, $instance->getInstancePath());
10550
}
10651
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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\PatchChecker\Patch;
9+
10+
use Magento\PatchChecker\Deploy\Instance;
11+
12+
/**
13+
* Convert patch to git or composer format
14+
*/
15+
class InstancePatchConverter
16+
{
17+
/**
18+
* @var Converter
19+
*/
20+
private $patchConverter;
21+
22+
/**
23+
* @var array
24+
*/
25+
private $cache = [];
26+
27+
/**
28+
* @param Converter $patchConverter
29+
*/
30+
public function __construct(Converter $patchConverter)
31+
{
32+
$this->patchConverter = $patchConverter;
33+
}
34+
35+
/**
36+
* Convert patch to the format compatible with given instance type
37+
*
38+
* @param string $originalPatchPath
39+
* @param string $instanceType
40+
* @return false|string
41+
*/
42+
public function convert(string $originalPatchPath, string $instanceType)
43+
{
44+
if (!isset($this->cache[$originalPatchPath]) || !isset($this->cache[$originalPatchPath][$instanceType])) {
45+
$patchPath = false;
46+
if ($instanceType === Instance::INSTANCE_TYPE_GIT) {
47+
$patchPath = BP . UPLOAD_PATH . pathinfo($originalPatchPath, PATHINFO_FILENAME) . '.git.patch';
48+
$isConverted = $this->patchConverter->convertFromComposerToGitFormat($originalPatchPath, $patchPath);
49+
if (!$isConverted) {
50+
$patchPath = false;
51+
}
52+
} elseif ($instanceType === Instance::INSTANCE_TYPE_COMPOSER) {
53+
$patchPath = BP . UPLOAD_PATH . pathinfo($originalPatchPath, PATHINFO_FILENAME) . '.composer.patch';
54+
$isConverted = $this->patchConverter->convertFromGitToComposerFormat($originalPatchPath, $patchPath);
55+
if (!$isConverted) {
56+
$patchPath = false;
57+
}
58+
}
59+
60+
$this->cache[$originalPatchPath][$instanceType] = $patchPath;
61+
}
62+
63+
return $this->cache[$originalPatchPath][$instanceType];
64+
}
65+
}

app/code/Patch/MQP/Checker.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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\PatchChecker\Patch\MQP;
9+
10+
use Composer\Semver\Semver;
11+
use Magento\PatchChecker\Deploy\Instance;
12+
use Magento\PatchChecker\Deploy\InstanceManager;
13+
use Magento\PatchChecker\Patch\AbstractChecker;
14+
use Magento\PatchChecker\Patch\Check\Strategy\StrategyInterface;
15+
use Magento\PatchChecker\Patch\Check\StrategyManager;
16+
use Magento\QualityPatches\Info;
17+
18+
/**
19+
* MQP patch checker
20+
*/
21+
class Checker extends AbstractChecker
22+
{
23+
/**
24+
* @var VersionsManager
25+
*/
26+
private $versionsManager;
27+
/**
28+
* @var PatchRepository
29+
*/
30+
private $patchRepository;
31+
32+
/**
33+
* @param InstanceManager $instanceManager
34+
* @param StrategyManager $strategyManager
35+
* @param PatchRepository $patchRepository
36+
* @param VersionsManager $versionsManager
37+
*/
38+
public function __construct(
39+
InstanceManager $instanceManager,
40+
StrategyManager $strategyManager,
41+
PatchRepository $patchRepository,
42+
VersionsManager $versionsManager
43+
) {
44+
parent::__construct($instanceManager, $strategyManager);
45+
$this->versionsManager = $versionsManager;
46+
$this->patchRepository = $patchRepository;
47+
}
48+
49+
/**
50+
* @inheritDoc
51+
*/
52+
public function getResult(string $patch, Instance $instance, StrategyInterface $strategy): int
53+
{
54+
$aggregatedPatch = $this->patchRepository->findOne($patch);
55+
$status = self::PATCH_APPLY_RESULT_FAILED;
56+
foreach ($aggregatedPatch->getPatches() as $patch) {
57+
$packageVersion = $this->versionsManager->getPackageVersion(
58+
$instance->getInstanceName(),
59+
$patch->getPackageName()
60+
);
61+
if ($packageVersion && Semver::satisfies($packageVersion, $patch->getPackageConstraint())) {
62+
$status = self::PATCH_APPLY_RESULT_SUCCESSFUL;
63+
break;
64+
}
65+
}
66+
return $status;
67+
}
68+
}

0 commit comments

Comments
 (0)