Skip to content
Snippets Groups Projects
Commit 08792050 authored by Lucas Hedding's avatar Lucas Hedding Committed by Lucas Hedding
Browse files

Issue #3093861 by heddn, ressa: Manual update (experimental) to 8.8.0-beta1 requires db_update

parent 7515c3a6
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,6 @@
*/
use Drupal\automatic_updates\ReadinessChecker\ReadinessCheckerManagerInterface;
use Drupal\automatic_updates\ReadinessChecker\Vendor;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
use Drupal\Core\Url;
......@@ -16,7 +15,12 @@ use Drupal\Core\Url;
function automatic_updates_requirements($phase) {
// Mimic the functionality of the vendor checker procedurally since class
// loading isn't available pre module install.
if (!file_exists(implode(DIRECTORY_SEPARATOR, [DRUPAL_ROOT, 'vendor', 'autoload.php']))) {
$vendor_autoloader = [
DRUPAL_ROOT,
'vendor',
'autoload.php',
];
if (!file_exists(implode(DIRECTORY_SEPARATOR, $vendor_autoloader))) {
return [
'not installable' => [
'title' => t('Automatic Updates'),
......
......@@ -6,6 +6,7 @@
*/
use Drupal\automatic_updates\ReadinessChecker\ReadinessCheckerManagerInterface;
use Drupal\update\UpdateManagerInterface;
/**
* Implements hook_page_top().
......@@ -84,19 +85,27 @@ function automatic_updates_cron() {
if ($config->get('enable_cron_updates')) {
\Drupal::service('update.manager')->refreshUpdateData();
$available = update_get_available(TRUE);
$data = update_calculate_project_data($available);
$not_recommended = $data['drupal']['existing_version'] !== $data['drupal']['recommended'];
$projects = update_calculate_project_data($available);
$not_recommended_version = $projects['drupal']['status'] !== UpdateManagerInterface::CURRENT;
$dev_core = strpos(\Drupal::VERSION, '-dev') !== FALSE;
$security_update = in_array($projects['drupal']['status'], [UpdateManagerInterface::NOT_SECURE, UpdateManagerInterface::REVOKED], TRUE);
$recommended_release = $projects['drupal']['releases'][$projects['drupal']['recommended']];
$major_upgrade = $recommended_release['version_major'] !== $projects['drupal']['existing_major'];
// Don't automatically update major version bumps or a dev version of core.
if ($major_upgrade || $dev_core) {
return;
}
if ($config->get('enable_cron_security_updates')) {
if ($not_recommended && isset($data['drupal']['security updates'])) {
if ($not_recommended_version && $security_update) {
/** @var \Drupal\automatic_updates\Services\UpdateInterface $updater */
$updater = \Drupal::service('automatic_updates.update');
$updater->update('drupal', 'core', \Drupal::VERSION, $data['drupal']['latest_version']);
$updater->update('drupal', 'core', \Drupal::VERSION, $recommended_release['version']);
}
}
elseif ($not_recommended) {
elseif ($not_recommended_version) {
/** @var \Drupal\automatic_updates\Services\UpdateInterface $updater */
$updater = \Drupal::service('automatic_updates.update');
$updater->update('drupal', 'core', \Drupal::VERSION, $data['drupal']['latest_version']);
$updater->update('drupal', 'core', \Drupal::VERSION, $recommended_release['version']);
}
}
}
......
......@@ -5,6 +5,7 @@ namespace Drupal\automatic_updates\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\update\UpdateManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -112,10 +113,12 @@ class SettingsForm extends ConfigFormBase {
$this->updateManager->refreshUpdateData();
$available = update_get_available(TRUE);
$data = update_calculate_project_data($available);
$not_recommended = $data['drupal']['existing_version'] !== $data['drupal']['recommended'];
$security_update = isset($data['drupal']['security updates']);
$no_dev_core = strpos(\Drupal::VERSION, '-dev') === FALSE;
$projects = update_calculate_project_data($available);
$not_recommended_version = $projects['drupal']['status'] !== UpdateManagerInterface::CURRENT;
$not_dev_core = strpos(\Drupal::VERSION, '-dev') === FALSE;
$security_update = in_array($projects['drupal']['status'], [UpdateManagerInterface::NOT_SECURE, UpdateManagerInterface::REVOKED], TRUE);
$recommended_release = $projects['drupal']['releases'][$projects['drupal']['recommended']];
$major_upgrade = $recommended_release['version_major'] !== $projects['drupal']['existing_major'];
$form['experimental'] = [
'#type' => 'details',
'#title' => $this->t('Experimental'),
......@@ -125,22 +128,31 @@ class SettingsForm extends ConfigFormBase {
],
],
];
if ($not_recommended && $security_update && $no_dev_core) {
$form['experimental']['security'] = [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $this->t('A security update is available for your version of Drupal.'),
];
if ($not_recommended_version && $not_dev_core) {
if ($security_update) {
$form['experimental']['security'] = [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $this->t('A security update is available for your version of Drupal.'),
];
}
if ($major_upgrade) {
$form['experimental']['major_version'] = [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $this->t('This update is a major version update which means that it may not be backwards compatible with your currently running version. It is recommended that you read the release notes and proceed at your own risk.'),
];
}
}
$update_text = $this->t('Your site is running %version of Drupal core. No recommended update is available at this time.</i>', ['%version' => \Drupal::VERSION]);
if ($not_recommended && $no_dev_core) {
if ($not_recommended_version && $not_dev_core) {
$update_text = $this->t('Even with all that caution, if you want to try it out, <a href="@link">manually update now</a>.', [
'@link' => Url::fromRoute('automatic_updates.inplace-update', [
'project' => 'drupal',
'type' => 'core',
'from' => \Drupal::VERSION,
'to' => $data['drupal']['latest_version'],
'to' => $recommended_release['version'],
])->toString(),
]);
}
......
......@@ -40,7 +40,7 @@ trait ProjectInfoTrait {
$file_paths = $this->getExtensionList($extension_type)->getPathnames();
$infos = $this->getExtensionList($extension_type)->getAllAvailableInfo();
array_walk($infos, function (array &$info, $key) use ($file_paths) {
$info['packaged'] = isset($info['project']) ? $info['project'] : FALSE;
$info['packaged'] = isset($info['datestamp']) ? $info['datestamp'] : FALSE;
$info['install path'] = $file_paths[$key] ? dirname($file_paths[$key]) : '';
$info['project'] = $this->getProjectName($key, $info);
$info['version'] = $this->getExtensionVersion($info);
......
......@@ -52,46 +52,13 @@ class InPlaceUpdateTest extends QuickStartTestBase {
* @dataProvider coreVersionsProvider
*/
public function testCoreUpdate($from_version, $to_version) {
$this->copyCodebase();
// We have to fetch the tags for this shallow repo. It might not be a
// shallow clone, therefore we use executeCommand instead of assertCommand.
$this->executeCommand('git fetch --unshallow --tags');
$this->executeCommand('git reset HEAD --hard');
$this->assertCommandSuccessful();
$this->executeCommand("git checkout $from_version -f");
$this->assertCommandSuccessful();
$fs = new SymfonyFilesystem();
$fs->chmod($this->getWorkspaceDirectory() . '/sites/default', 0700, 0000);
$this->executeCommand('COMPOSER_DISCARD_CHANGES=true composer install --no-dev --no-interaction');
$this->assertErrorOutputContains('Generating autoload files');
$this->installQuickStart('minimal');
// Currently, this test has to use extension_discovery_scan_tests so we can
// install test modules.
$fs->chmod($this->getWorkspaceDirectory() . '/sites/default/settings.php', 0640, 0000);
file_put_contents($this->getWorkspaceDirectory() . '/sites/default/settings.php', '$settings[\'extension_discovery_scan_tests\'] = TRUE;' . PHP_EOL, FILE_APPEND);
// Log in so that we can install modules.
$this->formLogin($this->adminUsername, $this->adminPassword);
$this->moduleInstall('update');
$this->moduleInstall('automatic_updates');
$this->moduleInstall('test_automatic_updates');
// Confirm we are running correct Drupal version.
$finder = new Finder();
$finder->files()->in($this->getWorkspaceDirectory())->path('core/lib/Drupal.php');
$finder->contains("/const VERSION = '$from_version'/");
$this->assertTrue($finder->hasResults());
$this->installCore($from_version);
// Assert files slated for deletion still exist.
foreach ($this->getDeletions('drupal', $from_version, $to_version) as $deletion) {
$this->assertFileExists($this->getWorkspaceDirectory() . DIRECTORY_SEPARATOR . $deletion);
}
// Assert that the site is functional before updating.
$this->visit();
$this->assertDrupalVisit();
// Update the site.
$assert = $this->visit("/test_automatic_updates/in-place-update/drupal/core/$from_version/$to_version")
->assertSession();
......@@ -118,6 +85,7 @@ class InPlaceUpdateTest extends QuickStartTestBase {
* @dataProvider contribProjectsProvider
*/
public function testContribUpdate($project, $project_type, $from_version, $to_version) {
$this->markTestSkipped('Contrib updates are not currently supported');
$this->copyCodebase();
$fs = new SymfonyFilesystem();
$fs->chmod($this->getWorkspaceDirectory() . '/sites/default', 0700, 0000);
......@@ -175,6 +143,77 @@ class InPlaceUpdateTest extends QuickStartTestBase {
}
}
/**
* Test in-place update via cron run.
*
* @covers ::update
* @see automatic_updates_cron()
*/
public function testCronCoreUpdate() {
$this->installCore('8.7.6');
$filesystem = new SymfonyFilesystem();
$filesystem->chmod($this->getWorkspaceDirectory() . '/sites/default', 0750, 0000);
$settings_php = $this->getWorkspaceDirectory() . '/sites/default/settings.php';
$filesystem->chmod($settings_php, 0640);
$filesystem->appendToFile($settings_php, PHP_EOL . '$config[\'automatic_updates.settings\'][\'enable_cron_updates\'] = TRUE;' . PHP_EOL);
$mink = $this->visit('/admin/config/system/cron');
$mink->getSession()->getPage()->findButton('Run cron')->submit();
$mink->assertSession()->pageTextContains('Cron ran successfully.');
// Assert that the update worked.
$this->assertDrupalVisit();
$finder = new Finder();
$finder->files()->in($this->getWorkspaceDirectory())->path('core/lib/Drupal.php');
$finder->notContains("/const VERSION = '8.7.6'/");
$finder->contains("/const VERSION = '8.7./");
$this->assertTrue($finder->hasResults());
}
/**
* Prepare core for testing.
*
* @param string $starting_version
* The starting version.
*/
protected function installCore($starting_version) {
$this->copyCodebase();
// We have to fetch the tags for this shallow repo. It might not be a
// shallow clone, therefore we use executeCommand instead of assertCommand.
$this->executeCommand('git fetch --unshallow --tags');
$this->executeCommand('git reset HEAD --hard');
$this->assertCommandSuccessful();
$this->executeCommand("git checkout $starting_version -f");
$this->assertCommandSuccessful();
$this->executeCommand('git reset HEAD --hard');
$this->assertCommandSuccessful();
$fs = new SymfonyFilesystem();
$fs->chmod($this->getWorkspaceDirectory() . '/sites/default', 0700, 0000);
$this->executeCommand('COMPOSER_DISCARD_CHANGES=true composer install --no-dev --no-interaction');
$this->assertErrorOutputContains('Generating autoload files');
$this->installQuickStart('minimal');
// Currently, this test has to use extension_discovery_scan_tests so we can
// install test modules.
$fs->chmod($this->getWorkspaceDirectory() . '/sites/default/settings.php', 0640, 0000);
file_put_contents($this->getWorkspaceDirectory() . '/sites/default/settings.php', '$settings[\'extension_discovery_scan_tests\'] = TRUE;' . PHP_EOL, FILE_APPEND);
// Log in so that we can install modules.
$this->formLogin($this->adminUsername, $this->adminPassword);
$this->moduleInstall('update');
$this->moduleInstall('automatic_updates');
$this->moduleInstall('test_automatic_updates');
// Confirm we are running correct Drupal version.
$finder = new Finder();
$finder->files()->in($this->getWorkspaceDirectory())->path('core/lib/Drupal.php');
$finder->contains("/const VERSION = '$starting_version'/");
$this->assertTrue($finder->hasResults());
// Assert that the site is functional after install.
$this->visit();
$this->assertDrupalVisit();
}
/**
* Core versions data provider.
*/
......@@ -183,26 +222,6 @@ class InPlaceUpdateTest extends QuickStartTestBase {
'from' => '8.7.0',
'to' => '8.7.1',
];
$datum[] = [
'from' => '8.7.1',
'to' => '8.7.2',
];
$datum[] = [
'from' => '8.7.2',
'to' => '8.7.3',
];
$datum[] = [
'from' => '8.7.3',
'to' => '8.7.4',
];
$datum[] = [
'from' => '8.7.4',
'to' => '8.7.5',
];
$datum[] = [
'from' => '8.7.5',
'to' => '8.7.6',
];
$datum[] = [
'from' => '8.7.6',
'to' => '8.7.7',
......
......@@ -59,6 +59,7 @@ class ModifiedFilesTest extends QuickStartTestBase {
* @dataProvider contribProjectsProvider
*/
public function testContribModified($project, $project_type, $version, array $modifications = []) {
$this->markTestSkipped('Contrib updates are not currently supported');
$this->copyCodebase();
// Download the project.
......@@ -125,11 +126,9 @@ class ModifiedFilesTest extends QuickStartTestBase {
// Currently, this test has to use extension_discovery_scan_tests so we can
// install test modules.
$this->symfonyFileSystem->chmod($this->getWorkspaceDirectory() . '/sites/default', 0750, 0000);
$this->symfonyFileSystem->chmod($this->getWorkspaceDirectory() . '/sites/default/settings.php', 0640, 0000);
$settings_php = $this->getWorkspaceDirectory() . '/sites/default/settings.php';
$this->symfonyFileSystem->chmod($settings_php, 0640);
$this->symfonyFileSystem->appendToFile($settings_php, PHP_EOL . '$settings[\'extension_discovery_scan_tests\'] = TRUE;' . PHP_EOL);
// Intentionally mark composer.json and composer.lock as ignored.
$this->symfonyFileSystem->appendToFile($settings_php, PHP_EOL . '$config[\'automatic_updates.settings\'][\'ignored_paths\'] = "composer.json\ncomposer.lock\nmodules/custom/*\nthemes/custom/*\nprofiles/custom/*";' . PHP_EOL);
// Restart server for config override to apply.
$this->stopServer();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment