From 18073caab25e3dd181b1f4a215377ab7d1b14858 Mon Sep 17 00:00:00 2001
From: Christian Kuhn <lolli@schwarzbu.ch>
Date: Tue, 24 Jul 2018 00:32:14 +0200
Subject: [PATCH] [TASK] Run tests with composer update --prefer-lowest

Similar to recent 'composer update everything' to see
if youngest dependencies allowed by our composer.json
survive the test suite, a 'composer update --prefer-lowest'
now does the opposite: An additional nightly test stage
checks if our lower bounds survive testing.

We need younger minimum fluid to run through all tests:
composer require typo3fluid/fluid ^2.5.2

We need to restrict doctrine/dbal to a higher patch level:
composer require doctrine/dbal ~2.7.1

And a series of require-dev dependencies:
composer require --dev typo3/testing-framework ^4.0.2
composer require --dev codeception/codeception ^2.4.4
composer require --dev friendsofphp/php-cs-fixer ^2.12.2

Change-Id: I5c3fa8478acc9537acc2205711081dc51b1c417a
Resolves: #85626
Related: #85624
Releases: master
Reviewed-on: https://review.typo3.org/57666
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
---
 .../src/main/java/core/AbstractCoreSpec.java  | 24 +++++++
 .../src/main/java/core/NightlySpec.java       | 67 +++++++++++++------
 composer.json                                 | 10 +--
 composer.lock                                 |  2 +-
 typo3/sysext/core/composer.json               | 10 +--
 typo3/sysext/fluid/composer.json              |  2 +-
 typo3/sysext/redirects/composer.json          |  2 +-
 7 files changed, 85 insertions(+), 32 deletions(-)

diff --git a/Build/bamboo/src/main/java/core/AbstractCoreSpec.java b/Build/bamboo/src/main/java/core/AbstractCoreSpec.java
index db62e95d7e09..de0940ae1a7d 100644
--- a/Build/bamboo/src/main/java/core/AbstractCoreSpec.java
+++ b/Build/bamboo/src/main/java/core/AbstractCoreSpec.java
@@ -1364,6 +1364,30 @@ abstract public class AbstractCoreSpec {
             .environmentVariables(this.composerRootVersionEnvironment);
     }
 
+    /**
+     * Task definition to execute 'composer update --prefer-lowest'.
+     * This will update all dependencies to current possible minimum version.
+     * Used in nightly to see if we are compatible with lowest possible dependency versions.
+     *
+     * We update in 2 steps: First composer install as usual, then update. This
+     * way it is easy to see which packages are updated in comparison to what is
+     * currently defined in composer.lock.
+     *
+     * @param String requirementIdentifier
+     */
+    protected Task getTaskComposerUpdateMin(String requirementIdentifier) {
+        return new ScriptTask()
+            .description("composer update --prefer-lowest")
+            .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+            .inlineBody(
+                this.getScriptTaskBashInlineBody() +
+                this.getScriptTaskComposer(requirementIdentifier) +
+                "composer install -n\n" +
+                "composer update --prefer-lowest -n"
+            )
+            .environmentVariables(this.composerRootVersionEnvironment);
+    }
+
     /**
      * Task to prepare an acceptance test
      */
diff --git a/Build/bamboo/src/main/java/core/NightlySpec.java b/Build/bamboo/src/main/java/core/NightlySpec.java
index 943db82078bd..4fbe3fc88d55 100644
--- a/Build/bamboo/src/main/java/core/NightlySpec.java
+++ b/Build/bamboo/src/main/java/core/NightlySpec.java
@@ -110,34 +110,62 @@ public class NightlySpec extends AbstractCoreSpec {
 
 
         // COMPOSER UPDATE MAX stage
-        ArrayList<Job> jobsComposerUpdateStage = new ArrayList<Job>();
+        ArrayList<Job> jobsComposerMaxStage = new ArrayList<Job>();
 
-        jobsComposerUpdateStage.add(this.getJobAcceptanceTestInstallMysql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerUpdateStage.add(this.getJobAcceptanceTestInstallPgsql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerUpdateStage.add(this.getJobAcceptanceTestInstallSqlite(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallMysql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallPgsql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallSqlite(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        jobsComposerUpdateStage.addAll(this.getJobsAcceptanceTestsBackendMysql(1, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.addAll(this.getJobsAcceptanceTestsBackendMysql(1, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        jobsComposerUpdateStage.add(this.getJobCglCheckFullCore(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobCglCheckFullCore(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        jobsComposerUpdateStage.add(this.getJobIntegrationAnnotations(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobIntegrationAnnotations(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        jobsComposerUpdateStage.add(this.getJobIntegrationVarious(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobIntegrationVarious(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        jobsComposerUpdateStage.addAll(this.getJobsFunctionalTestsMysql(1, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerUpdateStage.addAll(this.getJobsFunctionalTestsMssql(1, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerUpdateStage.addAll(this.getJobsFunctionalTestsPgsql(1, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerUpdateStage.addAll(this.getJobsFunctionalTestsSqlite(1, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMysql(1, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMssql(1, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsPgsql(1, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsSqlite(1, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        jobsComposerUpdateStage.add(this.getJobUnitJavaScript(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobUnitJavaScript(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        jobsComposerUpdateStage.add(this.getJobUnitPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerUpdateStage.add(this.getJobUnitDeprecatedPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerUpdateStage.addAll(this.getJobUnitPhpRandom(1, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobUnitPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobUnitDeprecatedPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.addAll(this.getJobUnitPhpRandom(1, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
 
-        Stage stageComposerUpdateStage = new Stage("Composer update max")
-            .jobs(jobsComposerUpdateStage.toArray(new Job[jobsComposerUpdateStage.size()]));
+        Stage stageComposerMaxStage = new Stage("Composer update max")
+            .jobs(jobsComposerMaxStage.toArray(new Job[jobsComposerMaxStage.size()]));
 
+        // COMPOSER UPDATE MIN stage
+        ArrayList<Job> jobsComposerMinStage = new ArrayList<Job>();
+
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallMysql(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallPgsql(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallSqlite(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        jobsComposerMinStage.addAll(this.getJobsAcceptanceTestsBackendMysql(2, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        jobsComposerMinStage.add(this.getJobCglCheckFullCore(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        jobsComposerMinStage.add(this.getJobIntegrationAnnotations(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        jobsComposerMinStage.add(this.getJobIntegrationVarious(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMysql(2, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMssql(2, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsPgsql(2, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsSqlite(2, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        jobsComposerMinStage.add(this.getJobUnitJavaScript(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        jobsComposerMinStage.add(this.getJobUnitPhp(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.add(this.getJobUnitDeprecatedPhp(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.addAll(this.getJobUnitPhpRandom(2, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+
+        Stage stageComposerMinStage = new Stage("Composer update min")
+            .jobs(jobsComposerMinStage.toArray(new Job[jobsComposerMinStage.size()]));
 
         // Compile plan
         return new Plan(project(), planName, planKey)
@@ -146,7 +174,8 @@ public class NightlySpec extends AbstractCoreSpec {
             .stages(
                 stagePreparation,
                 stageMainStage,
-                stageComposerUpdateStage
+                stageComposerMaxStage,
+                stageComposerMinStage
             )
             .linkedRepositories("github TYPO3 TYPO3.CMS")
             .triggers(
diff --git a/composer.json b/composer.json
index 7a09394ed9f7..30e4a8987fa3 100644
--- a/composer.json
+++ b/composer.json
@@ -38,7 +38,7 @@
 		"ext-xml": "*",
 		"cogpowered/finediff": "~0.3.1",
 		"doctrine/annotations": "^1.3",
-		"doctrine/dbal": "~2.7.0",
+		"doctrine/dbal": "~2.7.1",
 		"doctrine/instantiator": "~1.0.4",
 		"doctrine/lexer": "^1.0",
 		"guzzlehttp/guzzle": "^6.3.0",
@@ -58,15 +58,15 @@
 		"typo3/class-alias-loader": "^1.0",
 		"typo3/cms-cli": "^2.0",
 		"typo3/cms-composer-installers": "^2.0",
-		"typo3fluid/fluid": "^2.4"
+		"typo3fluid/fluid": "^2.5.2"
 	},
 	"require-dev": {
-		"codeception/codeception": "^2.3",
+		"codeception/codeception": "^2.4.4",
 		"enm1989/chromedriver": "~2.30",
 		"fiunchinho/phpunit-randomizer": "^4.0",
-		"friendsofphp/php-cs-fixer": "^2.0",
+		"friendsofphp/php-cs-fixer": "^2.12.2",
 		"typo3/cms-styleguide": "^9.1",
-		"typo3/testing-framework": "^4.0"
+		"typo3/testing-framework": "^4.0.2"
 	},
 	"suggest": {
 		"ext-gd": "GDlib/Freetype is required for building images with text (GIFBUILDER) and can also be used to scale images",
diff --git a/composer.lock b/composer.lock
index ec9a92eee4d9..47ba30809019 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "1ab1ed9fd305d2ea65bd018ab16745e1",
+    "content-hash": "a71e25c63829d22da3013a310006d675",
     "packages": [
         {
             "name": "cogpowered/finediff",
diff --git a/typo3/sysext/core/composer.json b/typo3/sysext/core/composer.json
index b24bebaae6d3..c81f31707338 100644
--- a/typo3/sysext/core/composer.json
+++ b/typo3/sysext/core/composer.json
@@ -20,7 +20,7 @@
 		"ext-xml": "*",
 		"cogpowered/finediff": "~0.3.1",
 		"doctrine/annotations": "^1.3",
-		"doctrine/dbal": "~2.7.0",
+		"doctrine/dbal": "~2.7.1",
 		"doctrine/instantiator": "~1.0.4",
 		"doctrine/lexer": "^1.0",
 		"guzzlehttp/guzzle": "^6.3.0",
@@ -39,15 +39,15 @@
 		"typo3/class-alias-loader": "^1.0",
 		"typo3/cms-cli": "^2.0",
 		"typo3/cms-composer-installers": "^2.0",
-		"typo3fluid/fluid": "^2.4"
+		"typo3fluid/fluid": "^2.5.2"
 	},
 	"require-dev": {
-		"codeception/codeception": "^2.3",
+		"codeception/codeception": "^2.4.4",
 		"enm1989/chromedriver": "~2.30",
 		"fiunchinho/phpunit-randomizer": "^4.0",
-		"friendsofphp/php-cs-fixer": "^2.0",
+		"friendsofphp/php-cs-fixer": "^2.12.2",
 		"typo3/cms-styleguide": "^9.1",
-		"typo3/testing-framework": "^4.0"
+		"typo3/testing-framework": "^4.0.2"
 	},
 	"suggest": {
 		"ext-fileinfo": "Used for proper file type detection in the file abstraction layer",
diff --git a/typo3/sysext/fluid/composer.json b/typo3/sysext/fluid/composer.json
index 575ece69e006..7043ecfd97e0 100644
--- a/typo3/sysext/fluid/composer.json
+++ b/typo3/sysext/fluid/composer.json
@@ -15,7 +15,7 @@
 	"require": {
 		"typo3/cms-core": "9.4.*@dev",
 		"typo3/cms-extbase": "9.4.*@dev",
-		"typo3fluid/fluid": "^2.4"
+		"typo3fluid/fluid": "^2.5.2"
 	},
 	"conflict": {
 		"typo3/cms": "*"
diff --git a/typo3/sysext/redirects/composer.json b/typo3/sysext/redirects/composer.json
index d0e16ba91767..496b03e153eb 100644
--- a/typo3/sysext/redirects/composer.json
+++ b/typo3/sysext/redirects/composer.json
@@ -15,7 +15,7 @@
 	"require": {
 		"typo3/cms-backend": "9.4.*@dev",
 		"typo3/cms-core": "9.4.*@dev",
-		"typo3fluid/fluid": "^2.4"
+		"typo3fluid/fluid": "^2.5.2"
 	},
 	"conflict": {
 		"typo3/cms": "*"
-- 
GitLab