Skip to content
Snippets Groups Projects
Commit fb6d0d7f authored by Adam G-H's avatar Adam G-H Committed by Ted Bowman
Browse files

Issue #3314137 by Wim Leers, phenaproxima, tedbow: Make Automatic Updates Drupal 10-compatible

parent 6bf619d5
No related branches found
No related tags found
No related merge requests found
Showing
with 109 additions and 20 deletions
name: 'Automatic Updates'
type: module
description: 'Automatically updates Drupal core.'
core_version_requirement: ^9.3
core_version_requirement: ^9.3 || ^10
dependencies:
- drupal:package_manager
- drupal:update
......@@ -164,6 +164,12 @@ function automatic_updates_module_implements_alter(&$implementations, $hook) {
* Implements hook_cron().
*/
function automatic_updates_cron() {
// @todo Refactor this after https://www.drupal.org/project/drupal/issues/2969056
// @todo Remove this after https://www.drupal.org/project/drupal/issues/3318964
if (defined('MAINTENANCE_MODE') || stripos($_SERVER['PHP_SELF'], 'update.php') !== FALSE) {
return;
}
/** @var \Drupal\automatic_updates\CronUpdater $updater */
$updater = \Drupal::service('automatic_updates.cron_updater');
$updater->handleCron();
......
name: 'Automatic Updates Extensions'
type: module
description: 'Allows updates to themes and modules'
core_version_requirement: ^9.3
core_version_requirement: ^9.3 || ^10
lifecycle: experimental
dependencies:
- drupal:automatic_updates
name: 'New module'
type: module
core_version_requirement: ^9
core_version_requirement: ^9 || ^10
project: new_module
name: 'New module'
type: module
core_version_requirement: ^9
core_version_requirement: ^9 || ^10
project: new_module
......@@ -12,7 +12,7 @@
},
"require": {
"ext-json": "*",
"drupal/core": "^9.3",
"drupal/core": "^9.3 || ^10",
"php-tuf/composer-stager": "^1.2",
"composer/composer": "^2.2.12 || ^2.3.5",
"composer-runtime-api": "^2.1",
......@@ -39,6 +39,9 @@
"phpcs": "Checks code for standards compliance.",
"test": "Runs PHPUnit tests.",
"core-convert": "Converts this module to a core merge request. Excepts 2 arguments. 1) The core clone directory. 2) The core merge request branch."
},
"require-dev": {
"colinodell/psr-testlogger": "^1"
},
"autoload": {
"psr-4": {
......
unrequested
updater's
stager's
syncer
syncers
unrequested
kirk
colinodell
testlogger
unwritable
filedate
......@@ -32,6 +32,8 @@ build:
- sed -i "s/yarn run -s spellcheck/yarn run -s spellcheck --root \$TOP_LEVEL/" modules/contrib/automatic_updates/commit-code-check.sh
# Add our words to the dictionary.
- cat modules/contrib/automatic_updates/dictionary.txt >> core/misc/cspell/dictionary.txt
# Ensure we have the full path to PHPStan.
- sed -i "s/vendor\/bin\/phpstan/\/var\/www\/html\/vendor\/bin\/phpstan/" modules/contrib/automatic_updates/commit-code-check.sh
# After all of the shenanigans above, we're finally ready to run core's `commit-code-check.sh`! :)
- "modules/contrib/automatic_updates/commit-code-check.sh --drupalci"
# Restore the original permissions.
......
name: 'Package Manager'
type: module
description: 'API module providing functionality for staging package installs and updates with Composer.'
core_version_requirement: ^9.3
core_version_requirement: ^9.3 || ^10
php: 7.4
dependencies:
- drupal:update
......@@ -8,6 +8,7 @@ use Composer\IO\NullIO;
use Composer\Package\Loader\ValidatingArrayLoader;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\PartialComposer;
use Composer\Semver\Comparator;
use Drupal\Component\Serialization\Yaml;
......@@ -30,23 +31,46 @@ class ComposerUtility {
*/
private static $corePackages;
/**
* Whether to raise a deprecation error when the constructor is called.
*
* @var bool
*/
private static $triggerConstructorDeprecation = TRUE;
/**
* Constructs a new ComposerUtility object.
*
* @param \Composer\Composer $composer
* @param \Composer\Composer|\Composer\PartialComposer $composer
* The Composer instance.
*/
public function __construct(Composer $composer) {
public function __construct(object $composer) {
// @todo Remove this in https://www.drupal.org/project/automatic_updates/issues/3321474.
if (self::$triggerConstructorDeprecation) {
@trigger_error(__METHOD__ . '() is deprecated in automatic_updates:8.x-2.5 and will be removed in automatic_updates:3.0.0. Use ' . __CLASS__ . '::createForDirectory() instead. See https://www.drupal.org/node/3314137.', E_USER_DEPRECATED);
}
self::$triggerConstructorDeprecation = TRUE;
// @todo Remove this check when either:
// - PHP 8 or later is required, in which case the $composer type hint
// should be Composer|PartialComposer.
// - Composer 2.3 or later is required, in which case the $composer type
// hint should be changed to PartialComposer.
// @todo Update in https://www.drupal.org/project/automatic_updates/issues/3321474
// @todo Update in https://www.drupal.org/project/automatic_updates/issues/3321476
if (!$composer instanceof Composer && !$composer instanceof PartialComposer) {
throw new \InvalidArgumentException('The $composer argument must be an instance of ' . Composer::class . ' or ' . PartialComposer::class);
}
$this->composer = $composer;
}
/**
* Returns the underlying Composer instance.
*
* @return \Composer\Composer
* @return \Composer\Composer|\Composer\PartialComposer
* The Composer instance.
*/
public function getComposer(): Composer {
public function getComposer(): object {
return $this->composer;
}
......@@ -58,10 +82,21 @@ class ComposerUtility {
*
* @return \Drupal\package_manager\ComposerUtility
* The utility object.
*
* @throws \InvalidArgumentException
* When $dir does not contain a composer.json file.
*/
public static function createForDirectory(string $dir): self {
$io = new NullIO();
// Pre-load the contents of composer.json so that Factory::createComposer()
// won't try to call realpath(), which will fail if composer.json is in a
// virtual file system.
$configuration = $dir . DIRECTORY_SEPARATOR . 'composer.json';
if (file_exists($configuration)) {
$configuration = file_get_contents($configuration);
$configuration = json_decode($configuration, TRUE, 512, JSON_THROW_ON_ERROR);
}
// The Composer factory requires that either the HOME or COMPOSER_HOME
// environment variables be set, so momentarily set the COMPOSER_HOME
......@@ -87,6 +122,7 @@ class ComposerUtility {
putenv("COMPOSER_HOME=$home");
putenv("COMPOSER_HTACCESS_PROTECT=$htaccess");
self::$triggerConstructorDeprecation = FALSE;
return new static($composer);
}
......
name: Alpha
type: module
core_version_requirement: ^9
core_version_requirement: ^9 || ^10
project: alpha
name: Alpha
type: module
core_version_requirement: ^9
core_version_requirement: ^9 || ^10
project: alpha
<?php
/**
* @file
* Contains a fake database post-update function for testing.
*/
/**
* Here is a fake post-update hook.
*/
function package_manager_post_update_test() {
}
......@@ -217,6 +217,13 @@ END;
// Disable Packagist entirely so that we don't test the Internet.
$this->runComposer('composer config repo.packagist.org false', $template_dir);
// Allow any version of the Drupal core packages in the template project.
$this->runComposer('composer require --no-update drupal/core-recommended:* drupal/core-project-message:* drupal/core-composer-scaffold:*', $template_dir);
$this->runComposer('composer require --no-update --dev drupal/core-dev:*', $template_dir);
if ($template === 'LegacyProject') {
$this->runComposer('composer require --no-update drupal/core-vendor-hardening:*', $template_dir);
}
// Create the test project, defining its repository as part of the
// `composer create-project` command.
$repository = [
......@@ -327,6 +334,11 @@ END;
$package['require']['symfony/polyfill-php72'],
$package['require']['symfony/polyfill-php73']
);
// If we're running on Drupal 10, which requires PHP 8.1 or later, this
// polyfill won't be installed, so make sure it's not required.
if (str_starts_with(\Drupal::VERSION, '10.')) {
unset($package['require']['symfony/polyfill-php80']);
}
// Disabling symlinks in the transport options doesn't seem to have an
// effect, so we use the COMPOSER_MIRROR_PATH_REPOS environment variable
// to force mirroring in ::createTestProject().
......
......@@ -32,8 +32,11 @@ class ComposerPatchesValidatorTest extends PackageManagerKernelTestBase {
];
$file->write($data);
// Because ComposerUtility reads composer.json and passes it to the Composer
// factory as an array, Composer will assume that the configuration is
// coming from a config.json file, even if one doesn't exist.
$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.',
"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 $dir/config.json.",
]);
$this->assertStatusCheckResults([$error]);
$this->assertResults([$error], PreCreateEvent::class);
......
......@@ -32,6 +32,17 @@ class ComposerUtilityTest extends KernelTestBase {
static::copyFixtureFilesTo(__DIR__ . '/../../fixtures/project_package_conversion', $fixture->url());
}
/**
* Tests that ComposerUtility::CreateForDirectory() validates the directory.
*/
public function testCreateForDirectoryValidation(): void {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Composer could not find the config file: vfs://root/composer.json');
$dir = vfsStream::setup()->url();
ComposerUtility::createForDirectory($dir);
}
/**
* Tests that ComposerUtility disables automatic creation of .htaccess files.
*/
......
......@@ -24,7 +24,7 @@ class ExecutableFinderTest extends PackageManagerKernelTestBase {
/**
* {@inheritdoc}
*/
public function find($name, $default = NULL, array $extraDirs = []) {
public function find($name, $default = NULL, array $extraDirs = []): ?string {
return '/dev/null';
}
......
......@@ -76,8 +76,9 @@ abstract class PackageManagerKernelTestBase extends KernelTestBase {
$this->createVirtualProject();
// The Update module's default configuration must be installed for our
// fake release metadata to be fetched.
$this->installConfig('update');
// fake release metadata to be fetched, and the System module's to ensure
// the site has a name.
$this->installConfig(['system', 'update']);
// Make the update system think that all of System's post-update functions
// have run.
......
......@@ -52,8 +52,9 @@ class PendingUpdatesValidatorTest extends PackageManagerKernelTestBase {
*/
public function testPendingPostUpdate(): void {
$this->registerPostUpdateFunctions();
// The System module's post-update functions have not been registered, so
// the update registry will think they're pending.
// Make an additional post-update function available; the update registry
// will think it's pending.
require_once __DIR__ . '/../../fixtures/post_update.php';
$result = ValidationResult::createError([
'Some modules have database schema updates to install. You should run the <a href="/update.php">database update script</a> immediately.',
]);
......
......@@ -11,7 +11,7 @@ use Drupal\package_manager\Exception\StageOwnershipException;
use Drupal\package_manager_bypass\Stager;
use Drupal\package_manager_test_validation\EventSubscriber\TestSubscriber;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Psr\Log\Test\TestLogger;
use ColinODell\PsrTestLogger\TestLogger;
/**
* Tests that ownership of the stage is enforced.
......
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