Commit f569f369 authored by Kunal Sachdev's avatar Kunal Sachdev Committed by Adam G-H
Browse files

Issue #3254207 by kunal.sachdev, phenaproxima, tedbow: Only allow 1 patch...

Issue #3254207 by kunal.sachdev, phenaproxima, tedbow: Only allow 1 patch release update increment in Cron
parent e8bde5a9
Loading
Loading
Loading
Loading
+49 −1
Original line number Diff line number Diff line
@@ -95,12 +95,14 @@ class UpdateVersionValidator implements EventSubscriberInterface {
      '@to_version' => $to_version_string,
      '@from_version' => $from_version_string,
    ];
    $from_version_extra = $from_version->getVersionExtra();
    $to_version_extra = $to_version->getVersionExtra();
    if (Semver::satisfies($to_version_string, "< $from_version_string")) {
      $event->addError([
        $this->t('Update version @to_version is lower than @from_version, downgrading is not supported.', $variables),
      ]);
    }
    elseif ($from_version->getVersionExtra() === 'dev') {
    elseif ($from_version_extra === 'dev') {
      $event->addError([
        $this->t('Drupal cannot be automatically updated from its current version, @from_version, to the recommended version, @to_version, because automatic updates from a dev version to any other version are not supported.', $variables),
      ]);
@@ -122,6 +124,30 @@ class UpdateVersionValidator implements EventSubscriberInterface {
        ]);
      }
    }
    elseif ($stage instanceof CronUpdater) {
      if ($from_version_extra || $to_version_extra) {
        if ($from_version_extra) {
          $messages[] = $this->t('Drupal cannot be automatically updated during cron from its current version, @from_version, because Automatic Updates only supports updating from stable versions during cron.', $variables);
          $event->addError($messages);
        }
        if ($to_version_extra) {
          // Because we do not support updating to a new minor version during
          // cron it is probably impossible to update from a stable version to
          // a unstable/pre-release version, but we should check this condition
          // just in case.
          $messages[] = $this->t('Drupal cannot be automatically updated during cron to the recommended version, @to_version, because Automatic Updates only supports updating to stable versions during cron.', $variables);
          $event->addError($messages);
        }
      }
      else {
        $to_patch_version = (int) $this->getPatchVersion($to_version_string);
        $from_patch_version = (int) $this->getPatchVersion($from_version_string);
        if ($from_patch_version + 1 !== $to_patch_version) {
          $messages[] = $this->t('Drupal cannot be automatically updated during cron from its current version, @from_version, to the recommended version, @to_version, because Automatic Updates only supports 1 patch version update during cron.', $variables);
          $event->addError($messages);
        }
      }
    }
  }

  /**
@@ -134,4 +160,26 @@ class UpdateVersionValidator implements EventSubscriberInterface {
    ];
  }

  /**
   * Gets the patch number for a version string.
   *
   * @todo Move this method to \Drupal\Core\Extension\ExtensionVersion in
   *   https://www.drupal.org/i/3261744.
   *
   * @param string $version_string
   *   The version string.
   *
   * @return string
   *   The patch number.
   */
  private function getPatchVersion(string $version_string): string {
    $version_extra = ExtensionVersion::createFromVersionString($version_string)
      ->getVersionExtra();
    if ($version_extra) {
      $version_string = str_replace("-$version_extra", '', $version_string);
    }
    $version_parts = explode('.', $version_string);
    return $version_parts[2];
  }

}
+24 −0
Original line number Diff line number Diff line
@@ -10,6 +10,18 @@
   <term><name>Projects</name><value>Drupal project</value></term>
  </terms>
<releases>
  <release>
    <name>Drupal 9.8.2</name>
    <version>9.8.2</version>
    <status>published</status>
    <release_link>http://example.com/drupal-9-8-2-release</release_link>
    <download_link>http://example.com/drupal-9-8-2.tar.gz</download_link>
    <date>1250425521</date>
    <terms>
      <term><name>Release type</name><value>New features</value></term>
      <term><name>Release type</name><value>Bug fixes</value></term>
    </terms>
  </release>
 <release>
  <name>Drupal 9.8.1</name>
  <version>9.8.1</version>
@@ -34,5 +46,17 @@
     <term><name>Release type</name><value>Bug fixes</value></term>
   </terms>
 </release>
  <release>
    <name>Drupal 9.8.0-alpha1</name>
    <version>9.8.0-alpha1</version>
    <status>published</status>
    <release_link>http://example.com/drupal-9-8-0-alpha1-release</release_link>
    <download_link>http://example.com/drupal-9-8-0-alpha1.tar.gz</download_link>
    <date>1250424521</date>
    <terms>
      <term><name>Release type</name><value>New features</value></term>
      <term><name>Release type</name><value>Bug fixes</value></term>
    </terms>
  </release>
</releases>
</project>
+8 −6
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ class ReadinessValidationTest extends AutomaticUpdatesFunctionalTestBase {
   */
  protected function setUp(): void {
    parent::setUp();
    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.9.8.1.xml');
    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.9.8.2.xml');
    $this->setCoreVersion('9.8.1');

    $this->reportViewerUser = $this->createUser([
@@ -386,9 +386,8 @@ class ReadinessValidationTest extends AutomaticUpdatesFunctionalTestBase {
    // version.
    $this->setCoreVersion('9.8.0');

    // Flag a validation warning, which will be displayed in the messages area,
    // but not block or abort the update.
    $results = $this->testResults['checker_1']['1 warning'];
    // Flag a validation error, which will be displayed in the messages area.
    $results = $this->testResults['checker_1']['1 error'];
    TestChecker1::setTestResult($results, ReadinessCheckEvent::class);
    $message = $results[0]->getMessages()[0];

@@ -398,7 +397,7 @@ class ReadinessValidationTest extends AutomaticUpdatesFunctionalTestBase {
      'package_manager_bypass',
    ]);

    // The warning should be persistently visible, even after the checker stops
    // The error should be persistently visible, even after the checker stops
    // flagging it.
    $this->drupalGet('/admin/structure');
    $assert_session->pageTextContains($message);
@@ -407,7 +406,10 @@ class ReadinessValidationTest extends AutomaticUpdatesFunctionalTestBase {
    $assert_session->pageTextContains($message);

    // Do the update; we don't expect any errors or special conditions to appear
    // during it.
    // during it. The Update button is displayed because the form does its own
    // readiness check (without storing the results), and the checker is no
    // longer raising an error.
    // @todo Fine-tune this in https://www.drupal.org/node/3261758.
    $this->drupalGet('/admin/modules/automatic-update');
    $page->pressButton('Update');
    $this->checkForMetaRefresh();
+1 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ class UpdateLockTest extends AutomaticUpdatesFunctionalTestBase {
  protected function setUp(): void {
    parent::setUp();

    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.9.8.1.xml');
    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.9.8.2.xml');
    $this->drupalLogin($this->rootUser);
    $this->checkForUpdates();
  }
+2 −2
Original line number Diff line number Diff line
@@ -75,8 +75,8 @@ abstract class AutomaticUpdatesKernelTestBase extends KernelTestBase {

    // By default, pretend we're running Drupal core 9.8.0 and a non-security
    // update to 9.8.1 is available.
    $this->setCoreVersion('9.8.0');
    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.9.8.1.xml');
    $this->setCoreVersion('9.8.1');
    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.9.8.2.xml');

    // Set a last cron run time so that the cron frequency validator will run
    // from a sane state.
Loading