Commit 3cb9eeba authored by Adam G-H's avatar Adam G-H
Browse files

Issue #3293381 by phenaproxima, tedbow: If cweagans/composer-patches is...

Issue #3293381 by phenaproxima, tedbow: If cweagans/composer-patches is installed, require composer-exit-on-patch-failure
parent cfd7b366
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -101,6 +101,12 @@ services:
      - '@package_manager.validator.symlink'
    tags:
      - { name: event_subscriber }
  automatic_updates.validator.patches:
    class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
    arguments:
      - '@package_manager.validator.patches'
    tags:
      - { name: event_subscriber }
  automatic_updates.cron_frequency_validator:
    class: Drupal\automatic_updates\Validator\CronFrequencyValidator
    arguments:
+3 −8
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ use Drupal\automatic_updates\Event\ReadinessCheckEvent;
use Drupal\automatic_updates_test\EventSubscriber\TestSubscriber1;
use Drupal\package_manager\Event\PreApplyEvent;
use Drupal\package_manager\ValidationResult;
use Drupal\package_manager_bypass\Beginner;
use Drupal\Tests\automatic_updates\Functional\AutomaticUpdatesFunctionalTestBase;
use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait;
use Drupal\Tests\automatic_updates_extensions\Traits\FormTestTrait;
@@ -140,14 +141,6 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
   * @dataProvider providerSuccessfulUpdate
   */
  public function testSuccessfulUpdate(bool $maintenance_mode_on, string $project_name, string $installed_version, string $target_version): void {
    // Disable the scaffold file permissions and target release validators
    // because they will try to read composer.json from the staging area,
    // which won't exist because Package Manager is bypassed.
    $this->disableValidators([
      'automatic_updates.validator.scaffold_file_permissions',
      'automatic_updates_extensions.validator.target_release',
    ]);

    $this->container->get('theme_installer')->install(['automatic_updates_theme_with_updates']);
    $this->updateProject = $project_name;
    $this->setReleaseMetadata(__DIR__ . '/../../../../tests/fixtures/release-history/drupal.9.8.2.xml');
@@ -157,6 +150,8 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
    $state = $this->container->get('state');
    $state->set('system.maintenance_mode', $maintenance_mode_on);

    Beginner::setFixturePath(__DIR__ . '/../../fixtures/fake-site');

    $page = $this->getSession()->getPage();
    // Navigate to the automatic updates form.
    $this->drupalGet('/admin/reports/updates');
+4 −0
Original line number Diff line number Diff line
@@ -156,3 +156,7 @@ services:
      - '@string_translation'
    tags:
      - { name: event_subscriber }
  package_manager.validator.patches:
    class: Drupal\package_manager\Validator\ComposerPatchesValidator
    tags:
      - { name: event_subscriber }
+48 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\package_manager\Validator;

use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\Event\PreOperationStageEvent;

/**
 * Validates the configuration of the cweagans/composer-patches plugin.
 */
class ComposerPatchesValidator implements PreOperationStageValidatorInterface {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public function validateStagePreOperation(PreOperationStageEvent $event): void {
    $stage = $event->getStage();
    $composer = $stage->getActiveComposer();

    if (array_key_exists('cweagans/composer-patches', $composer->getInstalledPackages())) {
      $composer = $composer->getComposer();

      $extra = $composer->getPackage()->getExtra();
      if (empty($extra['composer-exit-on-patch-failure'])) {
        $event->addError([
          $this->t('The <code>cweagans/composer-patches</code> plugin is installed, but the <code>composer-exit-on-patch-failure</code> key is not set to <code>true</code> in the <code>extra</code> section of @file.', [
            // If composer.json is in a virtual file system, Composer will not
            // be able to resolve a real path for it.
            '@file' => $composer->getConfig()->getConfigSource()->getName() ?: 'composer.json',
          ]),
        ]);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      PreCreateEvent::class => 'validateStagePreOperation',
    ];
  }

}
+47 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\package_manager\Kernel;

use Composer\Json\JsonFile;
use Drupal\package_manager\Exception\StageValidationException;
use Drupal\package_manager\ValidationResult;

/**
 * @covers \Drupal\package_manager\Validator\ComposerPatchesValidator
 *
 * @group package_manager
 */
class ComposerPatchesValidatorTest extends PackageManagerKernelTestBase {

  /**
   * Tests that the patcher configuration is validated during pre-create.
   */
  public function testPreCreate(): void {
    // Simulate an active directory where the patcher is installed, but there's
    // no composer-exit-on-patch-failure flag.
    $dir = $this->container->get('package_manager.path_locator')
      ->getProjectRoot();

    // Simulate that the patcher is installed in the active directory.
    $file = new JsonFile($dir . '/vendor/composer/installed.json');
    $this->assertTrue($file->exists());
    $data = $file->read();
    $data['packages'][] = [
      'name' => 'cweagans/composer-patches',
      'version' => '1.0.0',
    ];
    $file->write($data);

    $error = ValidationResult::createError([
      'The <code>cweagans/composer-patches</code> plugin is installed, but the <code>composer-exit-on-patch-failure</code> key is not set to <code>true</code> in the <code>extra</code> section of composer.json.',
    ]);
    try {
      $this->createStage()->create();
      $this->fail('Expected a validation error.');
    }
    catch (StageValidationException $e) {
      $this->assertValidationResultsEqual([$error], $e->getResults());
    }
  }

}
Loading