Skip to content
Snippets Groups Projects

Issue #3281397: VersionPolicyValidator should throw an exception if it can't determine the target version of Drupal

Merged Issue #3281397: VersionPolicyValidator should throw an exception if it can't determine the target version of Drupal
@@ -5,6 +5,7 @@ namespace Drupal\automatic_updates\Validator;
use Composer\Semver\Semver;
use Drupal\automatic_updates\CronUpdater;
use Drupal\automatic_updates\Event\ReadinessCheckEvent;
use Drupal\automatic_updates\Exception\UpdateException;
use Drupal\automatic_updates\ProjectInfo;
use Drupal\automatic_updates\Updater;
use Drupal\automatic_updates\Validator\VersionPolicy\ForbidDowngrade;
@@ -56,8 +57,8 @@ final class VersionPolicyValidator implements EventSubscriberInterface {
*
* @param \Drupal\automatic_updates\Updater $updater
* The updater which will perform the update.
* @param string $target_version
* The target version of Drupal core.
* @param string|null $target_version
* The target version of Drupal core, or NULL if it is not known.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
* The error messages returned from the first policy rule which rejected
@@ -65,17 +66,21 @@ final class VersionPolicyValidator implements EventSubscriberInterface {
*
* @see \Drupal\automatic_updates\Validator\VersionPolicy\RuleBase::validate()
*/
public function validateVersion(Updater $updater, string $target_version): array {
public function validateVersion(Updater $updater, ?string $target_version): array {
// Check that the installed version of Drupal isn't a dev snapshot.
$rules = [
// Check that the installed version of Drupal isn't a dev snapshot.
ForbidDevSnapshot::class,
];
// If the target version is known, it must conform to a few basic rules.
if ($target_version) {
// The target version must be newer than the installed version...
ForbidDowngrade::class,
$rules[] = ForbidDowngrade::class;
// ...and in the same major version as the installed version...
MajorVersionMatch::class,
$rules[] = MajorVersionMatch::class;
// ...and it must be a known, secure, installable release.
TargetVersionInstallable::class,
];
$rules[] = TargetVersionInstallable::class;
}
// If this is a cron update, we may need to do additional checks.
if ($updater instanceof CronUpdater) {
@@ -87,15 +92,19 @@ final class VersionPolicyValidator implements EventSubscriberInterface {
$rules[] = StableReleaseInstalled::class;
// It must also be in a supported branch.
$rules[] = SupportedBranchInstalled::class;
// The target version must be stable too...
$rules[] = TargetVersionStable::class;
// ...and it must be in the same minor as the installed version.
$rules[] = ForbidMinorUpdates::class;
// If only security updates are allowed during cron, the target
// version must be a security release.
if ($mode === CronUpdater::SECURITY) {
$rules[] = TargetSecurityRelease::class;
// If the target version is known, more rules apply.
if ($target_version) {
// The target version must be stable too...
$rules[] = TargetVersionStable::class;
// ...and it must be in the same minor as the installed version.
$rules[] = ForbidMinorUpdates::class;
// If only security updates are allowed during cron, the target
// version must be a security release.
if ($mode === CronUpdater::SECURITY) {
$rules[] = TargetSecurityRelease::class;
}
}
}
}
@@ -136,21 +145,23 @@ final class VersionPolicyValidator implements EventSubscriberInterface {
if (!$stage instanceof Updater) {
return;
}
$target_version = $this->getTargetVersion($event);
if (empty($target_version)) {
$event->addError([
$this->t('The target version of Drupal core could not be determined.'),
]);
return;
}
$messages = $this->validateVersion($stage, $target_version);
if ($messages) {
$summary = $this->t('Updating from Drupal @installed_version to @target_version is not allowed.', [
'@installed_version' => $this->getInstalledVersion(),
'@target_version' => $target_version,
]);
$installed_version = $this->getInstalledVersion();
if ($target_version) {
$summary = $this->t('Updating from Drupal @installed_version to @target_version is not allowed.', [
'@installed_version' => $installed_version,
'@target_version' => $target_version,
]);
}
else {
$summary = $this->t('Updating from Drupal @installed_version is not allowed.', [
'@installed_version' => $installed_version,
]);
}
$event->addError($messages, $summary);
}
}
@@ -177,16 +188,24 @@ final class VersionPolicyValidator implements EventSubscriberInterface {
$package_versions = $updater->getPackageVersions()['production'];
}
$unknown_target = new UpdateException([], 'The target version of Drupal core could not be determined.');
if ($package_versions) {
$core_package_name = key($updater->getActiveComposer()->getCorePackages());
return $package_versions[$core_package_name];
if (array_key_exists($core_package_name, $package_versions)) {
return $package_versions[$core_package_name];
}
else {
throw $unknown_target;
}
}
elseif ($event instanceof ReadinessCheckEvent) {
// It's okay if this returns NULL; it means there's nothing to update to.
return $this->getTargetVersionFromAvailableReleases($updater);
}
else {
return NULL;
}
// If we got here, something has gone very wrong.
throw $unknown_target;
}
/**
Loading