diff --git a/.travis.yml b/.travis.yml index dc0ebdb78..182dde46e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,14 +29,14 @@ matrix: fast_finish: true include: - { name: "Static code analysis", env: ORCA_JOB=STATIC_CODE_ANALYSIS } - - { name: "Deprecated code scan w/ SUT", env: ORCA_JOB=DEPRECATED_CODE_SCAN_SUT } - - { name: "Deprecated code scan w/ dependencies", env: ORCA_JOB=DEPRECATED_CODE_SCAN_CONTRIB } + - { name: "Deprecated code scan of SUT only", env: ORCA_JOB=DEPRECATED_CODE_SCAN_SUT } + - { name: "Deprecated code scan of SUT plus contrib", env: ORCA_JOB=DEPRECATED_CODE_SCAN_CONTRIB } - { name: "Isolated test w/ recommended package versions", env: ORCA_JOB=ISOLATED_RECOMMENDED } - { name: "Integrated test w/ recommended package versions", env: ORCA_JOB=INTEGRATED_RECOMMENDED } - - { name: "Previous minor version of Drupal core", env: ORCA_JOB=CORE_PREVIOUS } + - { name: "Integrated test w/ recommended package versions & previous minor release of Drupal core", env: ORCA_JOB=CORE_PREVIOUS } - { name: "Isolated test w/ dev package versions", env: ORCA_JOB=ISOLATED_DEV } - { name: "Integrated test w/ dev package versions", env: ORCA_JOB=INTEGRATED_DEV } - - { name: "Next pre-release of Drupal core", env: ORCA_JOB=CORE_NEXT } + - { name: "Integrated test w/ dev package versions & next minor dev version of Drupal core", env: ORCA_JOB=CORE_NEXT } allow_failures: - env: ORCA_JOB=DEPRECATED_CODE_SCAN_CONTRIB @@ -46,6 +46,8 @@ install: - ../orca/bin/travis/self-test/install.sh - ../orca/bin/travis/install.sh +before_script: ../orca/bin/travis/before_script.sh + script: - ../orca/bin/travis/self-test/script.sh - ../orca/bin/travis/script.sh diff --git a/bin/travis/_includes.sh b/bin/travis/_includes.sh index 3f003dcab..9bb820f13 100755 --- a/bin/travis/_includes.sh +++ b/bin/travis/_includes.sh @@ -32,6 +32,7 @@ assert "$TRAVIS" "This script is meant to run on Travis CI only." # Set environment variables. export ORCA_ROOT="$(cd "$(dirname "$BASH_SOURCE")/../.." && pwd)" export ORCA_FIXTURE_DIR=${ORCA_FIXTURE_DIR:="${ORCA_ROOT}/../orca-build"} +export ORCA_FIXTURE_DOCROOT=${ORCA_FIXTURE_DIR}/docroot export ORCA_SUT_DIR=${ORCA_SUT_DIR:=${TRAVIS_BUILD_DIR}} # Add binary directories to PATH. @@ -41,6 +42,9 @@ export PATH="$ORCA_ROOT/vendor/bin:$PATH" export PATH="$ORCA_FIXTURE_DIR/vendor/bin:$PATH" export PATH="$TRAVIS_BUILD_DIR/vendor/bin:$PATH" +# Add convenient aliases. +alias drush="drush -r ${ORCA_FIXTURE_DOCROOT}" + # Exit as soon as one command returns a non-zero exit code and make the shell # print all lines in the script before executing them. # @see https://docs.travis-ci.com/user/job-lifecycle/#complex-build-commands diff --git a/bin/travis/before_install.sh b/bin/travis/before_install.sh index e9bcf4a37..9d85e74fe 100755 --- a/bin/travis/before_install.sh +++ b/bin/travis/before_install.sh @@ -11,6 +11,9 @@ cd "$(dirname "$0")"; source _includes.sh +# Display the Google Chrome version. +google-chrome-stable --version + # Disable Xdebug. phpenv config-rm xdebug.ini diff --git a/bin/travis/before_script.sh b/bin/travis/before_script.sh new file mode 100755 index 000000000..f047f53fa --- /dev/null +++ b/bin/travis/before_script.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# NAME +# before_script.sh - Display details about the fixture. +# +# SYNOPSIS +# before_script.sh +# +# DESCRIPTION +# Displays information about installed Composer packages and Drupal +# projects. + +cd "$(dirname "$0")"; source _includes.sh + +# Exit early in the absence of a fixture. +[[ -d "$ORCA_FIXTURE_DIR" ]] || exit 0 + +# Display installed Composer packages. +composer -d${ORCA_FIXTURE_DIR} show + +# Display the list of available Drupal extensions (modules and themes). +drush --no-ansi pm:list || true + +# Display basic Drupal site details. +drush core-status diff --git a/bin/travis/install.sh b/bin/travis/install.sh index ed0574eb2..277c8c3c6 100755 --- a/bin/travis/install.sh +++ b/bin/travis/install.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # NAME -# install.sh - Install Travis CI dependencies +# install.sh - Install Travis CI dependencies. # # SYNOPSIS # install.sh @@ -21,10 +21,10 @@ assert_env_vars [[ "$ORCA_JOB" != "INTEGRATED_RECOMMENDED" ]] || orca fixture:init -f --sut=${ORCA_SUT_NAME} -[[ "$ORCA_JOB" != "CORE_PREVIOUS" ]] || orca fixture:init -f --sut=${ORCA_SUT_NAME} --core=PREVIOUS_MINOR +[[ "$ORCA_JOB" != "CORE_PREVIOUS" ]] || orca fixture:init -f --sut=${ORCA_SUT_NAME} --core=PREVIOUS_RELEASE [[ "$ORCA_JOB" != "ISOLATED_DEV" ]] || orca fixture:init -f --sut=${ORCA_SUT_NAME} --sut-only --dev [[ "$ORCA_JOB" != "INTEGRATED_DEV" ]] || orca fixture:init -f --sut=${ORCA_SUT_NAME} --dev -[[ "$ORCA_JOB" != "CORE_NEXT" ]] || orca fixture:init -f --sut=${ORCA_SUT_NAME} --core=LATEST_PRERELEASE --dev +[[ "$ORCA_JOB" != "CORE_NEXT" ]] || orca fixture:init -f --sut=${ORCA_SUT_NAME} --core=NEXT_DEV --dev diff --git a/bin/travis/script.sh b/bin/travis/script.sh index 1bc03875c..085225c62 100755 --- a/bin/travis/script.sh +++ b/bin/travis/script.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # NAME -# script.sh - Run ORCA tests +# script.sh - Run ORCA tests. # # SYNOPSIS # script.sh diff --git a/config/VERSION b/config/VERSION index 2cad04fb5..4e909960f 100644 --- a/config/VERSION +++ b/config/VERSION @@ -1 +1 @@ -v1.0.0-alpha10 +v1.0.0-alpha11 diff --git a/config/packages.yml b/config/packages.yml index 50633d908..4bb87c0f4 100644 --- a/config/packages.yml +++ b/config/packages.yml @@ -15,8 +15,11 @@ # place. Defaults to a directory adjacent to the fixture root named the # Composer project name, e.g., "../example" for a "drupal/example" project. # - "version": (optional) The recommended package version to require via -# Composer. Defaults to "*". +# Composer. Defaults to "*". Any version string Composer understands is +# acceptable. @see https://getcomposer.org/doc/articles/versions.md # - "version_dev": (required) The dev package version to require via Composer. +# Any version string Composer understands is acceptable. +# @see https://getcomposer.org/doc/articles/versions.md # - "enable": (internal) TRUE if the package is a Drupal module that should be # automatically enabled or FALSE if not. Defaults to TRUE for modules. Always # FALSE for anything else. @@ -27,6 +30,7 @@ # or merged in using the "ORCA_PACKAGES_CONFIG_ALTER" environment variable. See # config/services.yml for the relevant code or bin/self-test for a usage # example. + #drupal/acquia_commercemanager: # url: ../commerce-manager # version_dev: 1.x-dev @@ -47,7 +51,8 @@ drupal/acquia_purge: version_dev: 1.x-dev #drupal/acsf: -# version_dev: "*" +# version: ~1.0 +# version_dev: 1.x-dev acquia/blt: type: composer-plugin @@ -70,23 +75,23 @@ acquia/drupal-spec-tool: drupal/lightning_api: url: ../lightning-api - version_dev: 3.x-dev + version_dev: '3.x-dev || 4.x-dev' drupal/lightning_core: url: ../lightning-core - version_dev: 3.x-dev + version_dev: '3.x-dev || 4.x-dev' drupal/lightning_layout: url: ../lightning-layout - version_dev: 1.x-dev + version_dev: '1.x-dev || 2.x-dev' drupal/lightning_media: url: ../lightning-media - version_dev: 3.x-dev + version_dev: '3.x-dev || 4.x-dev' drupal/lightning_workflow: url: ../lightning-workflow - version_dev: 3.x-dev + version_dev: '2.x-dev || 3.x-dev' #drupal/media_acquiadam: # version_dev: 1.x-dev diff --git a/docs/getting-started.md b/docs/getting-started.md index 3933b2fc0..5b8d33eb7 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -49,6 +49,8 @@ Invoke ORCA from the terminal (`bin/orca`). Use the `--help` command option to l ORCA uses tags (for Behat) and groups (for PHPUnit) to determine which tests to run when, as depicted in the table below, where black indicates a test's being included and white indicates its being ignored: + + | | (Default) | `orca_public` | `orca_ignore` | |----------------------------|:--------------:|:--------------:|:--------------:| | Isolated tests (own) | :black_circle: | :black_circle: | :white_circle: | diff --git a/docs/understanding-orca.md b/docs/understanding-orca.md index 47406ea33..c2c5a470a 100644 --- a/docs/understanding-orca.md +++ b/docs/understanding-orca.md @@ -61,15 +61,17 @@ See [Designing automated tests](getting-started.md#designing-automated-tests). ORCA includes out-of-the-box support for Travis CI for continuous integration. The default implementation runs the following concurrent jobs per build: -| | #1
Static code
analysis | #2
Deprecated
code scan
w/ SUT | #3
Deprecated
code scan w/
dependencies | #4
Isolated/
recommended | #5
Integrated/
recommended | #6
Previous core
version | #7
Isolated/
dev | #8
Integrated/
dev | #9
Next core
version | -|----------------------|:---------------------------------:|:---------------------------------------------:|:------------------------------------------------------:|:----------------------------------:|:------------------------------------:|:----------------------------------:|:--------------------------:|:----------------------------:|:------------------------------:| -| Fixture type | None | SUT-only | SUT-only | SUT-only | Standard | Standard | SUT-only | Standard | Standard | -| Package stability | n/a | Stable | Stable | Stable | Stable | Stable | Dev | Dev | Dev | -| Drupal core version | n/a | Current | Current | Current | Current | Previous
minor | Current | Current | Latest pre-
release | -| Static analysis | :black_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | -| Deprecated code scan | :white_circle: | :black_circle: | :black_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | -| Automated tests | :white_circle: | :white_circle: | :white_circle: | :black_circle: | :black_circle: | :black_circle: | :black_circle: | :black_circle: | :black_circle: | -| Allow failure | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :black_circle: | :black_circle: | :black_circle: | + + +| | #1
Static code
analysis | #2
Deprecated
code scan
of SUT only | #3
Deprecated
code scan
w/ contrib | #4
Isolated/
recommended | #5
Integrated/
recommended | #6
Integrated/
recommended/
previous core | #7
Isolated/
dev | #8
Integrated/
dev | #9
Integrated/
dev/next core
dev | +|----------------------|:---------------------------------:|:--------------------------------------------------:|:-------------------------------------------------:|:----------------------------------:|:------------------------------------:|:---------------------------------------------------------:|:--------------------------:|:----------------------------:|:-----------------------------------------------:| +| Fixture type | None | SUT-only | SUT-only | SUT-only | Standard | Standard | SUT-only | Standard | Standard | +| Package stability | n/a | Stable | Stable | Stable | Stable | Stable | Dev | Dev | Dev | +| Drupal core version | n/a | Current | Current | Current | Current | Previous
minor dev | Current | Current | Next
minor dev | +| Static analysis | :black_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | +| Deprecated code scan | :white_circle: | :black_circle: | :black_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | +| Automated tests | :white_circle: | :white_circle: | :white_circle: | :black_circle: | :black_circle: | :black_circle: | :black_circle: | :black_circle: | :black_circle: | +| Allow failure | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :white_circle: | :black_circle: | :black_circle: | :black_circle: | See [Configuring Travis CI](getting-started.md#configuring-travis-ci). diff --git a/example/.travis.yml b/example/.travis.yml index 34e76e404..a4322dce8 100644 --- a/example/.travis.yml +++ b/example/.travis.yml @@ -64,10 +64,10 @@ matrix: - { name: "Deprecated code scan of SUT plus contrib", env: ORCA_JOB=DEPRECATED_CODE_SCAN_CONTRIB } - { name: "Isolated test w/ recommended package versions", env: ORCA_JOB=ISOLATED_RECOMMENDED } - { name: "Integrated test w/ recommended package versions", env: ORCA_JOB=INTEGRATED_RECOMMENDED } - - { name: "Previous minor version of Drupal core", env: ORCA_JOB=CORE_PREVIOUS } + - { name: "Integrated test w/ recommended package versions & previous minor release of Drupal core", env: ORCA_JOB=CORE_PREVIOUS } - { name: "Isolated test w/ dev package versions", env: ORCA_JOB=ISOLATED_DEV } - { name: "Integrated test w/ dev package versions", env: ORCA_JOB=INTEGRATED_DEV } - - { name: "Next pre-release of Drupal core", env: ORCA_JOB=CORE_NEXT } + - { name: "Integrated test w/ dev package versions & next minor dev version of Drupal core", env: ORCA_JOB=CORE_NEXT } # For various reasons, some jobs are allowed to fail without failing the whole # build. They should still be watched for advance notice of future problems. # @see https://docs.travis-ci.com/user/customizing-the-build#rows-that-are-allowed-to-fail @@ -86,6 +86,9 @@ before_install: # Create the test fixture and place the SUT. install: ../orca/bin/travis/install.sh +# Display details about the fixture. +before_script: ../orca/bin/travis/before_script.sh + # Run the test script. script: ../orca/bin/travis/script.sh diff --git a/src/Command/Debug/DebugCoreVersionsCommand.php b/src/Command/Debug/DebugCoreVersionsCommand.php new file mode 100644 index 000000000..a45ce493e --- /dev/null +++ b/src/Command/Debug/DebugCoreVersionsCommand.php @@ -0,0 +1,117 @@ +drupalCoreVersionFinder = $drupal_core_version_finder; + parent::__construct(self::$defaultName); + } + + /** + * {@inheritdoc} + */ + protected function configure() { + $this + ->setAliases(['core']) + ->setDescription('Provides an overview of Drupal Core versions'); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output): int { + $output->writeln('Getting version data via Composer. This takes a while.'); + + $overview = [ + $this->getRow(FixtureInitCommand::PREVIOUS_RELEASE), + $this->getRow(FixtureInitCommand::PREVIOUS_DEV), + $this->getRow(FixtureInitCommand::CURRENT_RECOMMENDED), + $this->getRow(FixtureInitCommand::CURRENT_DEV), + $this->getRow(FixtureInitCommand::NEXT_RELEASE), + $this->getRow(FixtureInitCommand::NEXT_DEV), + ]; + + (new StatusTable($output)) + ->setRows($overview) + ->render(); + return StatusCodes::OK; + } + + /** + * Gets a table row for a given version constant. + * + * @param string $version_constant + * The version constant. + * + * @return array + * A table row. + */ + private function getRow(string $version_constant): array { + $row = [$version_constant]; + try { + switch ($version_constant) { + case FixtureInitCommand::PREVIOUS_RELEASE: + $row[] = $this->drupalCoreVersionFinder->getPreviousMinorRelease(); + break; + + case FixtureInitCommand::PREVIOUS_DEV: + $row[] = $this->drupalCoreVersionFinder->getPreviousDevVersion(); + break; + + case FixtureInitCommand::CURRENT_RECOMMENDED: + $row[] = $this->drupalCoreVersionFinder->getCurrentRecommendedRelease(); + break; + + case FixtureInitCommand::CURRENT_DEV: + $row[] = $this->drupalCoreVersionFinder->getCurrentDevVersion(); + break; + + case FixtureInitCommand::NEXT_RELEASE: + $row[] = $this->drupalCoreVersionFinder->getNextRelease(); + break; + + case FixtureInitCommand::NEXT_DEV: + $row[] = $this->drupalCoreVersionFinder->getNextDevVersion(); + break; + } + } + catch (\RuntimeException $e) { + $row[] = '~'; + } + return $row; + } + +} diff --git a/src/Command/Fixture/FixtureInitCommand.php b/src/Command/Fixture/FixtureInitCommand.php index c0b19dc81..61da37f20 100644 --- a/src/Command/Fixture/FixtureInitCommand.php +++ b/src/Command/Fixture/FixtureInitCommand.php @@ -21,19 +21,25 @@ class FixtureInitCommand extends Command { public const CORE_OPTION_SPECIAL_VALUES = [ - self::PREVIOUS_MINOR, + self::PREVIOUS_RELEASE, + self::PREVIOUS_DEV, self::CURRENT_RECOMMENDED, self::CURRENT_DEV, - self::LATEST_PRERELEASE, + self::NEXT_RELEASE, + self::NEXT_DEV, ]; - public const PREVIOUS_MINOR = 'PREVIOUS_MINOR'; + public const PREVIOUS_RELEASE = 'PREVIOUS_RELEASE'; + + public const PREVIOUS_DEV = 'PREVIOUS_DEV'; public const CURRENT_RECOMMENDED = 'CURRENT_RECOMMENDED'; public const CURRENT_DEV = 'CURRENT_DEV'; - public const LATEST_PRERELEASE = 'LATEST_PRERELEASE'; + public const NEXT_RELEASE = 'NEXT_RELEASE'; + + public const NEXT_DEV = 'NEXT_DEV'; /** * The default command name. @@ -122,10 +128,12 @@ protected function configure() { ->addOption('sut-only', NULL, InputOption::VALUE_NONE, 'Add only the system under test (SUT). Omit all other non-required Acquia packages') ->addOption('core', NULL, InputOption::VALUE_REQUIRED, implode(PHP_EOL, [ 'Change the version of Drupal core installed:', - sprintf('- %s: The latest stable release of the previous minor version, e.g., "8.5.14" if the current minor version is "8.6"', self::PREVIOUS_MINOR), + sprintf('- %s: The latest release of the previous minor version, e.g., "8.5.14" if the current minor version is 8.6', self::PREVIOUS_RELEASE), + sprintf('- %s: The development version of the previous minor version, e.g., "8.5.x-dev"', self::PREVIOUS_DEV), sprintf('- %s: The current recommended release, e.g., "8.6.14"', self::CURRENT_RECOMMENDED), sprintf('- %s: The current development version, e.g., "8.6.x-dev"', self::CURRENT_DEV), - sprintf('- %s: The latest pre-release version, e.g., "8.7.0-beta2". Note: This could be newer OR older than the current recommended release', self::LATEST_PRERELEASE), + sprintf('- %s: The next release version if available, e.g., "8.7.0-beta2"', self::NEXT_RELEASE), + sprintf('- %s: The next development version, e.g., "8.7.x-dev"', self::NEXT_DEV), '- Any version string Composer understands, see https://getcomposer.org/doc/articles/versions.md', ])) ->addOption('dev', NULL, InputOption::VALUE_NONE, 'Use dev versions of Acquia packages') @@ -166,8 +174,8 @@ public function execute(InputInterface $input, OutputInterface $output): int { $this->setDev($input->getOption('dev')); $this->setCore($core, $input->getOption('dev')); $this->setProfile($input->getOption('profile')); - $this->setSiteInstall($input->getOption('no-site-install')); $this->setSqlite($input->getOption('no-sqlite')); + $this->setSiteInstall($input->getOption('no-site-install')); try { $this->fixtureCreator->create(); @@ -198,7 +206,7 @@ private function isValidInput($sut, $sut_only, $core, OutputInterface $output): if ($core && !$this->isValidCoreValue($core)) { $output->writeln([ sprintf('Error: Invalid value for "--core" option: "%s".', $core), - sprintf('Hint: Acceptable values are "%s", "%s", "%s", "%s", or any version string Composer understands.', self::PREVIOUS_MINOR, self::CURRENT_RECOMMENDED, self::CURRENT_DEV, self::LATEST_PRERELEASE), + sprintf('Hint: Acceptable values are "%s", or any version string Composer understands.', implode('", "', self::CORE_OPTION_SPECIAL_VALUES)), ]); return FALSE; } @@ -295,20 +303,28 @@ private function setCore($version, $dev): void { } switch ($version) { - case self::PREVIOUS_MINOR: - $version = $this->drupalCoreVersionFinder->getPreviousMinorVersion(); + case self::PREVIOUS_RELEASE: + $version = $this->drupalCoreVersionFinder->getPreviousMinorRelease(); + break; + + case self::PREVIOUS_DEV: + $version = $this->drupalCoreVersionFinder->getPreviousDevVersion(); break; case self::CURRENT_RECOMMENDED: - $version = $this->drupalCoreVersionFinder->getCurrentRecommendedVersion(); + $version = $this->drupalCoreVersionFinder->getCurrentRecommendedRelease(); break; case self::CURRENT_DEV: $version = $this->drupalCoreVersionFinder->getCurrentDevVersion(); break; - case self::LATEST_PRERELEASE: - $version = $this->drupalCoreVersionFinder->getLatestPreReleaseVersion(); + case self::NEXT_RELEASE: + $version = $this->drupalCoreVersionFinder->getNextRelease(); + break; + + case self::NEXT_DEV: + $version = $this->drupalCoreVersionFinder->getNextDevVersion(); break; } $this->fixtureCreator->setCoreVersion($version); diff --git a/src/Fixture/FixtureCreator.php b/src/Fixture/FixtureCreator.php index c65656472..80101783e 100644 --- a/src/Fixture/FixtureCreator.php +++ b/src/Fixture/FixtureCreator.php @@ -335,8 +335,15 @@ private function fixDefaultDependencies(): void { 'acquia/blt-require-dev', ], $fixture_path); + $additions = []; + + // Install the dev version of Drush. + if ($this->isDev) { + $additions[] = 'drush/drush:dev-master'; + } + // Add Drupal Console as a soft dependency akin to Drush. - $additions = ['drupal/console:~1.0']; + $additions[] = 'drupal/console:~1.0'; // Install a specific version of Drupal core. if ($this->drupalCoreVersion) { @@ -350,17 +357,15 @@ private function fixDefaultDependencies(): void { '--no-update', ], $additions), $fixture_path); - // For Drupal 8.6 or later, replace webflo/drupal-core-require-dev, which - // would otherwise be provided by BLT's dev requirements package. - if (!$this->drupalCoreVersion || floatval($this->drupalCoreVersion) >= 8.6) { - $this->processRunner->runOrcaVendorBin([ - 'composer', - 'require', - '--dev', - '--no-update', - 'webflo/drupal-core-require-dev', - ], $fixture_path); - } + // Replace webflo/drupal-core-require-dev, which would otherwise be provided + // by BLT's dev requirements package. + $this->processRunner->runOrcaVendorBin([ + 'composer', + 'require', + '--dev', + '--no-update', + 'webflo/drupal-core-require-dev:*', + ], $fixture_path); } /** diff --git a/src/Fixture/SubmoduleManager.php b/src/Fixture/SubmoduleManager.php index bd674f04f..479a1f08c 100644 --- a/src/Fixture/SubmoduleManager.php +++ b/src/Fixture/SubmoduleManager.php @@ -186,7 +186,7 @@ private function findSubmoduleComposerJsonFiles(array $paths) { ->files() ->followLinks() ->in($paths) - ->depth('> 1') + ->depth('> 0') ->exclude([ // Ignore package vendor directories. (These should never exist on CI. // This is mostly for local development.) diff --git a/src/Utility/DrupalCoreVersionFinder.php b/src/Utility/DrupalCoreVersionFinder.php index a0255eebd..447560ce5 100644 --- a/src/Utility/DrupalCoreVersionFinder.php +++ b/src/Utility/DrupalCoreVersionFinder.php @@ -13,56 +13,69 @@ class DrupalCoreVersionFinder { /** - * The current recommended version. + * The current recommended release. * * @var string */ - private $currentRecommendedVersion = ''; + private $currentRecommendedRelease = ''; /** - * The latest pre-release version. + * The next release. * * @var string */ - private $latestPreReleaseVersion = ''; + private $nextRelease = ''; /** - * The previous minor version. + * The previous minor release. * * @var string */ - private $previousMinorVersion = ''; + private $previousMinorRelease = ''; /** - * Gets the previous minor version. + * Gets the latest release from the previous minor version. * * @return string * The version string, e.g., "8.5.14.0". + * + * @see \Acquia\Orca\Command\Fixture\FixtureInitCommand::PREVIOUS_RELEASE */ - public function getPreviousMinorVersion(): string { - if ($this->previousMinorVersion) { - return $this->previousMinorVersion; + public function getPreviousMinorRelease(): string { + if ($this->previousMinorRelease) { + return $this->previousMinorRelease; } - $this->previousMinorVersion = $this->getVersionSelector() - ->findBestCandidate('drupal/core', "<{$this->getCurrentMinorVersion()}") - ->getVersion(); - return $this->previousMinorVersion; + $this->previousMinorRelease = $this->getCoreVersion("<{$this->getCurrentMinorVersion()}"); + return $this->previousMinorRelease; + } + + /** + * Gets the previous minor dev version. + * + * @return string + * The version string, e.g., "8.5.x-dev". + * + * @see \Acquia\Orca\Command\Fixture\FixtureInitCommand::PREVIOUS_DEV + */ + public function getPreviousDevVersion(): string { + $previous_minor_version = floatval($this->getCurrentMinorVersion()) - 0.1; + return "{$previous_minor_version}.x-dev"; } /** - * Gets the current recommended version. + * Gets the current recommended release. * * @return string * The version string, e.g., "8.6.14.0". + * + * @see \Acquia\Orca\Command\Fixture\FixtureInitCommand::CURRENT_RECOMMENDED */ - public function getCurrentRecommendedVersion(): string { - if ($this->currentRecommendedVersion) { - return $this->currentRecommendedVersion; + public function getCurrentRecommendedRelease(): string { + if ($this->currentRecommendedRelease) { + return $this->currentRecommendedRelease; } - $this->currentRecommendedVersion = $this->getVersionSelector() - ->findBestCandidate('drupal/core') - ->getVersion(); - return $this->currentRecommendedVersion; + $this->currentRecommendedRelease = $this->getCoreVersion(); + return $this->currentRecommendedRelease; } /** @@ -70,6 +83,8 @@ public function getCurrentRecommendedVersion(): string { * * @return string * The version string, e.g., "8.6.x-dev". + * + * @see \Acquia\Orca\Command\Fixture\FixtureInitCommand::CURRENT_DEV */ public function getCurrentDevVersion(): string { return "{$this->getCurrentMinorVersion()}.x-dev"; @@ -80,15 +95,49 @@ public function getCurrentDevVersion(): string { * * @return string * The version string, e.g., "8.7.0.0-beta2". + * + * @see \Acquia\Orca\Command\Fixture\FixtureInitCommand::NEXT_RELEASE + */ + public function getNextRelease(): string { + if ($this->nextRelease) { + return $this->nextRelease; + } + $this->nextRelease = $this->getCoreVersion(">{$this->getCurrentRecommendedRelease()}", 'alpha'); + return $this->nextRelease; + } + + /** + * Gets the next minor dev version. + * + * @return string + * The version string, e.g., "8.7.x-dev". + * + * @see \Acquia\Orca\Command\Fixture\FixtureInitCommand::NEXT_DEV + */ + public function getNextDevVersion(): string { + $previous_minor_version = floatval($this->getCurrentMinorVersion()) + 0.1; + return "{$previous_minor_version}.x-dev"; + } + + /** + * Gets the Drupal core version matching the given criteria. + * + * @param string|null $target_package_version + * The target package version. + * @param string $minimum_stability + * The minimum stability. Available options (in order of stability) are + * dev, alpha, beta, RC, and stable. + * + * @return string + * The version string. */ - public function getLatestPreReleaseVersion(): string { - if ($this->latestPreReleaseVersion) { - return $this->latestPreReleaseVersion; + private function getCoreVersion(string $target_package_version = NULL, string $minimum_stability = 'stable'): string { + $best_candidate = $this->getVersionSelector($minimum_stability) + ->findBestCandidate('drupal/core', $target_package_version); + if (!$best_candidate) { + throw new \RuntimeException(sprintf('No Drupal core version satisfies the given constraints: version=%s, minimum stability=%s', $target_package_version, $minimum_stability)); } - $this->latestPreReleaseVersion = $this->getVersionSelector('alpha') - ->findBestCandidate('drupal/core', ">{$this->getCurrentRecommendedVersion()}") - ->getVersion(); - return $this->latestPreReleaseVersion; + return $best_candidate->getVersion(); } /** @@ -115,7 +164,7 @@ private function getVersionSelector($minimum_stability = 'stable'): VersionSelec * The version string, e.g., "8.6". */ private function getCurrentMinorVersion(): string { - return (string) floatval($this->getCurrentRecommendedVersion()); + return (string) floatval($this->getCurrentRecommendedRelease()); } } diff --git a/tests/Command/Fixture/FixtureInitCommandTest.php b/tests/Command/Fixture/FixtureInitCommandTest.php index 8d750f866..d4da99df0 100644 --- a/tests/Command/Fixture/FixtureInitCommandTest.php +++ b/tests/Command/Fixture/FixtureInitCommandTest.php @@ -25,28 +25,32 @@ */ class FixtureInitCommandTest extends CommandTestBase { - private const CORE_VALUE_LITERAL_PREVIOUS_MINOR = '8.5.14.0'; + private const CORE_VALUE_LITERAL_PREVIOUS_RELEASE = '8.5.14.0'; - private const CORE_VALUE_LITERAL_RECOMMENDED_VERSION = '8.6.14.0'; + private const CORE_VALUE_LITERAL_PREVIOUS_DEV = '8.5.x-dev'; - private const CORE_VALUE_LITERAL_DEV_VERSION = '8.6.x-dev'; + private const CORE_VALUE_LITERAL_CURRENT_RECOMMENDED = '8.6.14.0'; - private const CORE_VALUE_LITERAL_LATEST_PRERELEASE = '8.7.0.0-beta2'; + private const CORE_VALUE_LITERAL_CURRENT_DEV = '8.6.x-dev'; + + private const CORE_VALUE_LITERAL_NEXT_RELEASE = '8.7.0.0-beta2'; + + private const CORE_VALUE_LITERAL_NEXT_DEV = '8.7.x-dev'; protected function setUp() { $this->drupalCoreVersionFinder = $this->prophesize(DrupalCoreVersionFinder::class); $this->drupalCoreVersionFinder - ->getPreviousMinorVersion() - ->willReturn(self::CORE_VALUE_LITERAL_PREVIOUS_MINOR); + ->getPreviousMinorRelease() + ->willReturn(self::CORE_VALUE_LITERAL_PREVIOUS_RELEASE); $this->drupalCoreVersionFinder - ->getCurrentRecommendedVersion() - ->willReturn(self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION); + ->getCurrentRecommendedRelease() + ->willReturn(self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED); $this->drupalCoreVersionFinder ->getCurrentDevVersion() - ->willReturn(self::CORE_VALUE_LITERAL_DEV_VERSION); + ->willReturn(self::CORE_VALUE_LITERAL_CURRENT_DEV); $this->drupalCoreVersionFinder - ->getLatestPreReleaseVersion() - ->willReturn(self::CORE_VALUE_LITERAL_LATEST_PRERELEASE); + ->getNextRelease() + ->willReturn(self::CORE_VALUE_LITERAL_NEXT_RELEASE); $this->fixtureCreator = $this->prophesize(FixtureCreator::class); $this->fixtureRemover = $this->prophesize(FixtureRemover::class); $this->fixture = $this->prophesize(Fixture::class); @@ -74,19 +78,19 @@ public function testCommand($fixture_exists, $args, $methods_called, $drupal_cor ->remove() ->shouldBeCalledTimes((int) in_array('remove', $methods_called)); $this->drupalCoreVersionFinder - ->getPreviousMinorVersion() + ->getPreviousMinorRelease() ->shouldBeCalledTimes((int) in_array('getPreviousMinorVersion', $methods_called)) ->willReturn($drupal_core_version); $this->drupalCoreVersionFinder - ->getCurrentRecommendedVersion() + ->getCurrentRecommendedRelease() ->shouldBeCalledTimes((int) in_array('getCurrentRecommendedVersion', $methods_called)) - ->willReturn(self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION); + ->willReturn(self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED); $this->drupalCoreVersionFinder ->getCurrentDevVersion() ->shouldBeCalledTimes((int) in_array('getCurrentDevVersion', $methods_called)) ->willReturn($drupal_core_version); $this->drupalCoreVersionFinder - ->getLatestPreReleaseVersion() + ->getNextRelease() ->shouldBeCalledTimes((int) in_array('getLatestPreReleaseVersion', $methods_called)) ->willReturn($drupal_core_version); $this->fixtureCreator @@ -99,7 +103,7 @@ public function testCommand($fixture_exists, $args, $methods_called, $drupal_cor ->setDev(TRUE) ->shouldBeCalledTimes((int) in_array('setDev', $methods_called)); $this->fixtureCreator - ->setCoreVersion($drupal_core_version ?: self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION) + ->setCoreVersion($drupal_core_version ?: self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED) ->shouldBeCalledTimes((int) in_array('setCoreVersion', $methods_called)); $this->fixtureCreator ->setSqlite(FALSE) @@ -134,7 +138,7 @@ public function providerCommand() { [FALSE, ['--sut' => self::INVALID_PACKAGE], ['PackageManager::exists'], NULL, 0, StatusCodes::ERROR, sprintf("Error: Invalid value for \"--sut\" option: \"%s\".\n", self::INVALID_PACKAGE)], [FALSE, ['--sut' => self::VALID_PACKAGE], ['PackageManager::exists', 'Fixture::exists', 'create', 'setSut'], NULL, 0, StatusCodes::OK, ''], [FALSE, ['--sut' => self::VALID_PACKAGE, '--sut-only' => TRUE], ['PackageManager::exists', 'Fixture::exists', 'create', 'setSut', 'setSutOnly'], NULL, 0, StatusCodes::OK, ''], - [FALSE, ['--dev' => TRUE], ['Fixture::exists', 'setDev', 'getCurrentDevVersion', 'setCoreVersion', 'create'], self::CORE_VALUE_LITERAL_DEV_VERSION, 0, StatusCodes::OK, ''], + [FALSE, ['--dev' => TRUE], ['Fixture::exists', 'setDev', 'getCurrentDevVersion', 'setCoreVersion', 'create'], self::CORE_VALUE_LITERAL_CURRENT_DEV, 0, StatusCodes::OK, ''], [FALSE, ['--no-site-install' => TRUE], ['Fixture::exists', 'setInstallSite', 'create'], NULL, 0, StatusCodes::OK, ''], [FALSE, ['--no-sqlite' => TRUE], ['Fixture::exists', 'setSqlite', 'create'], NULL, 0, StatusCodes::OK, ''], [FALSE, ['--profile' => 'lightning'], ['Fixture::exists', 'setProfile', 'create'], NULL, 0, StatusCodes::OK, ''], @@ -156,23 +160,31 @@ public function testNoOptions() { /** * @dataProvider providerCoreOption */ - public function testCoreOption($value, $call_parser, $set_version) { + public function testCoreOption($value, $set_version) { $this->drupalCoreVersionFinder - ->getPreviousMinorVersion() - ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::PREVIOUS_MINOR)) - ->willReturn(self::CORE_VALUE_LITERAL_PREVIOUS_MINOR); + ->getPreviousMinorRelease() + ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::PREVIOUS_RELEASE)) + ->willReturn(self::CORE_VALUE_LITERAL_PREVIOUS_RELEASE); $this->drupalCoreVersionFinder - ->getCurrentRecommendedVersion() + ->getPreviousDevVersion() + ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::PREVIOUS_DEV)) + ->willReturn(self::CORE_VALUE_LITERAL_PREVIOUS_DEV); + $this->drupalCoreVersionFinder + ->getCurrentRecommendedRelease() ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::CURRENT_RECOMMENDED)) - ->willReturn(self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION); + ->willReturn(self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED); $this->drupalCoreVersionFinder ->getCurrentDevVersion() ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::CURRENT_DEV)) - ->willReturn(self::CORE_VALUE_LITERAL_DEV_VERSION); + ->willReturn(self::CORE_VALUE_LITERAL_CURRENT_DEV); + $this->drupalCoreVersionFinder + ->getNextRelease() + ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::NEXT_RELEASE)) + ->willReturn(self::CORE_VALUE_LITERAL_NEXT_RELEASE); $this->drupalCoreVersionFinder - ->getLatestPreReleaseVersion() - ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::LATEST_PRERELEASE)) - ->willReturn(self::CORE_VALUE_LITERAL_LATEST_PRERELEASE); + ->getNextDevVersion() + ->shouldBeCalledTimes((int) ($value === FixtureInitCommand::NEXT_DEV)) + ->willReturn(self::CORE_VALUE_LITERAL_NEXT_DEV); $this->fixtureCreator->setCoreVersion($set_version) ->shouldBeCalledTimes(1); $this->fixtureCreator @@ -190,14 +202,16 @@ public function testCoreOption($value, $call_parser, $set_version) { public function providerCoreOption() { return [ - [FixtureInitCommand::PREVIOUS_MINOR, 0, self::CORE_VALUE_LITERAL_PREVIOUS_MINOR], - [FixtureInitCommand::CURRENT_RECOMMENDED, 0, self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION], - [FixtureInitCommand::CURRENT_DEV, 0, self::CORE_VALUE_LITERAL_DEV_VERSION], - [FixtureInitCommand::LATEST_PRERELEASE, 0, self::CORE_VALUE_LITERAL_LATEST_PRERELEASE], - [self::CORE_VALUE_LITERAL_PREVIOUS_MINOR, 1, self::CORE_VALUE_LITERAL_PREVIOUS_MINOR], - [self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION, 1, self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION], - [self::CORE_VALUE_LITERAL_DEV_VERSION, 1, self::CORE_VALUE_LITERAL_DEV_VERSION], - [self::CORE_VALUE_LITERAL_LATEST_PRERELEASE, 1, self::CORE_VALUE_LITERAL_LATEST_PRERELEASE], + [FixtureInitCommand::PREVIOUS_RELEASE, self::CORE_VALUE_LITERAL_PREVIOUS_RELEASE], + [FixtureInitCommand::PREVIOUS_DEV, self::CORE_VALUE_LITERAL_PREVIOUS_DEV], + [FixtureInitCommand::CURRENT_RECOMMENDED, self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED], + [FixtureInitCommand::CURRENT_DEV, self::CORE_VALUE_LITERAL_CURRENT_DEV], + [FixtureInitCommand::NEXT_RELEASE, self::CORE_VALUE_LITERAL_NEXT_RELEASE], + [FixtureInitCommand::NEXT_DEV, self::CORE_VALUE_LITERAL_NEXT_DEV], + [self::CORE_VALUE_LITERAL_PREVIOUS_RELEASE, self::CORE_VALUE_LITERAL_PREVIOUS_RELEASE], + [self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED, self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED], + [self::CORE_VALUE_LITERAL_CURRENT_DEV, self::CORE_VALUE_LITERAL_CURRENT_DEV], + [self::CORE_VALUE_LITERAL_NEXT_RELEASE, self::CORE_VALUE_LITERAL_NEXT_RELEASE], ]; } @@ -218,12 +232,12 @@ public function testCoreOptionVersionParsing($status_code, $value, $display) { public function providerCoreOptionVersionParsing() { $error_message = 'Error: Invalid value for "--core" option: "%s".' . PHP_EOL - . 'Hint: Acceptable values are "PREVIOUS_MINOR", "CURRENT_RECOMMENDED", "CURRENT_DEV", "LATEST_PRERELEASE", or any version string Composer understands.' . PHP_EOL; + . 'Hint: Acceptable values are "PREVIOUS_RELEASE", "PREVIOUS_DEV", "CURRENT_RECOMMENDED", "CURRENT_DEV", "NEXT_RELEASE", "NEXT_DEV", or any version string Composer understands.' . PHP_EOL; return [ - [StatusCodes::OK, self::CORE_VALUE_LITERAL_PREVIOUS_MINOR, ''], - [StatusCodes::OK, self::CORE_VALUE_LITERAL_RECOMMENDED_VERSION, ''], - [StatusCodes::OK, self::CORE_VALUE_LITERAL_DEV_VERSION, ''], - [StatusCodes::OK, self::CORE_VALUE_LITERAL_LATEST_PRERELEASE, ''], + [StatusCodes::OK, self::CORE_VALUE_LITERAL_PREVIOUS_RELEASE, ''], + [StatusCodes::OK, self::CORE_VALUE_LITERAL_CURRENT_RECOMMENDED, ''], + [StatusCodes::OK, self::CORE_VALUE_LITERAL_CURRENT_DEV, ''], + [StatusCodes::OK, self::CORE_VALUE_LITERAL_NEXT_RELEASE, ''], [StatusCodes::OK, '^1.0', ''], [StatusCodes::OK, '~1.0', ''], [StatusCodes::OK, '>=1.0', ''],