[由Adobe高级技术架构师Anton Evers提供]{class="badge informative" title="安东·埃弗斯撰写"}

大规模分发Adobe Commerce修补程序的最佳实践

如果您管理多个Adobe Commerce安装,修补可能是一个复杂的过程。 集中式修补 ​是全局参考体系结构的重要部分,是企业的最佳实践。 它可帮助您在所有Adobe Commerce安装中应用正确的修补程序。 本主题介绍如何为所有类型的Adobe Commerce 修补程序实现集中式修补程序分发。

NOTE
以下内容最初发布在Adobe技术博客上的按比例分发Adobe Commerce修补程序帖子中。 它经过了修改,侧重于实施集中修补策略的步骤和代码示例。 请参阅原始文章,以了解有关此处描述的不同修补程序类型的更多详细信息。

受影响的产品和版本

所有受支持的版本,共:

  • 云基础架构上的Adobe Commerce
  • Adobe Commerce内部部署

策略

由于存在许多不同类型的修补程序以及应用这些修补程序的多种方法,您如何知道哪个修补程序首先应用? 您拥有的修补程序越多,它们应用到同一文件或同一行代码的可能性就越大。 修补程序的应用顺序如下:

  1. 安全修补程序 ​是Adobe Commerce版本的静态代码库的一部分。

  2. 通过composer installcomposer update插件(如cweagans/composer-patches),Composer修补程序

  3. Commerce🔗程序包的Cloud修补程序中包含所有​ 必需的修补程序

  4. 已选择[Quality Patches Tool]中包含的​ 质量修补程序

  5. 自定义修补程序 ​以及/m2-hotfixes目录中的Adobe Commerce支持修补程序,按修补程序名称的字母顺序排列。

    note important
    IMPORTANT
    应用的修补程序越多,代码就越复杂。 复杂的代码会增加升级到新版Adobe商务的难度,并增加您的总拥有成本。

如果您负责维护Adobe Commerce的多个安装,那么确保所有实例都安装了同一组修补程序将是一项困难的挑战。 每个安装都有自己的Git存储库、/m2-hotfixes目录和composer.json文件。 您拥有的唯一保证是,云用户的​ 安全修补程序 ​和​ 必需的修补程序 ​都作为主Adobe Commerce版本的一部分安装。

目前,对于此问题,没有单一的集中式解决方案,但Composer提供了一种弥补差距的方法。 cweagans/composer-patches程序包允许您应用依赖项中的修补程序。 您可以创建一个可安装所有修补程序的Composer包,然后在您的所有项目中需要该包。

涵盖​ 安全修补程序必需的修补程序 ​和​ Composer修补程序,但质量修补程序和/m2-hotfixes目录的内容呢?

应用高品质的补丁程序和修补程序

您可以使用vendor/bin/magento-patches apply命令在云基础架构和内部部署安装上安装质量修补程序。 您必须确保vendor/bin/magento-patches apply命令在composer install操作之后运行。

NOTE
在云基础架构上,您还可以通过将质量修补程序列在您的项目的.magento.env.yaml文件中来安装质量修补程序。 此处描述的示例要求使用vendor/bin/magento-patches apply命令。

您可以指定要应用于自定义编辑器组件包的composer.json文件中的修补程序,然后创建在composer install操作后运行该命令的插件包。

总之,此集中式打补丁示例要求您创建两个自定义编辑器包:

  • 组件包: centralized-patcher

    • 定义要安装的质量修补程序和m2-hotfixes的列表
    • 需要centralized-patcher-composer-plugin程序包,该程序包在composer install操作后运行vendor/bin/magento-patches apply命令
  • 插件包: centralized-patcher-composer-plugin

    • 定义从centralized-patcher包读取质量修补程序列表的CentralizedPatcher PHP类
    • 运行vendor/bin/magento-patches apply命令以在composer install操作后安装质量修补程序列表

centralized-patcher

您可以创建编辑器组件包(centralized-patcher)以集中管理所有Adobe Commerce安装中的所有质量修补程序和/m2-hotfixes

组件包必须:

  • 在部署期间将/m2-hotfixes目录的内容复制到所有安装中。
  • 定义要安装的质量补丁程序的列表。
  • 运行vendor/bin/magento-patches命令以在所有安装中安装相同的质量修补程序列表(使用centralized-patcher-composer-plugin插件包作为依赖项)。

要创建centralized-patcher组件包,请执行以下操作:

  1. 创建包含以下内容的composer.json文件:

    note note
    NOTE
    以下示例中的require属性显示了插件包上的require依赖项,在此示例的后面必须创建该依赖项。
    code language-json
    {
     "name": "magento-services/centralized-patcher",
     "version": "0.0.1",
     "description": "Centralized patcher for patching multiple web stores from a central place",
     "type": "magento2-component",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
         "magento-services/centralized-patcher-composer-plugin": "~0.0.1"
     },
     "require-dev": {
         "composer/composer": "^2.0"
     },
     "extra": {
         "map": [
         ],
    }
    
  2. 在包中创建一个/m2-hotfixes目录,并将其添加到composer.json文件中的map属性。 map属性包含要从此包复制到要修补的目标项目根目录中的文件。

    code language-json
    {
     ...
     "extra": {
         "map": [
             [
                 "/m2-hotfixes",
                 "/m2-hotfixes"
             ]
         ],
    }
    
    note note
    NOTE
    centralized-patcher包将/m2-hotfixes目录的内容复制到composer install上目标项目的m2-hotfixes目录中。 由于云部署脚本在composer install之后应用m2修补程序,因此部署机制将安装所有修补程序。
  3. 定义要在quality-patches属性中安装的质量修补程序。

    code language-json
    {
    ...
     "extra": {
         "map": [
             [
                 "/m2-hotfixes",
                 "/m2-hotfixes"
             ]
         ],
         "quality-patches": [
             "MDVA-30106",
             "MDVA-12304"
         ]
    }
    

上述代码示例中的quality-patches属性包含完整修补程序列表中的两个修补程序示例。 使用vendor/bin/magento-patches apply命令在需要centralized-patcher软件包的每个项目中安装这些质量修补程序。

出于测试目的,您可以创建示例修补程序(/m2-hotfixes/EXAMPLE-PATCH_2.4.6.patch)。

NOTE
您应该将自己的修补程序与直接从Adobe Commerce支持接收的修补程序一起放在m2-hotfixes目录中。

示例修补程序文件(/m2-hotfixes/EXAMPLE-PATCH_2.4.6.patch):

diff --git a/vendor/magento/framework/Mview/View/Subscription.php b/vendor/magento/framework/Mview/View/Subscription.php
index 03a3bf9..681e0b0 100644
--- a/vendor/magento/framework/Mview/View/Subscription.php
+++ b/vendor/magento/framework/Mview/View/Subscription.php
@@ -16,6 +16,7 @@ use Magento\Framework\Mview\ViewInterface;

 /**
  * Mview subscription.
+ * Test Patch File
  */
 class Subscription implements SubscriptionInterface
 {

centralized-patcher-composer-plugin

由于此示例使用本地方法来安装质量修补程序,因此您必须确保vendor/bin/magento-patches apply命令在composer install操作后运行。 此插件是在运行vendor/bin/magento-patches apply命令的composer install操作之后触发的。

要创建centralized-patcher-compose-plugin组件包,请执行以下操作:

  1. 创建包含以下内容的composer.json文件:

    code language-json
    {
     "name": "magento-services/centralized-patcher-composer-plugin",
     "version": "0.0.1",
     "description": "Centralized patcher composer plugin to apply quality patches from the centralized patcher",
     "type": "composer-plugin",
     "license": [
         "OSL-3.0",
         "AFL-3.0"
     ],
     "require": {
         "symfony/process": "^4.1 || ^5.1",
         "magento/magento-cloud-patches": "~1.0.20",
         "magento/framework": "~103.0.5-p1",
         "composer-plugin-api": "^2.0"
     },
     "require-dev": {
         "composer/composer": "^2.0"
     },
     "suggest": {
         "magento-services/centralized-patcher": "~0.0.1"
     },
     "autoload": {
         "psr-4": {
             "MagentoServices\\CentralizedPatcherComposerPlugin\\": ""
         }
     },
     "extra": {
         "class": "MagentoServices\\CentralizedPatcherComposerPlugin\\Patcher"
     }
    }
    
  2. 创建PHP文件并定义CentralizedPatcher类以从centralized-patcher组件包中读取质量修补程序列表,并在每次composer install操作后立即安装它们。

    code language-php
    <?php
    declare(strict_types=1);
    
    namespace MagentoServices\CentralizedPatcherComposerPlugin;
    
    use Composer\Composer;
    use Composer\EventDispatcher\EventSubscriberInterface;
    use Composer\IO\IOInterface;
    use Composer\Plugin\PluginInterface;
    use Composer\Script\ScriptEvents;
    use Symfony\Component\Process\Exception\ProcessFailedException;
    use Symfony\Component\Process\Process;
    
    class Patcher implements PluginInterface, EventSubscriberInterface
    {
     /**
      * @var Composer $composer
      */
     protected $composer;
    
     /**
      * @var IOInterface $io
      */
     protected $io;
    
     /**
      * @param Composer $composer
      * @param IOInterface $io
      * @return void
      */
     public function activate(Composer $composer, IOInterface $io)
     {
         $this->composer = $composer;
         $this->io = $io;
     }
    
     /**
      * @param Composer $composer
      * @param IOInterface $io
      * @return void
      */
     public function deactivate(Composer $composer, IOInterface $io)
     {
         // Method must exist
     }
    
     /**
      * @param Composer $composer
      * @param IOInterface $io
      * @return void
      */
     public function uninstall(Composer $composer, IOInterface $io)
     {
         // Method must exist
     }
    
     /**
      * @return string[]
      */
     public static function getSubscribedEvents()
     {
         return [
             ScriptEvents::POST_UPDATE_CMD => 'installPatches',
             ScriptEvents::POST_INSTALL_CMD => 'installPatches',
         ];
     }
    
     /**
      * Apply patches from magento-services/centralized-patcher
      *
      * @param \Composer\Script\Event $event
      * @return void
      */
     public function installPatches(\Composer\Script\Event $event)
     {
         $patches = [];
         $this->io->write('Applying centralized quality patches');
         $packages = $this->composer->getLocker()->getLockData()['packages'];
         foreach ($packages as $package) {
             if ($package['name'] !== 'magento-services/centralized-patcher') {
                 continue;
             }
             $patches = $package['extra']['quality-patches'] ?? [];
         }
         if (empty($patches)) {
             $this->io->error("No centralized quality patches to install");
             exit(0);
         }
         $command = array_merge(
             ['php','./vendor/bin/magento-patches','apply','--no-interaction'],
              $patches
         );
         $process = new Process($command);
         try {
             $this->io->debug($process->getCommandLine());
             $process->mustRun();
             $this->io->write(
                 str_replace("\n\n", "\n", trim($process->getErrorOutput() ?: $process->getOutput(), "\n"))
             );
         } catch (ProcessFailedException $e) {
             $process = $e->getProcess();
             $error = sprintf(
                 'The command "%s" failed. %s',
                 $process->getCommandLine(),
                 trim($process->getErrorOutput() ?: $process->getOutput(), "\n")
             );
             throw new \RuntimeException($error, $process->getExitCode());
         }
     }
    }
    
TIP
请参阅code-examples,查看此示例中描述的两个包的实际操作情况。

如何处理特定于项目的修补程序

您可能会遇到这样的情况:所有项目中仅需要95%的修补程序,而少数修补程序仅适用于特定实例。 应用修补的常规方法仍然有效。 您可以在/m2-hotfixes目录中保留特定于项目的修补程序,并为每个项目安装质量修补程序。

如果使用此方法,不提交centralized-patcher组件包复制到您项目的/m2-hotfixes目录中的任何修补程序。 通过将/m2-hotfixes添加到您的.gitignore文件,您可以防止意外提交。 更新.gitignore文件后,请记住,必须使用git add –force命令添加任何特定于项目的/m2-hotfixes

运行其他Adobe Commerce版本

确保在centralized-patcher组件包中设置正确的依赖关系。 例如,您可能需要Adobe Commerce 2.4.5-p2才能获取包的特定版本,该版本仅提供与Adobe Commerce 2.4.5-p2兼容的修补程序。 您可能具有此包的其他版本与Adobe Commerce 2.4.4兼容。

了解结果

与云基础架构上的Adobe Commerce一样,本文假定您的部署过程使用composer install命令而不是composer updategit pull将新代码部署到您的服务器。 然后,集中式补丁安装的流程如下所示:

  1. Composer安装

    • 安装Adobe Commerce,包括 — p1或 — p2安全和功能修补程序
    • 将集中式/m2-hotfixes与项目特定的/m2-hotfixes结合起来并支持修补程序并支持修补程序
    • 应用随cweagans/composer-patches Composer包一起安装的所有修补程序
  2. composer install之后

    • Composer插件可安装集中式质量修补程序
  3. 部署

    • 基于.magento.env.yaml文件安装了所需的补丁程序和特定于项目的质量补丁程序(仅云基础架构项目上的Adobe Commerce)。
    • /m2-hotfixes目录中的自定义修补程序和支持修补程序按修补程序名称的字母顺序安装。

这样,您就可以集中管理所有安装的所有修补程序,并且可以更好地保证Adobe Commerce存储的安全性和稳定性。 请使用以下方法检查修补程序状态:

代码示例

recommendation-more-help
754cbbf3-3a3c-4af3-b6ce-9d34390f3a60