Skip to content

Commit 5807d6e

Browse files
Merge pull request #1 from magento-borg/COMOPS-890-cloud-support
COMOPS-890: Cloud Support
2 parents b9ff85e + 6f362f8 commit 5807d6e

File tree

9 files changed

+145
-59
lines changed

9 files changed

+145
-59
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
## Purpose of plugin
44

5-
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.
5+
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.
66

7-
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.
7+
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.
88

99
# Getting Started
1010

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"AFL-3.0"
77
],
88
"require": {
9-
"composer/composer": "<=1.10.6",
9+
"composer/composer": "<=1.10.15",
1010
"composer-plugin-api": "^1.0"
1111
},
1212
"require-dev": {

docs/class_descriptions.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Classes in this namespace tie into the Composer library's code that handles plug
5757

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

60-
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.
60+
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.
6161

6262
- **`configure()`**
6363
- 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
@@ -67,8 +67,10 @@ Extends the native [RequireCommand](https://getcomposer.org/apidoc/master/Compos
6767
- Wraps the native `RequireCommand::execute()` function with the Magento project update code
6868
- **`runUpdate()`**
6969
- Calls [MagentoRootUpdater::runUpdate()](#magentorootupdater) after processing CLI options
70+
- **`convertBaseEditionOption()`**
71+
- Validates the base edition option value and convert it to the internal edition designator
7072
- **`parseMagentoRequirement()`**
71-
- Parses the CLI command arguments for a magento/product requirement
73+
- Parses the CLI command arguments for a Magento product or cloud metapackage requirement
7274

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

@@ -199,15 +201,15 @@ This class runs [DeltaResolver::resolveRootDeltas()](#deltaresolver) if an updat
199201
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).
200202

201203
- **`getOriginalRootPackage()`**
202-
- Fetches the original (default) Magento root project package from the Composer repository
204+
- Fetches the original (default) Magento root project package from the Composer repository or GitHub (in the case of cloud)
203205
- **`getTargetRootPackage()`**
204-
- Fetches the target Magento root project package from the Composer repository
206+
- Fetches the target Magento root project package from the Composer repository or GitHub (in the case of cloud)
205207
- **`getUserRootPackage()`**
206208
- Returns the existing root project package, including all user customizations
207209
- **`fetchMageRootFromRepo()`**
208-
- Given a Magento edition and version constraint, fetch the best-fit Magento root project package from the Composer repository
210+
- 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)
209211
- **`parseVersionAndEditionFromLock()`**
210-
- Inspect the `composer.lock` file for the currently-installed Magento product package and parse out the edition and version for use by `getOriginalRootPackage()`
212+
- 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()`
211213
- **`getTargetLabel()`**
212214
- Gets the formatted label for the target Magento version
213215
- **`getOriginalLabel()`**
@@ -238,15 +240,21 @@ Common package-related utility functions.
238240

239241
- **`getMagentoPackageType()`**
240242
- Extracts the package type (`product` or `project`) from a Magento package name
243+
- Not applicable for cloud
241244
- **`getMagentoProductEdition()`**
242-
- Extracts the package edition from a Magento product package name
245+
- Extracts the package edition from a Magento product or cloud metapackage name
246+
- For the purposes of this plugin, 'cloud' is considered an edition
247+
- **`getProjectPackageName()`**
248+
- Constructs the project package name from an edition
249+
- **`getMetapackageName()`**
250+
- Constructs the metapackage name from an edition
243251
- **`getEditionLabel()`**
244252
- Translates package edition into the marketing edition label
245253
- **`findRequire()`**
246254
- 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
247255
- **`isConstraintStrict()`**
248256
- Checks if a version constraint is strict or if it allows multiple versions (such as `~1.0` or `>= 1.5.3`)
249257
- **`getLockedProduct()`**
250-
- Gets the installed magento/product package from the composer.lock file if it exists
258+
- Gets the installed Magento product or cloud metapackage from the composer.lock file if it exists
251259
- **`getRootLocker()`**
252260
- 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

src/Magento/ComposerRootUpdatePlugin/Plugin/Commands/MageRootRequireCommand.php

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,14 @@ protected function configure()
107107
null,
108108
InputOption::VALUE_REQUIRED,
109109
'Edition of the initially-installed Magento product to use as the base for composer.json updates. ' .
110-
'Valid values: \'Open Source\', \'Commerce\''
110+
'Not valid for Magento Cloud upgrades. Valid values: \'Open Source\', \'Commerce\''
111111
)
112112
->addOption(
113113
static::BASE_VERSION_OPT,
114114
null,
115115
InputOption::VALUE_REQUIRED,
116-
'Version of the initially-installed Magento product to use as the base for composer.json updates.'
116+
'Version of the initially-installed Magento product or cloud metapackage to use as the base for ' .
117+
'composer.json updates.'
117118
);
118119

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

188189
/**
189-
* Checks the package arguments for a Magento product package and run the update if one is found
190+
* Checks the package arguments for a Magento metapackage and run the update if one is found
190191
*
191192
* Returns true if an update was attempted successfully
192193
*
@@ -202,13 +203,7 @@ protected function runUpdate($input)
202203
$overrideEdition = $input->getOption(static::BASE_EDITION_OPT);
203204
$overrideVersion = $input->getOption(static::BASE_VERSION_OPT);
204205
if ($overrideEdition) {
205-
$overrideEdition = strtolower($overrideEdition);
206-
if ($overrideEdition !== 'open source' && $overrideEdition !== 'commerce') {
207-
$opt = '--' . static::BASE_EDITION_OPT;
208-
throw new InvalidOptionException("'$opt' accepts only 'Open Source' or 'Commerce'");
209-
}
210-
$overrideEdition = $overrideEdition == 'open source' ?
211-
PackageUtils::OPEN_SOURCE_PKG_EDITION : PackageUtils::COMMERCE_PKG_EDITION;
206+
$overrideEdition = $this->convertBaseEditionOption($edition, $overrideEdition);
212207
}
213208

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

255250
/**
256-
* Check if the plugin should run and parses the package arguments for a magento/product requirement if so
251+
* Helper function to validate the BASE_EDITION_OPT option value and convert it to the internal edition
252+
*
253+
* 'open source' -> community, 'commerce' -> enterprise
254+
*
255+
* @param string $currentEdition
256+
* @param string $overrideEdition
257+
* @return string
258+
*/
259+
protected function convertBaseEditionOption($currentEdition, $overrideEdition)
260+
{
261+
if ($currentEdition == PackageUtils::CLOUD_PKG_EDITION) {
262+
$opt = '--' . static::BASE_EDITION_OPT;
263+
throw new InvalidOptionException("'$opt' cannot be used when upgrading Magento Cloud");
264+
}
265+
$overrideEdition = strtolower($overrideEdition);
266+
if ($overrideEdition !== 'open source' && $overrideEdition !== 'commerce') {
267+
$opt = '--' . static::BASE_EDITION_OPT;
268+
throw new InvalidOptionException("'$opt' accepts only 'Open Source' or 'Commerce'");
269+
}
270+
return $overrideEdition == 'open source' ?
271+
PackageUtils::OPEN_SOURCE_PKG_EDITION : PackageUtils::COMMERCE_PKG_EDITION;
272+
}
273+
274+
/**
275+
* Check if the plugin should run and parses the package arguments for a magento metapackage requirement if so
257276
*
258277
* @param InputInterface $input
259278
* @return void
@@ -275,7 +294,7 @@ protected function parseMageRequirement(&$input)
275294
foreach ($requires as $requirement) {
276295
$edition = $this->pkgUtils->getMagentoProductEdition($requirement['name']);
277296
if ($edition) {
278-
$this->package = "magento/product-$edition-edition";
297+
$this->package = $requirement['name'];
279298
$this->constraint = isset($requirement['version']) ? $requirement['version'] : '*';
280299
break;
281300
}

src/Magento/ComposerRootUpdatePlugin/Setup/WebSetupWizardPluginInstaller.php

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public function doVarInstall()
102102
try {
103103
$this->console->log(
104104
"Checking for \"$packageName: $version\" for the Web Setup Wizard...",
105-
Console::VERBOSE
105+
Console::VERY_VERBOSE
106106
);
107107
$this->updateSetupWizardPlugin($composer, $path, $version);
108108
} catch (Exception $e) {
@@ -125,6 +125,8 @@ public function doVarInstall()
125125
/**
126126
* Update the plugin installation inside the ./var directory used by the Web Setup Wizard
127127
*
128+
* Does not install the plugin inside var if on a cloud installation
129+
*
128130
* @param Composer $composer
129131
* @param string $filePath
130132
* @param string $pluginVersion
@@ -135,6 +137,14 @@ public function updateSetupWizardPlugin($composer, $filePath, $pluginVersion)
135137
{
136138
$packageName = PluginDefinition::PACKAGE_NAME;
137139

140+
if ($this->pkgUtils->findRequire($composer, PackageUtils::CLOUD_METAPACKAGE) !== false) {
141+
$this->console->log(
142+
"Cloud installation detected, Not installing $packageName for the Web Setup Wizard",
143+
Console::VERBOSE
144+
);
145+
return false;
146+
}
147+
138148
// If in ./var already or Magento or the plugin is missing from composer.json, do not install in var
139149
if (!preg_match('/\/composer\.json$/', $filePath) ||
140150
preg_match('/\/var\/composer\.json$/', $filePath) ||
@@ -170,7 +180,6 @@ public function updateSetupWizardPlugin($composer, $filePath, $pluginVersion)
170180

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

173-
$exception = null;
174183
$tmpDir = null;
175184
try {
176185
$tmpDir = $this->getTempDir($var, $packageName, $pluginVersion);
@@ -187,14 +196,8 @@ public function updateSetupWizardPlugin($composer, $filePath, $pluginVersion)
187196
$install->run();
188197

189198
$this->copyAndReplace("$tmpDir/vendor", "$var/vendor");
190-
} catch (Exception $e) {
191-
$exception = $e;
192-
}
193-
194-
$this->deletePath($tmpDir);
195-
196-
if ($exception !== null) {
197-
throw $exception;
199+
} finally {
200+
$this->deletePath($tmpDir);
198201
}
199202

200203
return true;

src/Magento/ComposerRootUpdatePlugin/Updater/MagentoRootUpdater.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function runUpdate(
8787

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

100100
$this->console->setVerboseLabel($retriever->getTargetLabel());
101+
$project = $this->pkgUtils->getProjectPackageName($origEdition);
101102
$this->console->labeledVerbose(
102-
"Base Magento project package version: magento/project-$origEdition-edition $prettyOrigVersion"
103+
"Base Magento project package version: $project $prettyOrigVersion"
103104
);
104105

105106
$resolver = new DeltaResolver($this->console, $overrideOption, $retriever);

src/Magento/ComposerRootUpdatePlugin/Updater/RootPackageRetriever.php

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Composer\Package\Version\VersionParser;
1616
use Composer\Package\Version\VersionSelector;
1717
use Composer\Repository\CompositeRepository;
18+
use Composer\Repository\VcsRepository;
1819
use Magento\ComposerRootUpdatePlugin\ComposerReimplementation\AccessibleRootPackageLoader;
1920
use Magento\ComposerRootUpdatePlugin\Utils\PackageUtils;
2021
use Magento\ComposerRootUpdatePlugin\Utils\Console;
@@ -157,10 +158,11 @@ public function getOriginalRootPackage($overrideOption)
157158

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

166168
$overrideRoot = $overrideOption;
@@ -247,7 +249,7 @@ protected function fetchMageRootFromRepo(
247249
$phpVersion = null,
248250
$preferredStability = 'stable'
249251
) {
250-
$packageName = strtolower("magento/project-$edition-edition");
252+
$packageName = $this->pkgUtils->getProjectPackageName($edition);
251253
$parsedConstraint = (new VersionParser())->parseConstraints($constraint);
252254

253255
$minStability = $this->composer->getPackage()->getMinimumStability();
@@ -266,11 +268,25 @@ protected function fetchMageRootFromRepo(
266268
$stabilityFlags,
267269
[$packageName => $parsedConstraint]
268270
);
269-
$pool->addRepository(new CompositeRepository($this->composer->getRepositoryManager()->getRepositories()));
271+
if ($edition == PackageUtils::CLOUD_PKG_EDITION) {
272+
// magento/magento-cloud-template exists on github, not the composer repo
273+
$repoConfig = [
274+
'url' => 'https://github.com/magento/magento-cloud',
275+
'type' => 'vcs'
276+
];
277+
$pool->addRepository(new VcsRepository(
278+
$repoConfig,
279+
$this->console->getIO(),
280+
$this->composer->getConfig()
281+
));
282+
} else {
283+
$pool->addRepository(new CompositeRepository($this->composer->getRepositoryManager()->getRepositories()));
284+
}
270285

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

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

299315
/**
300-
* Gets the original Magento product edition and version from the package in composer.lock
316+
* Gets the original Magento metapackage edition and version from the package in composer.lock
301317
*
302318
* @param string $overrideEdition
303319
* @param string $overrideVersion

0 commit comments

Comments
 (0)