Skip to content

Commit

Permalink
Merge pull request #1 from magento-borg/COMOPS-890-cloud-support
Browse files Browse the repository at this point in the history
COMOPS-890: Cloud Support
  • Loading branch information
pdohogne-magento authored Dec 15, 2020
2 parents b9ff85e + 6f362f8 commit 5807d6e
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 59 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

## Purpose of plugin

The `magento/composer-root-update-plugin` Composer plugin resolves changes that need to be made to the root project `composer.json` file before updating to a new Magento product requirement.
The `magento/composer-root-update-plugin` Composer plugin resolves changes that need to be made to the root project `composer.json` file before updating to a new Magento metapackage requirement.

This is accomplished by comparing the root `composer.json` file for the Magento project corresponding to the Magento version and edition in the current installation with the Magento project `composer.json` file for the target Magento product package when the `composer require` command runs and applying any deltas found between the two files if they do not conflict with the existing `composer.json` file in the Magento root directory.
This is accomplished by comparing the root `composer.json` file for the Magento project corresponding to the Magento version and edition in the current installation with the Magento project `composer.json` file for the target Magento metapackage when the `composer require` command runs and applying any deltas found between the two files if they do not conflict with the existing `composer.json` file in the Magento root directory.

# Getting Started

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"AFL-3.0"
],
"require": {
"composer/composer": "<=1.10.6",
"composer/composer": "<=1.10.15",
"composer-plugin-api": "^1.0"
},
"require-dev": {
Expand Down
24 changes: 16 additions & 8 deletions docs/class_descriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Classes in this namespace tie into the Composer library's code that handles plug

This class is the entrypoint into the plugin's functionality from the `composer require` CLI command.

Extends the native [RequireCommand](https://getcomposer.org/apidoc/master/Composer/Command/RequireCommand.html) functionality to add additional processing when run with a Magento product as one of the command's parameters.
Extends the native [RequireCommand](https://getcomposer.org/apidoc/master/Composer/Command/RequireCommand.html) functionality to add additional processing when run with a Magento product or cloud metapackage as one of the command's parameters.

- **`configure()`**
- Add the options and description for the plugin functionality to those already configured in `RequireCommand` and sets the new command's name to a dummy unique value so it passes Composer's command registry check
Expand All @@ -67,8 +67,10 @@ Extends the native [RequireCommand](https://getcomposer.org/apidoc/master/Compos
- Wraps the native `RequireCommand::execute()` function with the Magento project update code
- **`runUpdate()`**
- Calls [MagentoRootUpdater::runUpdate()](#magentorootupdater) after processing CLI options
- **`convertBaseEditionOption()`**
- Validates the base edition option value and convert it to the internal edition designator
- **`parseMagentoRequirement()`**
- Parses the CLI command arguments for a magento/product requirement
- Parses the CLI command arguments for a Magento product or cloud metapackage requirement

#### [**Commands\UpdatePluginNamespaceCommands**](../src/Magento/ComposerRootUpdatePlugin/Plugin/Commands/UpdatePluginNamespaceCommands.php)

Expand Down Expand Up @@ -199,15 +201,15 @@ This class runs [DeltaResolver::resolveRootDeltas()](#deltaresolver) if an updat
This class contains methods to retrieve Composer [Package](https://getcomposer.org/apidoc/master/Composer/Package/Package.html) objects for the target Magento root project package, the original (default) Magento root project package for the currently-installed Magento version, and the currently-installed root project package (including all user customizations).

- **`getOriginalRootPackage()`**
- Fetches the original (default) Magento root project package from the Composer repository
- Fetches the original (default) Magento root project package from the Composer repository or GitHub (in the case of cloud)
- **`getTargetRootPackage()`**
- Fetches the target Magento root project package from the Composer repository
- Fetches the target Magento root project package from the Composer repository or GitHub (in the case of cloud)
- **`getUserRootPackage()`**
- Returns the existing root project package, including all user customizations
- **`fetchMageRootFromRepo()`**
- Given a Magento edition and version constraint, fetch the best-fit Magento root project package from the Composer repository
- Given a Magento edition and version constraint, fetch the best-fit Magento root project package from the Composer repository or GitHub (in the case of cloud)
- **`parseVersionAndEditionFromLock()`**
- Inspect the `composer.lock` file for the currently-installed Magento product package and parse out the edition and version for use by `getOriginalRootPackage()`
- Inspect the `composer.lock` file for the currently-installed Magento product or cloud metapackage and parse out the edition and version for use by `getOriginalRootPackage()`
- **`getTargetLabel()`**
- Gets the formatted label for the target Magento version
- **`getOriginalLabel()`**
Expand Down Expand Up @@ -238,15 +240,21 @@ Common package-related utility functions.

- **`getMagentoPackageType()`**
- Extracts the package type (`product` or `project`) from a Magento package name
- Not applicable for cloud
- **`getMagentoProductEdition()`**
- Extracts the package edition from a Magento product package name
- Extracts the package edition from a Magento product or cloud metapackage name
- For the purposes of this plugin, 'cloud' is considered an edition
- **`getProjectPackageName()`**
- Constructs the project package name from an edition
- **`getMetapackageName()`**
- Constructs the metapackage name from an edition
- **`getEditionLabel()`**
- Translates package edition into the marketing edition label
- **`findRequire()`**
- Searches the `"require"` section of a [Composer](https://getcomposer.org/apidoc/master/Composer/Composer.html) object for a package link that fits the supplied name or matcher
- **`isConstraintStrict()`**
- Checks if a version constraint is strict or if it allows multiple versions (such as `~1.0` or `>= 1.5.3`)
- **`getLockedProduct()`**
- Gets the installed magento/product package from the composer.lock file if it exists
- Gets the installed Magento product or cloud metapackage from the composer.lock file if it exists
- **`getRootLocker()`**
- Helper function to get the [Locker](https://getcomposer.org/apidoc/master/Composer/Package/Locker.html) object for the `composer.lock` file in the project root directory. If the current working directory is `var` (which is the case for the Web Setup Wizard), instead use the `composer.lock` file in the parent directory
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,14 @@ protected function configure()
null,
InputOption::VALUE_REQUIRED,
'Edition of the initially-installed Magento product to use as the base for composer.json updates. ' .
'Valid values: \'Open Source\', \'Commerce\''
'Not valid for Magento Cloud upgrades. Valid values: \'Open Source\', \'Commerce\''
)
->addOption(
static::BASE_VERSION_OPT,
null,
InputOption::VALUE_REQUIRED,
'Version of the initially-installed Magento product to use as the base for composer.json updates.'
'Version of the initially-installed Magento product or cloud metapackage to use as the base for ' .
'composer.json updates.'
);

$mageHelp = '
Expand All @@ -122,7 +123,7 @@ protected function configure()
With <info>' . PluginDefinition::PACKAGE_NAME . "</info> installed, <info>$origName</info> will also check for and
execute any changes to the root composer.json file that exist between the Magento
project package corresponding to the currently-installed version and the project
for the target Magento product version if the package requirement has changed.
for the target Magento metapackage version if the package requirement has changed.
By default, any changes that would affect values that have been customized in the
existing installation will not be applied. Using <info>--" . static::OVERRIDE_OPT . '</info> will instead
Expand Down Expand Up @@ -186,7 +187,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}

/**
* Checks the package arguments for a Magento product package and run the update if one is found
* Checks the package arguments for a Magento metapackage and run the update if one is found
*
* Returns true if an update was attempted successfully
*
Expand All @@ -202,13 +203,7 @@ protected function runUpdate($input)
$overrideEdition = $input->getOption(static::BASE_EDITION_OPT);
$overrideVersion = $input->getOption(static::BASE_VERSION_OPT);
if ($overrideEdition) {
$overrideEdition = strtolower($overrideEdition);
if ($overrideEdition !== 'open source' && $overrideEdition !== 'commerce') {
$opt = '--' . static::BASE_EDITION_OPT;
throw new InvalidOptionException("'$opt' accepts only 'Open Source' or 'Commerce'");
}
$overrideEdition = $overrideEdition == 'open source' ?
PackageUtils::OPEN_SOURCE_PKG_EDITION : PackageUtils::COMMERCE_PKG_EDITION;
$overrideEdition = $this->convertBaseEditionOption($edition, $overrideEdition);
}

$updater = new MagentoRootUpdater($this->console, $this->getComposer());
Expand Down Expand Up @@ -253,7 +248,31 @@ protected function runUpdate($input)
}

/**
* Check if the plugin should run and parses the package arguments for a magento/product requirement if so
* Helper function to validate the BASE_EDITION_OPT option value and convert it to the internal edition
*
* 'open source' -> community, 'commerce' -> enterprise
*
* @param string $currentEdition
* @param string $overrideEdition
* @return string
*/
protected function convertBaseEditionOption($currentEdition, $overrideEdition)
{
if ($currentEdition == PackageUtils::CLOUD_PKG_EDITION) {
$opt = '--' . static::BASE_EDITION_OPT;
throw new InvalidOptionException("'$opt' cannot be used when upgrading Magento Cloud");
}
$overrideEdition = strtolower($overrideEdition);
if ($overrideEdition !== 'open source' && $overrideEdition !== 'commerce') {
$opt = '--' . static::BASE_EDITION_OPT;
throw new InvalidOptionException("'$opt' accepts only 'Open Source' or 'Commerce'");
}
return $overrideEdition == 'open source' ?
PackageUtils::OPEN_SOURCE_PKG_EDITION : PackageUtils::COMMERCE_PKG_EDITION;
}

/**
* Check if the plugin should run and parses the package arguments for a magento metapackage requirement if so
*
* @param InputInterface $input
* @return void
Expand All @@ -275,7 +294,7 @@ protected function parseMageRequirement(&$input)
foreach ($requires as $requirement) {
$edition = $this->pkgUtils->getMagentoProductEdition($requirement['name']);
if ($edition) {
$this->package = "magento/product-$edition-edition";
$this->package = $requirement['name'];
$this->constraint = isset($requirement['version']) ? $requirement['version'] : '*';
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public function doVarInstall()
try {
$this->console->log(
"Checking for \"$packageName: $version\" for the Web Setup Wizard...",
Console::VERBOSE
Console::VERY_VERBOSE
);
$this->updateSetupWizardPlugin($composer, $path, $version);
} catch (Exception $e) {
Expand All @@ -125,6 +125,8 @@ public function doVarInstall()
/**
* Update the plugin installation inside the ./var directory used by the Web Setup Wizard
*
* Does not install the plugin inside var if on a cloud installation
*
* @param Composer $composer
* @param string $filePath
* @param string $pluginVersion
Expand All @@ -135,6 +137,14 @@ public function updateSetupWizardPlugin($composer, $filePath, $pluginVersion)
{
$packageName = PluginDefinition::PACKAGE_NAME;

if ($this->pkgUtils->findRequire($composer, PackageUtils::CLOUD_METAPACKAGE) !== false) {
$this->console->log(
"Cloud installation detected, Not installing $packageName for the Web Setup Wizard",
Console::VERBOSE
);
return false;
}

// If in ./var already or Magento or the plugin is missing from composer.json, do not install in var
if (!preg_match('/\/composer\.json$/', $filePath) ||
preg_match('/\/var\/composer\.json$/', $filePath) ||
Expand Down Expand Up @@ -170,7 +180,6 @@ public function updateSetupWizardPlugin($composer, $filePath, $pluginVersion)

$this->console->info("Installing \"$packageName: $pluginVersion\" for the Web Setup Wizard");

$exception = null;
$tmpDir = null;
try {
$tmpDir = $this->getTempDir($var, $packageName, $pluginVersion);
Expand All @@ -187,14 +196,8 @@ public function updateSetupWizardPlugin($composer, $filePath, $pluginVersion)
$install->run();

$this->copyAndReplace("$tmpDir/vendor", "$var/vendor");
} catch (Exception $e) {
$exception = $e;
}

$this->deletePath($tmpDir);

if ($exception !== null) {
throw $exception;
} finally {
$this->deletePath($tmpDir);
}

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function runUpdate(

if ($origEdition == $retriever->getTargetEdition() && $origVersion == $retriever->getTargetVersion()) {
$this->console->labeledVerbose(
'The Magento product requirement matched the current installation; no root updates are required'
'The Magento metapackage requirement matched the current installation; no root updates are required'
);
return false;
}
Expand All @@ -98,8 +98,9 @@ public function runUpdate(
}

$this->console->setVerboseLabel($retriever->getTargetLabel());
$project = $this->pkgUtils->getProjectPackageName($origEdition);
$this->console->labeledVerbose(
"Base Magento project package version: magento/project-$origEdition-edition $prettyOrigVersion"
"Base Magento project package version: $project $prettyOrigVersion"
);

$resolver = new DeltaResolver($this->console, $overrideOption, $retriever);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Composer\Package\Version\VersionParser;
use Composer\Package\Version\VersionSelector;
use Composer\Repository\CompositeRepository;
use Composer\Repository\VcsRepository;
use Magento\ComposerRootUpdatePlugin\ComposerReimplementation\AccessibleRootPackageLoader;
use Magento\ComposerRootUpdatePlugin\Utils\PackageUtils;
use Magento\ComposerRootUpdatePlugin\Utils\Console;
Expand Down Expand Up @@ -157,10 +158,11 @@ public function getOriginalRootPackage($overrideOption)

if (!$originalRootPackage) {
if (!$originalEdition || !$originalVersion) {
$this->console->warning('No Magento product package was found in the current installation.');
$this->console->warning('No Magento metapackage was found in the current installation.');
} else {
$metapackageName = $this->pkgUtils->getMetapackageName($originalEdition);
$this->console->warning('The Magento project package corresponding to the currently installed ' .
"\"magento/product-$originalEdition-edition: $prettyOrigVersion\" package is unavailable.");
"\"$metapackageName: $prettyOrigVersion\" package is unavailable.");
}

$overrideRoot = $overrideOption;
Expand Down Expand Up @@ -247,7 +249,7 @@ protected function fetchMageRootFromRepo(
$phpVersion = null,
$preferredStability = 'stable'
) {
$packageName = strtolower("magento/project-$edition-edition");
$packageName = $this->pkgUtils->getProjectPackageName($edition);
$parsedConstraint = (new VersionParser())->parseConstraints($constraint);

$minStability = $this->composer->getPackage()->getMinimumStability();
Expand All @@ -266,11 +268,25 @@ protected function fetchMageRootFromRepo(
$stabilityFlags,
[$packageName => $parsedConstraint]
);
$pool->addRepository(new CompositeRepository($this->composer->getRepositoryManager()->getRepositories()));
if ($edition == PackageUtils::CLOUD_PKG_EDITION) {
// magento/magento-cloud-template exists on github, not the composer repo
$repoConfig = [
'url' => 'https://github.com/magento/magento-cloud',
'type' => 'vcs'
];
$pool->addRepository(new VcsRepository(
$repoConfig,
$this->console->getIO(),
$this->composer->getConfig()
));
} else {
$pool->addRepository(new CompositeRepository($this->composer->getRepositoryManager()->getRepositories()));
}

if (!$this->pkgUtils->isConstraintStrict($constraint)) {
$metapackageName = $this->pkgUtils->getMetapackageName($edition);
if ($edition != PackageUtils::CLOUD_PKG_EDITION && !$this->pkgUtils->isConstraintStrict($constraint)) {
$this->console->warning(
"The version constraint \"magento/product-$edition-edition: $constraint\" is not exact; " .
"The version constraint \"$metapackageName: $constraint\" is not exact; " .
'the Magento root updater might not accurately determine the version to use according to other ' .
'requirements in this installation. It is recommended to use an exact version number.'
);
Expand All @@ -286,7 +302,7 @@ protected function fetchMageRootFromRepo(
);

if (!$result) {
$err = "Could not find a Magento project package matching \"magento/product-$edition-edition $constraint\"";
$err = "Could not find a Magento project package matching \"$metapackageName $constraint\"";
if ($phpVersion) {
$err = "$err for PHP version $phpVersion";
}
Expand All @@ -297,7 +313,7 @@ protected function fetchMageRootFromRepo(
}

/**
* Gets the original Magento product edition and version from the package in composer.lock
* Gets the original Magento metapackage edition and version from the package in composer.lock
*
* @param string $overrideEdition
* @param string $overrideVersion
Expand Down
Loading

0 comments on commit 5807d6e

Please sign in to comment.