[TASK] Run tests on new bamboo infrastructure 22/57522/50
authorChristian Kuhn <lolli@schwarzbu.ch>
Mon, 9 Jul 2018 22:41:03 +0000 (00:41 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sun, 15 Jul 2018 15:06:40 +0000 (17:06 +0200)
A new bamboo agent infrastructure has been deployed that
significantly changes how tests are executed: The agent
docker containers are now "stupid" and no longer bundle
specific php versions or daemons. Instead, they can run
own containers to start needed daemons for specific jobs
and execute needed php commands in ad-hoc containers that
provide the required php version.
Daemons needed for single jobs are defined in a
docker-compose.yml file provided by core itself.
This docker-compose.yml file can not be used directly for
local test execution since it has to fiddle quite a bit
with docker volume mounts, networks and executing users
that is specific to the bamboo environment.
However, another yml file can be added later to ease local
test execution in a similar way.
The patch rewrites the bamboo plan pre-merge and nightly
specs of core master to use the new infrastructure and brings
a couple of minor changes to tests that rely on a running
memcached or redis to retrieve the daemon host from an
environment variable.
There will be separated patche for older core versions.

Change-Id: I65777eeee6e28fca5b3d3d979498293cc91a77af
Resolves: #85563
Resolves: #36934
Releases: master
Reviewed-on: https://review.typo3.org/57522
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
12 files changed:
Build/bamboo/src/main/java/core/AbstractCoreSpec.java
Build/bamboo/src/main/java/core/NightlySpec.java
Build/bamboo/src/main/java/core/PreMergeSpec.java
Build/testing-docker/bamboo/docker-compose.yml [new file with mode: 0644]
typo3/sysext/core/Tests/Acceptance/Install.suite.yml
typo3/sysext/core/Tests/Acceptance/Install/Mysql/BlankPageCest.php
typo3/sysext/core/Tests/Acceptance/Install/Mysql/IntroductionPackageCest.php
typo3/sysext/core/Tests/Acceptance/Install/Postgresql/BlankPageCest.php
typo3/sysext/core/Tests/Acceptance/Install/Postgresql/IntroductionPackageCest.php
typo3/sysext/core/Tests/Functional/Cache/Backend/MemcachedBackendTest.php
typo3/sysext/core/Tests/Functional/Session/Backend/RedisSessionBackendTest.php
typo3/sysext/core/Tests/Unit/Cache/Backend/RedisBackendTest.php

index 7759aa1..209720c 100644 (file)
@@ -45,23 +45,22 @@ abstract public class AbstractCoreSpec {
     protected static String projectName = "TYPO3 Core";
     protected static String projectKey = "CORE";
 
-    protected String composerRootVersionEnvironment = "COMPOSER_ROOT_VERSION=9.3.0@dev";
+    protected String composerRootVersionEnvironment = "COMPOSER_ROOT_VERSION=9.4.0@dev";
 
     protected String testingFrameworkBuildPath = "vendor/typo3/testing-framework/Resources/Core/Build/";
 
+    /**
+     * @todo This can be removed if acceptance mysql tests are rewritten and active again
+     */
     protected String credentialsMysql =
-        "typo3DatabaseName=\"func\"" +
-        " typo3DatabaseUsername=\"funcu\"" +
+        "typo3DatabaseName=\"func_test\"" +
+        " typo3DatabaseUsername=\"root\"" +
         " typo3DatabasePassword=\"funcp\"" +
-        " typo3DatabaseHost=\"localhost\"" +
-        " typo3InstallToolPassword=\"klaus\"";
-
-    protected String installCredentialsMysql =
-        "typo3InstallMysqlDatabaseName=\"func_install\"" +
-        " typo3InstallMysqlDatabaseUsername=\"funcu\"" +
-        " typo3InstallMysqlDatabasePassword=\"funcp\"" +
-        " typo3InstallMysqlDatabaseHost=\"localhost\"";
+        " typo3DatabaseHost=\"mariadb10\"";
 
+    /**
+     * @todo This can be removed if acceptance mssql functional tests work again
+     */
     protected String credentialsMssql =
         "typo3DatabaseDriver=\"sqlsrv\"" +
         " typo3DatabaseName=\"func\"" +
@@ -71,20 +70,6 @@ abstract public class AbstractCoreSpec {
         " typo3DatabasePort=\"1433\"" +
         " typo3DatabaseCharset=\"utf-8\"";
 
-    protected String credentialsPgsql =
-        "typo3DatabaseDriver=\"pdo_pgsql\"" +
-        " typo3DatabaseName=\"func\"" +
-        " typo3DatabaseUsername=\"bamboo\"" +
-        " typo3DatabaseHost=\"localhost\"";
-
-    protected String installCredentialsPgsql =
-        "typo3InstallPostgresqlDatabaseName=\"func_atipgsql\"" +
-        " typo3InstallPostgresqlDatabaseUsername=\"bamboo\"" +
-        " typo3InstallPostgresqlDatabaseHost=\"localhost\"";
-
-    protected String credentialsSqlite =
-        "typo3DatabaseDriver=\"pdo_sqlite\"";
-
     /**
      * Default permissions on core plans
      *
@@ -158,142 +143,202 @@ abstract public class AbstractCoreSpec {
 
     /**
      * Job composer validate
+     *
+     * @param String requirementIdentifier
      */
-    protected Job getJobComposerValidate() {
+    protected Job getJobComposerValidate(String requirementIdentifier) {
         return new Job("Validate composer.json", new BambooKey("VC"))
         .description("Validate composer.json before actual tests are executed")
         .pluginConfigurations(this.getDefaultJobPluginConfiguration())
         .tasks(
             this.getTaskGitCloneRepository(),
             this.getTaskGitCherryPick(),
-            new CommandTask()
+            new ScriptTask()
                 .description("composer validate")
-                .executable("composer").argument("validate")
+                .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                .inlineBody(
+                    this.getScriptTaskBashInlineBody() +
+                    this.getScriptTaskComposer(requirementIdentifier) +
+                    "composer validate"
+                )
                 .environmentVariables(this.composerRootVersionEnvironment)
         )
+        .requirements(
+            this.getRequirementDocker10()
+        )
         .cleanWorkingDirectory(true);
     }
 
     /**
-     * Job acceptance test installs system on mysql
+     * Job acceptance test installs system on mariadb
      *
-     * @param Requirement requirement
-     * @param String requirementIdentfier
+     * @param String requirementIdentifier
      */
-    protected Job getJobAcceptanceTestInstallMysql(Requirement requirement, String requirementIdentifier) {
+    protected Job getJobAcceptanceTestInstallMysql(String requirementIdentifier) {
         return new Job("Accept inst my " + requirementIdentifier, new BambooKey("ACINSTMY" + requirementIdentifier))
-            .description("Install TYPO3 on mysql and load introduction package " + requirementIdentifier)
+            .description("Install TYPO3 on mariadb and load introduction package " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
                 this.getTaskPrepareAcceptanceTest(),
-                new CommandTask()
-                    .description("Install TYPO3 on mysql")
-                    .executable("codecept")
-                    .argument("run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=mysql,headless --xml reports.xml --html reports.html")
-                    .environmentVariables(this.installCredentialsMysql)
+                this.getTaskDockerDependenciesAcceptanceInstallMariadb10(),
+                new ScriptTask()
+                    .description("Install TYPO3 on mariadb 10")
+                    .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                    .inlineBody(
+                        this.getScriptTaskBashInlineBody() +
+                        "function codecept() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        -e typo3InstallMysqlDatabaseHost=${typo3InstallMysqlDatabaseHost} \\\n" +
+                        "        -e typo3InstallMysqlDatabaseName=${typo3InstallMysqlDatabaseName} \\\n" +
+                        "        -e typo3InstallMysqlDatabaseUsername=${typo3InstallMysqlDatabaseUsername} \\\n" +
+                        "        -e typo3InstallMysqlDatabasePassword=${typo3InstallMysqlDatabasePassword} \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./bin/codecept $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "codecept run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=mysql --xml reports.xml --html reports.html\n"
+                    )
             )
             .finalTasks(
+                this.getTaskStopDockerDependencies(),
                 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
-                    .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
-                this.getTaskDeleteMysqlDatabases(),
-                this.getTaskTearDownAcceptanceTestSetup()
-            )
-            .requirements(
-                requirement
+                    .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml")
             )
             .artifacts(new Artifact()
                 .name("Test Report")
                 .copyPattern("typo3temp/var/tests/AcceptanceReports/")
                 .shared(false)
             )
+            .requirements(
+                this.getRequirementDocker10()
+            )
             .cleanWorkingDirectory(true);
     }
 
     /**
      * Job acceptance test installs system and introduction package on pgsql
      *
-     * @param Requirement requirement
-     * @param String requirementIdentfier
+     * @param String requirementIdentifier
      */
-    protected Job getJobAcceptanceTestInstallPgsql(Requirement requirement, String requirementIdentifier) {
+    protected Job getJobAcceptanceTestInstallPgsql(String requirementIdentifier) {
         return new Job("Accept inst pg " + requirementIdentifier, new BambooKey("ACINSTPG" + requirementIdentifier))
         .description("Install TYPO3 on pgsql and load introduction package " + requirementIdentifier)
         .pluginConfigurations(this.getDefaultJobPluginConfiguration())
         .tasks(
             this.getTaskGitCloneRepository(),
             this.getTaskGitCherryPick(),
-            this.getTaskComposerInstall(),
+            this.getTaskComposerInstall(requirementIdentifier),
             this.getTaskPrepareAcceptanceTest(),
-            new CommandTask()
-                .description("Install TYPO3 on postgresql")
-                .executable("codecept")
-                .argument("run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=postgresql,headless --xml reports.xml --html reports.html")
-                .environmentVariables(this.installCredentialsPgsql)
+            this.getTaskDockerDependenciesAcceptanceInstallPostgres10(),
+            new ScriptTask()
+                .description("Install TYPO3 on postgresql 10")
+                .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                .inlineBody(
+                    this.getScriptTaskBashInlineBody() +
+                    "function codecept() {\n" +
+                    "    docker run \\\n" +
+                    "        -u ${HOST_UID} \\\n" +
+                    "        -v /etc/passwd:/etc/passwd \\\n" +
+                    "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                    "        -e typo3InstallPostgresqlDatabaseHost=${typo3InstallPostgresqlDatabaseHost} \\\n" +
+                    "        -e typo3InstallPostgresqlDatabaseName=${typo3InstallPostgresqlDatabaseName} \\\n" +
+                    "        -e typo3InstallPostgresqlDatabaseUsername=${typo3InstallPostgresqlDatabaseUsername} \\\n" +
+                    "        -e typo3InstallPostgresqlDatabasePassword=${typo3InstallPostgresqlDatabasePassword} \\\n" +
+                    "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                    "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                    "        --rm \\\n" +
+                    "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                    "        bin/bash -c \"cd ${PWD}; ./bin/codecept $*\"\n" +
+                    "}\n" +
+                    "\n" +
+                    "codecept run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=postgresql --xml reports.xml --html reports.html\n"
+                )
         )
         .finalTasks(
+            this.getTaskStopDockerDependencies(),
             new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
-                .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
-            this.getTaskDeletePgsqlDatabases(),
-            this.getTaskTearDownAcceptanceTestSetup()
-        )
-        .requirements(
-            requirement
+                .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml")
         )
         .artifacts(new Artifact()
             .name("Test Report")
             .copyPattern("typo3temp/var/tests/AcceptanceReports/")
             .shared(false)
         )
+        .requirements(
+            this.getRequirementDocker10()
+        )
         .cleanWorkingDirectory(true);
     }
 
     /**
      * Job acceptance test installs system and introduction package on sqlite
      *
-     * @param Requirement requirement
-     * @param String requirementIdentfier
+     * @param String requirementIdentifier
      */
-    protected Job getJobAcceptanceTestInstallSqlite(Requirement requirement, String requirementIdentifier) {
+    protected Job getJobAcceptanceTestInstallSqlite(String requirementIdentifier) {
         return new Job("Accept inst sq " + requirementIdentifier, new BambooKey("ACINSTSQ" + requirementIdentifier))
         .description("Install TYPO3 on sqlite and load introduction package " + requirementIdentifier)
         .pluginConfigurations(this.getDefaultJobPluginConfiguration())
         .tasks(
             this.getTaskGitCloneRepository(),
             this.getTaskGitCherryPick(),
-            this.getTaskComposerInstall(),
+            this.getTaskComposerInstall(requirementIdentifier),
             this.getTaskPrepareAcceptanceTest(),
-            new CommandTask()
+            this.getTaskDockerDependenciesAcceptanceInstallSqlite(),
+            new ScriptTask()
                 .description("Install TYPO3 on sqlite")
-                .executable("codecept")
-                .argument("run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=sqlite,headless --xml reports.xml --html reports.html")
+                .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                .inlineBody(
+                    this.getScriptTaskBashInlineBody() +
+                    "function codecept() {\n" +
+                    "    docker run \\\n" +
+                    "        -u ${HOST_UID} \\\n" +
+                    "        -v /etc/passwd:/etc/passwd \\\n" +
+                    "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                    "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                    "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                    "        --rm \\\n" +
+                    "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                    "        bin/bash -c \"cd ${PWD}; ./bin/codecept $*\"\n" +
+                    "}\n" +
+                    "\n" +
+                    "codecept run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=sqlite --xml reports.xml --html reports.html\n"
+                )
         )
         .finalTasks(
+            this.getTaskStopDockerDependencies(),
             new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
-                .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
-            this.getTaskTearDownAcceptanceTestSetup()
-        )
-        .requirements(
-            requirement
+                .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml")
         )
         .artifacts(new Artifact()
             .name("Test Report")
             .copyPattern("typo3temp/var/tests/AcceptanceReports/")
             .shared(false)
         )
+        .requirements(
+            this.getRequirementDocker10()
+        )
         .cleanWorkingDirectory(true);
     }
 
     /**
      * Jobs for mysql based acceptance tests
      *
+     * @todo Currently disabled and broken
+     *
      * @param int numberOfChunks
-     * @param Requirement requirement
      * @param String requirementIdentifier
      */
-    protected ArrayList<Job> getJobsAcceptanceTestsMysql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
+    protected ArrayList<Job> getJobsAcceptanceTestsMysql(int numberOfChunks, String requirementIdentifier) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -307,7 +352,7 @@ abstract public class AbstractCoreSpec {
                 .tasks(
                     this.getTaskGitCloneRepository(),
                     this.getTaskGitCherryPick(),
-                    this.getTaskComposerInstall(),
+                    this.getTaskComposerInstall(requirementIdentifier),
                     this.getTaskPrepareAcceptanceTest(),
                     new ScriptTask()
                         .description("Split acceptance tests")
@@ -323,19 +368,18 @@ abstract public class AbstractCoreSpec {
                         .environmentVariables(this.credentialsMysql)
                 )
                 .finalTasks(
+                    this.getTaskStopDockerDependencies(),
                     new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
-                        .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
-                    this.getTaskDeleteMysqlDatabases(),
-                    this.getTaskTearDownAcceptanceTestSetup()
-                )
-                .requirements(
-                    requirement
+                        .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml")
                 )
                 .artifacts(new Artifact()
                     .name("Test Report")
                     .copyPattern("typo3temp/var/tests/AcceptanceReports/")
                     .shared(false)
                 )
+                .requirements(
+                    this.getRequirementDocker10()
+                )
                 .cleanWorkingDirectory(true)
                 .enabled(false)
             );
@@ -348,10 +392,9 @@ abstract public class AbstractCoreSpec {
      * Jobs for mysql based functional tests
      *
      * @param int numberOfChunks
-     * @param Requirement requirement
      * @param String requirementIdentifier
      */
-    protected ArrayList<Job> getJobsFunctionalTestsMysql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
+    protected ArrayList<Job> getJobsFunctionalTestsMysql(int numberOfChunks, String requirementIdentifier) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -365,24 +408,42 @@ abstract public class AbstractCoreSpec {
                 .tasks(
                     this.getTaskGitCloneRepository(),
                     this.getTaskGitCherryPick(),
-                    this.getTaskComposerInstall(),
-                    this.getTaskSplitFunctionalJobs(numberOfChunks),
+                    this.getTaskComposerInstall(requirementIdentifier),
+                    this.getTaskDockerDependenciesFunctionalMariadb10(),
+                    this.getTaskSplitFunctionalJobs(numberOfChunks, requirementIdentifier),
                     new ScriptTask()
                         .description("Run phpunit with functional chunk " + formattedI)
                         .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                         .inlineBody(
                             this.getScriptTaskBashInlineBody() +
-                            "./bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
+                            "function phpunit() {\n" +
+                            "    docker run \\\n" +
+                            "        -u ${HOST_UID} \\\n" +
+                            "        -v /etc/passwd:/etc/passwd \\\n" +
+                            "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                            "        -e typo3DatabaseName=func_test \\\n" +
+                            "        -e typo3DatabaseUsername=root \\\n" +
+                            "        -e typo3DatabasePassword=funcp \\\n" +
+                            "        -e typo3DatabaseHost=mariadb10 \\\n" +
+                            "        -e typo3TestingRedisHost=${BAMBOO_COMPOSE_PROJECT_NAME}sib_redis4_1 \\\n" +
+                            "        -e typo3TestingMemcachedHost=${BAMBOO_COMPOSE_PROJECT_NAME}sib_memcached1-5_1 \\\n" +
+                            "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                            "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                            "        --rm \\\n" +
+                            "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                            "        bin/bash -c \"cd ${PWD}; ./bin/phpunit $*\"\n" +
+                            "}\n" +
+                            "\n" +
+                            "phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
                         )
-                        .environmentVariables(this.credentialsMysql)
                 )
                 .finalTasks(
-                    this.getTaskDeleteMysqlDatabases(),
+                    this.getTaskStopDockerDependencies(),
                     new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                         .resultDirectories("test-reports/phpunit.xml")
                 )
                 .requirements(
-                    requirement
+                    this.getRequirementDocker10()
                 )
                 .cleanWorkingDirectory(true)
             );
@@ -394,11 +455,12 @@ abstract public class AbstractCoreSpec {
     /**
      * Jobs for mssql based functional tests
      *
+     * @todo Currently disabled and broken
+     *
      * @param int numberOfChunks
-     * @param Requirement requirement
      * @param String requirementIdentifier
      */
-    protected ArrayList<Job> getJobsFunctionalTestsMssql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
+    protected ArrayList<Job> getJobsFunctionalTestsMssql(int numberOfChunks, String requirementIdentifier) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -412,8 +474,8 @@ abstract public class AbstractCoreSpec {
                 .tasks(
                     this.getTaskGitCloneRepository(),
                     this.getTaskGitCherryPick(),
-                    this.getTaskComposerInstall(),
-                    this.getTaskSplitFunctionalJobs(numberOfChunks),
+                    this.getTaskComposerInstall(requirementIdentifier),
+                    this.getTaskSplitFunctionalJobs(numberOfChunks, requirementIdentifier),
                     new ScriptTask()
                         .description("Run phpunit with functional chunk " + formattedI)
                         .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
@@ -424,12 +486,12 @@ abstract public class AbstractCoreSpec {
                         .environmentVariables(this.credentialsMssql)
                 )
                 .finalTasks(
-                    this.getTaskDeleteMssqlDatabases(),
+                    this.getTaskStopDockerDependencies(),
                     new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                         .resultDirectories("test-reports/phpunit.xml")
                 )
                 .requirements(
-                    requirement
+                    this.getRequirementDocker10()
                 )
                 .cleanWorkingDirectory(true)
                 .enabled(false)
@@ -443,10 +505,9 @@ abstract public class AbstractCoreSpec {
      * Jobs for pgsql based functional tests
      *
      * @param int numberOfChunks
-     * @param Requirement requirement
      * @param String requirementIdentifier
      */
-    protected ArrayList<Job> getJobsFunctionalTestsPgsql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
+    protected ArrayList<Job> getJobsFunctionalTestsPgsql(int numberOfChunks, String requirementIdentifier) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -460,24 +521,43 @@ abstract public class AbstractCoreSpec {
                 .tasks(
                     this.getTaskGitCloneRepository(),
                     this.getTaskGitCherryPick(),
-                    this.getTaskComposerInstall(),
-                    this.getTaskSplitFunctionalJobs(numberOfChunks),
+                    this.getTaskComposerInstall(requirementIdentifier),
+                    this.getTaskSplitFunctionalJobs(numberOfChunks, requirementIdentifier),
+                    this.getTaskDockerDependenciesFunctionalPostgres10(),
                     new ScriptTask()
                         .description("Run phpunit with functional chunk " + formattedI)
                         .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                         .inlineBody(
                             this.getScriptTaskBashInlineBody() +
-                            "./bin/phpunit --exclude-group not-postgres --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
+                            "function phpunit() {\n" +
+                            "    docker run \\\n" +
+                            "        -u ${HOST_UID} \\\n" +
+                            "        -v /etc/passwd:/etc/passwd \\\n" +
+                            "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                            "        -e typo3DatabaseDriver=pdo_pgsql \\\n" +
+                            "        -e typo3DatabaseName=bamboo \\\n" +
+                            "        -e typo3DatabaseUsername=bamboo \\\n" +
+                            "        -e typo3DatabaseHost=postgres10 \\\n" +
+                            "        -e typo3DatabasePassword=funcp \\\n" +
+                            "        -e typo3TestingRedisHost=redis4 \\\n" +
+                            "        -e typo3TestingMemcachedHost=memcached1-5 \\\n" +
+                            "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                            "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                            "        --rm \\\n" +
+                            "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                            "        bin/bash -c \"cd ${PWD}; ./bin/phpunit $*\"\n" +
+                            "}\n" +
+                            "\n" +
+                            "phpunit --exclude-group not-postgres --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
                         )
-                        .environmentVariables(this.credentialsPgsql)
                 )
                 .finalTasks(
-                    this.getTaskDeletePgsqlDatabases(),
+                    this.getTaskStopDockerDependencies(),
                     new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                         .resultDirectories("test-reports/phpunit.xml")
                 )
                 .requirements(
-                    requirement
+                    this.getRequirementDocker10()
                 )
                 .cleanWorkingDirectory(true)
             );
@@ -490,10 +570,9 @@ abstract public class AbstractCoreSpec {
      * Jobs for sqlite based functional tests
      *
      * @param int numberOfChunks
-     * @param Requirement requirement
      * @param String requirementIdentifier
      */
-    protected ArrayList<Job> getJobsFunctionalTestsSqlite(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
+    protected ArrayList<Job> getJobsFunctionalTestsSqlite(int numberOfChunks, String requirementIdentifier) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -507,23 +586,39 @@ abstract public class AbstractCoreSpec {
                 .tasks(
                     this.getTaskGitCloneRepository(),
                     this.getTaskGitCherryPick(),
-                    this.getTaskComposerInstall(),
-                    this.getTaskSplitFunctionalJobs(numberOfChunks),
+                    this.getTaskComposerInstall(requirementIdentifier),
+                    this.getTaskSplitFunctionalJobs(numberOfChunks, requirementIdentifier),
+                    this.getTaskDockerDependenciesFunctionalSqlite(),
                     new ScriptTask()
                         .description("Run phpunit with functional chunk " + formattedI)
                         .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                         .inlineBody(
                             this.getScriptTaskBashInlineBody() +
-                            "./bin/phpunit --exclude-group not-sqlite --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
+                            "function phpunit() {\n" +
+                            "    docker run \\\n" +
+                            "        -u ${HOST_UID} \\\n" +
+                            "        -v /etc/passwd:/etc/passwd \\\n" +
+                            "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                            "        -e typo3DatabaseDriver=pdo_sqlite \\\n" +
+                            "        -e typo3TestingRedisHost=redis4 \\\n" +
+                            "        -e typo3TestingMemcachedHost=memcached1-5 \\\n" +
+                            "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                            "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                            "        --rm \\\n" +
+                            "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                            "        bin/bash -c \"cd ${PWD}; ./bin/phpunit $*\"\n" +
+                            "}\n" +
+                            "\n" +
+                            "phpunit --exclude-group not-sqlite --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
                         )
-                        .environmentVariables(this.credentialsSqlite)
                 )
                 .finalTasks(
+                    this.getTaskStopDockerDependencies(),
                     new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                         .resultDirectories("test-reports/phpunit.xml")
                 )
                 .requirements(
-                    requirement
+                    this.getRequirementDocker10()
                 )
                 .cleanWorkingDirectory(true)
             );
@@ -534,33 +629,48 @@ abstract public class AbstractCoreSpec {
 
     /**
      * Job with integration test checking for valid @xy annotations
+     *
+     * @param String requirementIdentifier
      */
-    protected Job getJobIntegrationAnnotations() {
+    protected Job getJobIntegrationAnnotations(String requirementIdentifier) {
         return new Job("Integration annotations", new BambooKey("IANNO"))
             .description("Check docblock-annotations by executing Build/Scripts/annotationChecker.php script")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
                 new ScriptTask()
                     .description("Execute annotations check script")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "./Build/Scripts/annotationChecker.php\n"
+                        "function annotationChecker() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./Build/Scripts/annotationChecker.php $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "annotationChecker"
                     )
             )
             .requirements(
-                this.getRequirementPhpVersion72()
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
 
     /**
      * Job with various smaller script tests
+     *
+     * @param String requirementIdentifier
      */
-    protected Job getJobIntegrationVarious() {
+    protected Job getJobIntegrationVarious(String requirementIdentifier) {
         // Exception code checker, xlf, permissions, rst file check
         return new Job("Integration various", new BambooKey("CDECC"))
             .description("Checks duplicate exceptions, git submodules, xlf files, permissions, rst")
@@ -568,7 +678,7 @@ abstract public class AbstractCoreSpec {
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
                 new ScriptTask()
                     .description("Run duplicate exception code check script")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
@@ -605,7 +715,18 @@ abstract public class AbstractCoreSpec {
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "./Build/Scripts/validateRstFiles.php"
+                        "function validateRstFiles() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./Build/Scripts/validateRstFiles.php $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "validateRstFiles"
                     ),
                 new ScriptTask()
                     .description("Run path length check")
@@ -619,63 +740,118 @@ abstract public class AbstractCoreSpec {
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "./Build/Scripts/extensionScannerRstFileReferences.php"
+                        "function extensionScannerRstFileReferences() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./Build/Scripts/extensionScannerRstFileReferences.php $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "extensionScannerRstFileReferences"
                     ),
                 new ScriptTask()
                     .description("Run functional fixture csv format checker")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "./Build/Scripts/checkIntegrityCsvFixtures.php"
+                        "function checkIntegrityCsvFixtures() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./Build/Scripts/checkIntegrityCsvFixtures.php $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "checkIntegrityCsvFixtures"
                     ),
                 new ScriptTask()
                     .description("Run composer.json integrity check")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "./Build/Scripts/checkIntegrityComposer.php"
-                   )
-           )
+                        "function checkIntegrityComposer() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./Build/Scripts/checkIntegrityComposer.php $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "checkIntegrityComposer"
+                    )
+            )
             .requirements(
-                this.getRequirementPhpVersion72()
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
 
     /**
      * Job for javascript unit tests
+     *
+     * @param String requirementIdentifier
      */
-    protected Job getJobUnitJavaScript() {
+    protected Job getJobUnitJavaScript(String requirementIdentifier) {
         return new Job("Unit JavaScript", new BambooKey("JSUT"))
             .description("Run JavaScript unit tests")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
                 new ScriptTask()
                     .description("yarn install in Build/ dir")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
+                        "function yarn() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        -e HOME=${HOME} \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}/Build; yarn $*\"\n" +
+                        "}\n" +
+                        "\n" +
                         "yarn install"
-                    )
-                    .workingSubdirectory("Build/"),
+                    ),
                 new ScriptTask()
                     .description("Run tests")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "./Build/node_modules/karma/bin/karma start " + this.testingFrameworkBuildPath + "Configuration/JSUnit/karma.conf.js --single-run"
+                        "function karma() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        -e HOME=${HOME} \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./Build/node_modules/karma/bin/karma $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "karma start " + this.testingFrameworkBuildPath + "Configuration/JSUnit/karma.conf.js --single-run"
                     )
             )
             .finalTasks(
                 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                     .resultDirectories("typo3temp/var/tests/*")
             )
-            .requirements(
-                this.getRequirementPhpVersion72()
-            )
             .artifacts(
                 new Artifact()
                     .name("Clover Report (System)")
@@ -683,16 +859,18 @@ abstract public class AbstractCoreSpec {
                     .location("Build/target/site/clover")
                     .shared(false)
             )
+            .requirements(
+                this.getRequirementDocker10()
+            )
             .cleanWorkingDirectory(true);
     }
 
     /**
      * Job for PHP lint
      *
-     * @param Requirement requirement
-     * @param String requirementIdentfier
+     * @param String requirementIdentifier
      */
-    protected Job getJobLintPhp(Requirement requirement, String requirementIdentifier) {
+    protected Job getJobLintPhp(String requirementIdentifier) {
         return new Job("Lint " + requirementIdentifier, new BambooKey("L" + requirementIdentifier))
             .description("Run php -l on source files for linting " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
@@ -704,19 +882,33 @@ abstract public class AbstractCoreSpec {
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "find . -name \\*.php -print0 | xargs -0 -n1 -P2 php -l >/dev/null\n"
+                        "function runLint() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        -e HOME=${HOME} \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; find . -name \\*.php -print0 | xargs -0 -n1 -P2 php -n -c /etc/php/cli-no-xdebug/php.ini -l >/dev/null\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "runLint"
                     )
             )
             .requirements(
-                requirement
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
 
     /**
      * Job for lint npm scss and typescript
+     *
+     * @param String requirementIdentifier
      */
-    protected Job getJobLintScssTs() {
+    protected Job getJobLintScssTs(String requirementIdentifier) {
         return new Job("Lint scss ts", new BambooKey("LSTS"))
             .description("Run npm lint, run npm run build-js")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
@@ -728,19 +920,58 @@ abstract public class AbstractCoreSpec {
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
+                        "function yarn() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        -e HOME=${HOME} \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}/Build; yarn $*\"\n" +
+                        "}\n" +
+                        "\n" +
                         "yarn install"
-                    )
-                    .workingSubdirectory("Build/"),
-                new NpmTask()
+                    ),
+                new ScriptTask()
                     .description("Run npm lint")
-                    .nodeExecutable("Node.js")
-                    .workingSubdirectory("Build/")
-                    .command("run lint"),
-                new NpmTask()
+                    .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                    .inlineBody(
+                        this.getScriptTaskBashInlineBody() +
+                        "function npm() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        -e HOME=${HOME} \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}/Build; npm $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "npm run lint"
+                    ),
+                new ScriptTask()
                     .description("Run npm build-js")
-                    .nodeExecutable("Node.js")
-                    .workingSubdirectory("Build/")
-                    .command("run build-js"),
+                    .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                    .inlineBody(
+                        this.getScriptTaskBashInlineBody() +
+                        "function npm() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        -e HOME=${HOME} \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}/Build; npm $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "npm run build-js"
+                    ),
                 new ScriptTask()
                     .description("git status to check for changed files after build-js")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
@@ -750,7 +981,7 @@ abstract public class AbstractCoreSpec {
                     )
             )
             .requirements(
-                new Requirement("system.imageVersion")
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
@@ -758,31 +989,44 @@ abstract public class AbstractCoreSpec {
     /**
      * Job for unit testing PHP
      *
-     * @param Requirement requirement
-     * @param String requirementIdentfier
+     * @param String requirementIdentifier
      */
-    protected Job getJobUnitPhp(Requirement requirement, String requirementIdentifier) {
+    protected Job getJobUnitPhp(String requirementIdentifier) {
         return new Job("Unit " + requirementIdentifier, new BambooKey("UT" + requirementIdentifier))
             .description("Run unit tests " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
+                this.getTaskDockerDependenciesUnit(),
                 new ScriptTask()
                     .description("Run phpunit")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTests.xml"
+                        "function phpunit() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTests.xml"
                     )
             )
             .finalTasks(
+                this.getTaskStopDockerDependencies(),
                 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                     .resultDirectories("test-reports/phpunit.xml")
             )
             .requirements(
-                requirement
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
@@ -790,31 +1034,44 @@ abstract public class AbstractCoreSpec {
     /**
      * Job for unit testing deprecated PHP
      *
-     * @param Requirement requirement
-     * @param String requirementIdentfier
+     * @param String requirementIdentifier
      */
-    protected Job getJobUnitDeprecatedPhp(Requirement requirement, String requirementIdentifier) {
+    protected Job getJobUnitDeprecatedPhp(String requirementIdentifier) {
         return new Job("Unit deprecated " + requirementIdentifier, new BambooKey("UTD" + requirementIdentifier))
             .description("Run deprecated unit tests " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
+                this.getTaskDockerDependenciesUnit(),
                 new ScriptTask()
                     .description("Run phpunit")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTestsDeprecated.xml"
+                        "function phpunit() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTestsDeprecated.xml"
                     )
             )
             .finalTasks(
+                this.getTaskStopDockerDependencies(),
                 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                     .resultDirectories("test-reports/phpunit.xml")
             )
             .requirements(
-                requirement
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
@@ -823,10 +1080,9 @@ abstract public class AbstractCoreSpec {
      * Jobs for unit testing PHP in random test order
      *
      * @param int numberOfRuns
-     * @param Requirement requirement
-     * @param String requirementIdentfier
+     * @param String requirementIdentifier
      */
-    protected ArrayList<Job> getJobUnitPhpRandom(int numberOfRuns, Requirement requirement, String requirementIdentifier) {
+    protected ArrayList<Job> getJobUnitPhpRandom(int numberOfRuns, String requirementIdentifier) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfRuns; i++) {
@@ -836,21 +1092,35 @@ abstract public class AbstractCoreSpec {
                 .tasks(
                     this.getTaskGitCloneRepository(),
                     this.getTaskGitCherryPick(),
-                    this.getTaskComposerInstall(),
+                    this.getTaskComposerInstall(requirementIdentifier),
+                    this.getTaskDockerDependenciesUnit(),
                     new ScriptTask()
                         .description("Run phpunit-randomizer")
                         .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                         .inlineBody(
                             this.getScriptTaskBashInlineBody() +
-                            "php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit-randomizer --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTests.xml --order rand"
+                            "function phpunitRandomizer() {\n" +
+                            "    docker run \\\n" +
+                            "        -u ${HOST_UID} \\\n" +
+                            "        -v /etc/passwd:/etc/passwd \\\n" +
+                            "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                            "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                            "        --network ${BAMBOO_COMPOSE_PROJECT_NAME}_test \\\n" +
+                            "        --rm \\\n" +
+                            "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                            "        bin/bash -c \"cd ${PWD}; php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit-randomizer $*\"\n" +
+                            "}\n" +
+                            "\n" +
+                            "phpunitRandomizer --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTests.xml --order rand"
                         )
                 )
                 .finalTasks(
+                    this.getTaskStopDockerDependencies(),
                     new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
                         .resultDirectories("test-reports/phpunit.xml")
                 )
                 .requirements(
-                    requirement
+                    this.getRequirementDocker10()
                 )
                 .cleanWorkingDirectory(true)
             );
@@ -865,8 +1135,7 @@ abstract public class AbstractCoreSpec {
     protected Task getTaskGitCloneRepository() {
         return new VcsCheckoutTask()
             .description("Checkout git core")
-            .checkoutItems(new CheckoutItem().defaultRepository())
-            .cleanCheckout(true);
+            .checkoutItems(new CheckoutItem().defaultRepository());
     }
 
     /**
@@ -890,168 +1159,187 @@ abstract public class AbstractCoreSpec {
 
     /**
      * Task definition to execute composer install
+     *
+     * @param String requirementIdentifier
      */
-    protected Task getTaskComposerInstall() {
-        return new CommandTask()
+    protected Task getTaskComposerInstall(String requirementIdentifier) {
+        return new ScriptTask()
             .description("composer install")
-            .executable("composer")
-            .argument("install -n")
+            .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+            .inlineBody(
+                this.getScriptTaskBashInlineBody() +
+                this.getScriptTaskComposer(requirementIdentifier) +
+                "composer install -n"
+            )
             .environmentVariables(this.composerRootVersionEnvironment);
     }
 
     /**
-     * Task to prepare an acceptance test starting selenium and others
+     * Task to prepare an acceptance test
      */
     protected Task getTaskPrepareAcceptanceTest() {
         return new ScriptTask()
-            .description("Start php web server, chromedriver, prepare environment")
+            .description("Prepare acceptance test environment")
             .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
             .inlineBody(
                 this.getScriptTaskBashInlineBody() +
-                "php -n -c /etc/php/cli-no-xdebug/php.ini -S localhost:8000 >/dev/null 2>&1 &\n" +
-                "echo $! > phpserver.pid\n" +
-                "\n" +
-                "./bin/chromedriver --url-base=/wd/hub >/dev/null 2>&1 &\n" +
-                "echo $! > chromedriver.pid\n" +
-                "\n" +
                 "mkdir -p typo3temp/var/tests/\n"
             );
     }
 
     /**
-     * Task to delete any created mysql test databases, used as final task
+     * Start docker sibling containers to execute acceptance tests on mariadb
      */
-    protected Task getTaskDeleteMysqlDatabases() {
+    protected Task getTaskDockerDependenciesAcceptanceInstallMariadb10() {
         return new ScriptTask()
-            .description("Delete mysql test dbs")
+            .description("Start docker siblings for acceptance test install mariadb")
             .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
             .inlineBody(
                 this.getScriptTaskBashInlineBody() +
-                "DB_STARTS_WITH=\"func_\"\n" +
-                "MUSER=\"funcu\"\n" +
-                "MPWD=\"funcp\"\n" +
-                "MYSQL=\"mysql\"\n" +
-                "DBS=\"$($MYSQL -u $MUSER -p\"$MPWD\" -Bse 'show databases')\"\n" +
-                "\n" +
-                "for db in $DBS; do\n" +
-                "    if [[ \"$db\" == $DB_STARTS_WITH* ]]; then\n" +
-                "        echo \"Deleting $db\"\n" +
-                "        $MYSQL -u $MUSER -p\"$MPWD\" -Bse \"drop database $db\"\n" +
-                "    fi\n" +
-                "done\n"
+                "cd Build/testing-docker/bamboo\n" +
+                "echo COMPOSE_PROJECT_NAME=${BAMBOO_COMPOSE_PROJECT_NAME}sib > .env\n" +
+                "docker-compose run start_dependencies_acceptance_install_mariadb10"
             );
     }
 
     /**
-     * Task to delete any created mssql test databases, used as final task
+     * Start docker sibling containers to execute acceptance tests on postgres
      */
-    protected Task getTaskDeleteMssqlDatabases() {
+    protected Task getTaskDockerDependenciesAcceptanceInstallPostgres10() {
         return new ScriptTask()
-            .description("Delete mssql test dbs")
+            .description("Start docker siblings for acceptance test install postgres")
             .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
             .inlineBody(
                 this.getScriptTaskBashInlineBody() +
-                "DBS=`/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Test1234!' -Q 'select name from sys.databases' | grep '^func_'`\n" +
-                "\n" +
-                "for db in $DBS; do\n" +
-                "    echo \"Deleteing $db\"\n" +
-                "    /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Test1234!' -Q \"drop database $db\"\n" +
-                "done\n"
+                "cd Build/testing-docker/bamboo\n" +
+                "echo COMPOSE_PROJECT_NAME=${BAMBOO_COMPOSE_PROJECT_NAME}sib > .env\n" +
+                "docker-compose run start_dependencies_acceptance_install_postgres10"
             );
     }
 
     /**
-     * Task to delete any created pgsql test databases, used as final task
+     * Start docker sibling containers to execute acceptance tests on sqlite
      */
-    protected Task getTaskDeletePgsqlDatabases() {
+    protected Task getTaskDockerDependenciesAcceptanceInstallSqlite() {
         return new ScriptTask()
-            .description("Delete pgsql test dbs")
+            .description("Start docker siblings for acceptance test install sqlite")
             .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
             .inlineBody(
                 this.getScriptTaskBashInlineBody() +
-                "DB_STARTS_WITH=\"func_\"\n" +
-                "PGUSER=\"bamboo\"\n" +
-                "DBS=\"$(/usr/bin/psql -qtA -c 'SELECT datname FROM pg_database WHERE datistemplate = false;' postgres)\"\n" +
-                "\n" +
-                "for db in $DBS; do\n" +
-                "    if [[ \"$db\" == $DB_STARTS_WITH* ]]; then\n" +
-                "        echo \"Deleting $db\"\n" +
-                "        /usr/bin/psql -qtA -c \"DROP DATABASE $db\" postgres\n" +
-                "    fi\n" +
-                "done\n"
+                "cd Build/testing-docker/bamboo\n" +
+                "echo COMPOSE_PROJECT_NAME=${BAMBOO_COMPOSE_PROJECT_NAME}sib > .env\n" +
+                "docker-compose run start_dependencies_acceptance_install_sqlite"
             );
     }
 
     /**
-     * Task to stop selenium and friends, opposite of getTaskPrepareAcceptanceTest, used as final task
+     * Start docker sibling containers to execute functional tests on mariadb
      */
-    protected Task getTaskTearDownAcceptanceTestSetup() {
+    protected Task getTaskDockerDependenciesFunctionalMariadb10() {
         return new ScriptTask()
-            .description("Stop acceptance test services like chromedriver and friends")
+            .description("Start docker siblings for functional tests on mariadb")
             .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
             .inlineBody(
                 this.getScriptTaskBashInlineBody() +
-                "kill -9 `cat phpserver.pid`\n" +
-                "kill `cat chromedriver.pid`\n"
+                "cd Build/testing-docker/bamboo\n" +
+                "echo COMPOSE_PROJECT_NAME=${BAMBOO_COMPOSE_PROJECT_NAME}sib > .env\n" +
+                "docker-compose run start_dependencies_functional_mariadb10"
             );
     }
 
     /**
-     * Task to split functional jobs into chunks
+     * Start docker sibling containers to execute functional tests on postgres
      */
-    protected Task getTaskSplitFunctionalJobs(int numberOfJobs) {
+    protected Task getTaskDockerDependenciesFunctionalPostgres10() {
         return new ScriptTask()
-            .description("Create list of test files to execute per job")
+            .description("Start docker siblings for functional tests on postgres10")
             .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
             .inlineBody(
                 this.getScriptTaskBashInlineBody() +
-                "./" + this.testingFrameworkBuildPath + "Scripts/splitFunctionalTests.php " + numberOfJobs + " -v"
+                "cd Build/testing-docker/bamboo\n" +
+                "echo COMPOSE_PROJECT_NAME=${BAMBOO_COMPOSE_PROJECT_NAME}sib > .env\n" +
+                "docker-compose run start_dependencies_functional_postgres10"
             );
     }
 
     /**
-     * Requirement for php 7.0
+     * Start docker sibling containers to execute functional tests on sqlite
      */
-    protected Requirement getRequirementPhpVersion70() {
-        return new Requirement("system.phpVersion")
-            .matchValue("7.0")
-            .matchType(Requirement.MatchType.EQUALS);
+    protected Task getTaskDockerDependenciesFunctionalSqlite() {
+        return new ScriptTask()
+            .description("Start docker siblings for functional tests on sqlite")
+            .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+            .inlineBody(
+                this.getScriptTaskBashInlineBody() +
+                "cd Build/testing-docker/bamboo\n" +
+                "echo COMPOSE_PROJECT_NAME=${BAMBOO_COMPOSE_PROJECT_NAME}sib > .env\n" +
+                "docker-compose run start_dependencies_functional_sqlite"
+            );
     }
 
     /**
-     * Requirement for php 7.1
+     * Start docker sibling containers to execute unit tests
      */
-    protected Requirement getRequirementPhpVersion71() {
-        return new Requirement("system.phpVersion")
-            .matchValue("7.1")
-            .matchType(Requirement.MatchType.EQUALS);
+    protected Task getTaskDockerDependenciesUnit() {
+        return new ScriptTask()
+            .description("Start docker siblings for unit tests")
+            .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+            .inlineBody(
+                this.getScriptTaskBashInlineBody() +
+                "cd Build/testing-docker/bamboo\n" +
+                "echo COMPOSE_PROJECT_NAME=${BAMBOO_COMPOSE_PROJECT_NAME}sib > .env\n" +
+                "docker-compose run start_dependencies_unit"
+            );
     }
 
     /**
-     * Requirement for php 7.2
+     * Stop started docker containers
      */
-    protected Requirement getRequirementPhpVersion72() {
-        return new Requirement("system.phpVersion")
-            .matchValue("7.2")
-            .matchType(Requirement.MatchType.EQUALS);
+    protected Task getTaskStopDockerDependencies() {
+        return new ScriptTask()
+            .description("Stop docker siblings")
+            .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+            .inlineBody(
+                this.getScriptTaskBashInlineBody() +
+                "cd Build/testing-docker/bamboo\n" +
+                "docker-compose down -v"
+            );
     }
 
     /**
-     * Requirement for php 7.0 or 7.1
+     * Task to split functional jobs into chunks
+     *
+     * @param int numberOfJobs
+     * @param String requirementIdentifier
      */
-    protected Requirement getRequirementPhpVersion70Or71() {
-        return new Requirement("system.phpVersion")
-            .matchValue("7\\.0|7\\.1")
-            .matchType(Requirement.MatchType.MATCHES);
+    protected Task getTaskSplitFunctionalJobs(int numberOfJobs, String requirementIdentifier) {
+        return new ScriptTask()
+            .description("Create list of test files to execute per job")
+            .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+            .inlineBody(
+                this.getScriptTaskBashInlineBody() +
+                "function splitFunctionalTests() {\n" +
+                "    docker run \\\n" +
+                "        -u ${HOST_UID} \\\n" +
+                "        -v /etc/passwd:/etc/passwd \\\n" +
+                "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                "        --rm \\\n" +
+                "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                "        bin/bash -c \"cd ${PWD}; ./" + this.testingFrameworkBuildPath + "Scripts/splitFunctionalTests.php $*\"\n" +
+                "}\n" +
+                "\n" +
+                "splitFunctionalTests " + numberOfJobs + " -v"
+            );
     }
 
     /**
-     * Requirement for php 7.0 or 7.1 or 7.2
+     * Requirement for docker 1.0 set by bamboo-agents
      */
-    protected Requirement getRequirementPhpVersion70Or71Or72() {
-        return new Requirement("system.phpVersion")
-            .matchValue("7\\.0|7\\.1|7\\.2")
-            .matchType(Requirement.MatchType.MATCHES);
+    protected Requirement getRequirementDocker10() {
+        return new Requirement("system.hasDocker")
+            .matchValue("1.0")
+            .matchType(Requirement.MatchType.EQUALS);
     }
 
     /**
@@ -1065,6 +1353,30 @@ abstract public class AbstractCoreSpec {
             "    bash \"$0\" \"$@\"\n" +
             "    exit \"$?\"\n" +
             "fi\n" +
+            "\n" +
+            "set -x\n" +
+            "\n";
+    }
+
+    /**
+     * A bash function aliasing 'composer' as docker command
+     *
+     * @param String requirementIdentifier
+     */
+    protected String getScriptTaskComposer(String requirementIdentifier) {
+        return
+            "function composer() {\n" +
+            "    docker run \\\n" +
+            "        -u ${HOST_UID} \\\n" +
+            "        -v /etc/passwd:/etc/passwd \\\n" +
+            "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+            "        -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} \\\n" +
+            "        -e HOME=${HOME} \\\n" +
+            "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+            "        --rm \\\n" +
+            "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+            "        bin/bash -c \"cd ${PWD}; composer $*\"\n" +
+            "}\n" +
             "\n";
     }
 }
index 9279792..21ff1d0 100644 (file)
@@ -66,49 +66,37 @@ public class NightlySpec extends AbstractCoreSpec {
      * Returns full Plan definition
      */
     Plan createPlan() {
-        // PREPARATION stage
-        ArrayList<Job> jobsPreparationStage = new ArrayList<Job>();
-
-        jobsPreparationStage.add(this.getJobComposerValidate());
-
-        Stage stagePreparation = new Stage("Preparation")
-            .jobs(jobsPreparationStage.toArray(new Job[jobsPreparationStage.size()]));
-
-
         // MAIN stage
         ArrayList<Job> jobsMainStage = new ArrayList<Job>();
 
-        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(this.getRequirementPhpVersion72(), "PHP72"));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(this.getRequirementPhpVersion72(), "PHP72"));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(this.getRequirementPhpVersion72(), "PHP72"));
-
-        jobsMainStage.addAll(this.getJobsAcceptanceTestsMysql(this.numberOfAcceptanceTestJobs, this.getRequirementPhpVersion72(), "PHP72"));
-
-        jobsMainStage.add(this.getJobCglCheckFullCore());
-
-        jobsMainStage.add(this.getJobIntegrationAnnotations());
-
-        jobsMainStage.add(this.getJobIntegrationVarious());
+        jobsMainStage.add(this.getJobComposerValidate("PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(this.numberOfFunctionalMysqlJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql("PHP72"));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql("PHP72"));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite("PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(this.numberOfFunctionalMssqlJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.addAll(this.getJobsAcceptanceTestsMysql(this.numberOfAcceptanceTestJobs, "PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(this.numberOfFunctionalPgsqlJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobCglCheckFullCore("PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(this.numberOfFunctionalSqliteJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobIntegrationAnnotations("PHP72"));
 
-        jobsMainStage.add(this.getJobUnitJavaScript());
+        jobsMainStage.add(this.getJobIntegrationVarious("PHP72"));
 
-        jobsMainStage.add(this.getJobLintPhp(this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(this.numberOfFunctionalMysqlJobs, "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(this.numberOfFunctionalMssqlJobs, "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(this.numberOfFunctionalPgsqlJobs, "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(this.numberOfFunctionalSqliteJobs, "PHP72"));
 
-        jobsMainStage.add(this.getJobLintScssTs());
+        jobsMainStage.add(this.getJobUnitJavaScript("PHP72"));
 
-        jobsMainStage.add(this.getJobUnitPhp(this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobLintPhp("PHP72"));
 
-        jobsMainStage.add(this.getJobUnitDeprecatedPhp(this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobLintScssTs("PHP72"));
 
-        jobsMainStage.addAll(this.getJobUnitPhpRandom(this.numberOfUnitRandomOrderJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobUnitPhp("PHP72"));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp("PHP72"));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(this.numberOfUnitRandomOrderJobs, "PHP72"));
 
         Stage stageMainStage = new Stage("Main stage")
             .jobs(jobsMainStage.toArray(new Job[jobsMainStage.size()]));
@@ -119,7 +107,6 @@ public class NightlySpec extends AbstractCoreSpec {
             .description("Execute TYPO3 core master nightly tests. Auto generated! See Build/bamboo of core git repository.")
             .pluginConfigurations(this.getDefaultPlanPluginConfiguration())
             .stages(
-                stagePreparation,
                 stageMainStage
             )
             .linkedRepositories("git.typo3.org Core")
@@ -143,26 +130,39 @@ public class NightlySpec extends AbstractCoreSpec {
 
     /**
      * Job checking CGL of all core php files
+     *
+     * @param String requirementIdentifier
      */
-    protected Job getJobCglCheckFullCore() {
+    protected Job getJobCglCheckFullCore(String requirementIdentifier) {
         return new Job("Integration CGL", new BambooKey("CGLCHECK"))
             .description("Check coding guidelines of full core")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
                 new ScriptTask()
                     .description("Execute cgl check")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "php -n -c /etc/php/cli-no-xdebug/php.ini bin/php-cs-fixer fix -v --dry-run --path-mode intersection --config=Build/.php_cs typo3/\n" +
-                        "exit $?\n"
+                        "function phpCsFixer() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; php -n -c /etc/php/cli-no-xdebug/php.ini bin/php-cs-fixer $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "phpCsFixer fix -v --dry-run --path-mode intersection --config=Build/.php_cs typo3/\n" +
+                        "exit $?"
                     )
             )
             .requirements(
-                this.getRequirementPhpVersion72()
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
index 962c8de..9b5c1a3 100644 (file)
@@ -76,48 +76,44 @@ public class PreMergeSpec extends AbstractCoreSpec {
     Plan createPlan() {
         // PREPARATION stage
         ArrayList<Job> jobsPreparationStage = new ArrayList<Job>();
-
         jobsPreparationStage.add(this.getJobBuildLabels());
-
-        jobsPreparationStage.add(this.getJobCglCheckGitCommit());
-
-        jobsPreparationStage.add(this.getJobComposerValidate());
-
         Stage stagePreparation = new Stage("Preparation")
             .jobs(jobsPreparationStage.toArray(new Job[jobsPreparationStage.size()]));
 
+        // EARLY stage
+        ArrayList<Job> jobsEarlyStage = new ArrayList<Job>();
+        jobsEarlyStage.add(this.getJobCglCheckGitCommit("PHP72"));
+        jobsEarlyStage.add(this.getJobComposerValidate("PHP72"));
+        Stage stageEarly = new Stage("Early")
+            .jobs(jobsEarlyStage.toArray(new Job[jobsEarlyStage.size()]));
+
         // MAIN stage
         ArrayList<Job> jobsMainStage = new ArrayList<Job>();
 
-        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(this.getRequirementPhpVersion72(), "PHP72"));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(this.getRequirementPhpVersion72(), "PHP72"));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(this.getRequirementPhpVersion72(), "PHP72"));
-
-        jobsMainStage.addAll(this.getJobsAcceptanceTestsMysql(this.numberOfAcceptanceTestJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql("PHP72"));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql("PHP72"));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite("PHP72"));
 
-        jobsMainStage.add(this.getJobIntegrationAnnotations());
+        jobsMainStage.addAll(this.getJobsAcceptanceTestsMysql(this.numberOfAcceptanceTestJobs, "PHP72"));
 
-        jobsMainStage.add(this.getJobIntegrationVarious());
+        jobsMainStage.add(this.getJobIntegrationAnnotations("PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(this.numberOfFunctionalMysqlJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobIntegrationVarious("PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(this.numberOfFunctionalMssqlJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(this.numberOfFunctionalMysqlJobs, "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(this.numberOfFunctionalMssqlJobs, "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(this.numberOfFunctionalPgsqlJobs, "PHP72"));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(this.numberOfFunctionalSqliteJobs, "PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(this.numberOfFunctionalPgsqlJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobUnitJavaScript("PHP72"));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(this.numberOfFunctionalSqliteJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobLintPhp("PHP72"));
 
-        jobsMainStage.add(this.getJobUnitJavaScript());
+        jobsMainStage.add(this.getJobLintScssTs("PHP72"));
 
-        jobsMainStage.add(this.getJobLintPhp(this.getRequirementPhpVersion72(), "PHP72"));
-
-        jobsMainStage.add(this.getJobLintScssTs());
-
-        jobsMainStage.add(this.getJobUnitPhp(this.getRequirementPhpVersion72(), "PHP72"));
-
-        jobsMainStage.add(this.getJobUnitDeprecatedPhp(this.getRequirementPhpVersion72(), "PHP72"));
-
-        jobsMainStage.addAll(this.getJobUnitPhpRandom(this.numberOfUnitRandomOrderJobs, this.getRequirementPhpVersion72(), "PHP72"));
+        jobsMainStage.add(this.getJobUnitPhp("PHP72"));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp("PHP72"));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(this.numberOfUnitRandomOrderJobs, "PHP72"));
 
         Stage stageMainStage = new Stage("Main stage")
             .jobs(jobsMainStage.toArray(new Job[jobsMainStage.size()]));
@@ -128,6 +124,7 @@ public class PreMergeSpec extends AbstractCoreSpec {
             .pluginConfigurations(this.getDefaultPlanPluginConfiguration())
             .stages(
                 stagePreparation,
+                stageEarly,
                 stageMainStage
             )
             .linkedRepositories("git.typo3.org Core")
@@ -188,30 +185,46 @@ public class PreMergeSpec extends AbstractCoreSpec {
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody("echo \"I'm just here for the labels!\"")
             )
+            .requirements(
+                this.getRequirementDocker10()
+            )
             .cleanWorkingDirectory(true);
     }
 
     /**
      * Job checking CGL of last git commit
+     *
+     * @param String requirementIdentifier
      */
-    protected Job getJobCglCheckGitCommit() {
+    protected Job getJobCglCheckGitCommit(String requirementIdentifier) {
         return new Job("Integration CGL", new BambooKey("CGLCHECK"))
             .description("Check coding guidelines by executing Build/Scripts/cglFixMyCommit.sh script")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
                 this.getTaskGitCherryPick(),
-                this.getTaskComposerInstall(),
+                this.getTaskComposerInstall(requirementIdentifier),
                 new ScriptTask()
                     .description("Execute cgl check script")
                     .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
                     .inlineBody(
                         this.getScriptTaskBashInlineBody() +
-                        "./Build/Scripts/cglFixMyCommit.sh dryrun\n"
+                        "function cglFixMyCommit() {\n" +
+                        "    docker run \\\n" +
+                        "        -u ${HOST_UID} \\\n" +
+                        "        -v /etc/passwd:/etc/passwd \\\n" +
+                        "        -v ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data:/srv/bamboo/xml-data/build-dir/ \\\n" +
+                        "        --name ${BAMBOO_COMPOSE_PROJECT_NAME}sib_adhoc \\\n" +
+                        "        --rm \\\n" +
+                        "        typo3gmbh/" + requirementIdentifier.toLowerCase() + ":latest \\\n" +
+                        "        bin/bash -c \"cd ${PWD}; ./Build/Scripts/cglFixMyCommit.sh $*\"\n" +
+                        "}\n" +
+                        "\n" +
+                        "cglFixMyCommit dryrun\n"
                     )
             )
             .requirements(
-                this.getRequirementPhpVersion72()
+                this.getRequirementDocker10()
             )
             .cleanWorkingDirectory(true);
     }
diff --git a/Build/testing-docker/bamboo/docker-compose.yml b/Build/testing-docker/bamboo/docker-compose.yml
new file mode 100644 (file)
index 0000000..3cb4b56
--- /dev/null
@@ -0,0 +1,154 @@
+version: '2.3'
+services:
+  chrome:
+    image: selenium/standalone-chrome:3.12
+    networks:
+      - test
+  mariadb10:
+    image: mariadb:10
+    environment:
+      MYSQL_ROOT_PASSWORD: funcp
+    tmpfs:
+      - /var/lib/mysql/:rw,noexec,nosuid
+    networks:
+      - test
+  postgres10:
+    image: postgres:10
+    environment:
+      POSTGRES_PASSWORD: funcp
+      POSTGRES_USER: ${HOST_USER}
+    volumes:
+      - /etc/passwd:/etc/passwd,ro
+    tmpfs:
+      - /var/lib/postgresql/data:rw,noexec,nosuid
+    networks:
+      - test
+  redis4:
+    image: redis:4-alpine
+    networks:
+      - test
+  memcached1-5:
+    image: memcached:1.5-alpine
+    networks:
+      - test
+  web:
+    image: typo3gmbh/php72:latest
+    user: ${HOST_UID}
+    stop_grace_period: 1s
+    networks:
+      - test
+    volumes:
+      - bamboo-data:/srv/bamboo/xml-data/build-dir
+    command: php -n -c /etc/php/cli-no-xdebug/php.ini -S web:8000 -t /srv/bamboo/xml-data/build-dir/${bamboo_buildKey}
+
+  start_dependencies_acceptance_install_mariadb10:
+    image: alpine:3.8
+    links:
+      - mariadb10
+      - chrome
+      - web
+    networks:
+      - test
+    command: >
+      /bin/sh -c "
+        echo Waiting for db start...;
+        while ! nc -z mariadb10 3306;
+        do
+          sleep 1;
+        done;
+        echo Connected!;
+      "
+
+  start_dependencies_acceptance_install_postgres10:
+    image: alpine:3.8
+    links:
+      - postgres10
+      - chrome
+      - web
+    networks:
+      - test
+    command: >
+      /bin/sh -c "
+        echo Waiting for db start...;
+        while ! nc -z postgres10 5432;
+        do
+          sleep 1;
+        done;
+        echo Connected!;
+      "
+
+  start_dependencies_acceptance_install_sqlite:
+    image: alpine:3.8
+    links:
+      - chrome
+      - web
+    command: >
+      /bin/sh -c "
+        sleep 1;
+      "
+
+  start_dependencies_functional_mariadb10:
+    image: alpine:3.8
+    links:
+      - mariadb10
+      - redis4
+      - memcached1-5
+    networks:
+      - test
+    command: >
+      /bin/sh -c "
+        echo Waiting for db start...;
+        while ! nc -z mariadb10 3306;
+        do
+          sleep 1;
+        done;
+        echo Connected!;
+      "
+
+  start_dependencies_functional_postgres10:
+    image: alpine:3.8
+    links:
+      - postgres10
+      - redis4
+      - memcached1-5
+    networks:
+      - test
+    command: >
+      /bin/sh -c "
+        echo Waiting for db start...;
+        while ! nc -z postgres10 5432;
+        do
+          sleep 1;
+        done;
+        echo Connected!;
+      "
+  start_dependencies_functional_sqlite:
+    image: alpine:3.8
+    links:
+      - redis4
+      - memcached1-5
+    networks:
+      - test
+    command: >
+      /bin/sh -c "
+        sleep 1;
+      "
+
+  start_dependencies_unit:
+    image: alpine:3.8
+    links:
+      - redis4
+    command: >
+      /bin/sh -c "
+        sleep 1;
+      "
+
+networks:
+  test:
+    external:
+      name: ${BAMBOO_COMPOSE_PROJECT_NAME}_test
+
+volumes:
+  bamboo-data:
+    external:
+      name: ${BAMBOO_COMPOSE_PROJECT_NAME}_bamboo-data
\ No newline at end of file
index 4938972..ceefe0f 100644 (file)
@@ -2,7 +2,7 @@ actor: InstallTester
 modules:
   enabled:
     - WebDriver:
-        url: http://master:8000/typo3temp/var/tests/acceptance
+        url: http://web:8000/typo3temp/var/tests/acceptance
         browser: chrome
         wait: 1
         host: chrome
index 526cfd1..f5fb1b1 100644 (file)
@@ -41,6 +41,7 @@ class BlankPageCest
         $I->waitForText('Select database');
         $I->fillField('#t3-install-step-mysqliManualConfiguration-username', $scenario->current('typo3InstallMysqlDatabaseUsername'));
         $I->fillField('#t3-install-step-mysqliManualConfiguration-password', $scenario->current('typo3InstallMysqlDatabasePassword'));
+        $I->fillField('#t3-install-step-mysqliManualConfiguration-host', $scenario->current('typo3InstallMysqlDatabaseHost'));
         $I->click('Continue');
 
         // DatabaseSelect step
index 5eb83e4..d02f216 100644 (file)
@@ -41,6 +41,7 @@ class IntroductionPackageCest
         $I->waitForText('Select database');
         $I->fillField('#t3-install-step-mysqliManualConfiguration-username', $scenario->current('typo3InstallMysqlDatabaseUsername'));
         $I->fillField('#t3-install-step-mysqliManualConfiguration-password', $scenario->current('typo3InstallMysqlDatabasePassword'));
+        $I->fillField('#t3-install-step-mysqliManualConfiguration-host', $scenario->current('typo3InstallMysqlDatabaseHost'));
         $I->click('Continue');
 
         // DatabaseSelect step
index 44a0fb6..af12934 100644 (file)
@@ -42,8 +42,9 @@ class BlankPageCest
         $I->waitForText('Select database');
         $I->selectOption('#t3js-connect-database-driver', 'Manually configured PostgreSQL connection');
         $I->fillField('#t3-install-step-postgresManualConfiguration-username', $scenario->current('typo3InstallPostgresqlDatabaseUsername'));
-        // password intentionally not filled. Postgres authenticates with the shell user.
+        $I->fillField('#t3-install-step-postgresManualConfiguration-password', $scenario->current('typo3InstallPostgresqlDatabasePassword'));
         $I->fillField('#t3-install-step-postgresManualConfiguration-database', $scenario->current('typo3InstallPostgresqlDatabaseName'));
+        $I->fillField('#t3-install-step-postgresManualConfiguration-host', $scenario->current('typo3InstallPostgresqlDatabaseHost'));
         $I->click('Continue');
 
         // DatabaseData step
index c7d0983..5a936ba 100644 (file)
@@ -42,8 +42,9 @@ class IntroductionPackageCest
         $I->waitForText('Select database');
         $I->selectOption('#t3js-connect-database-driver', 'Manually configured PostgreSQL connection');
         $I->fillField('#t3-install-step-postgresManualConfiguration-username', $scenario->current('typo3InstallPostgresqlDatabaseUsername'));
-        // password intentionally not filled. Postgres authenticates with the shell user.
+        $I->fillField('#t3-install-step-postgresManualConfiguration-password', $scenario->current('typo3InstallPostgresqlDatabasePassword'));
         $I->fillField('#t3-install-step-postgresManualConfiguration-database', $scenario->current('typo3InstallPostgresqlDatabaseName'));
+        $I->fillField('#t3-install-step-postgresManualConfiguration-host', $scenario->current('typo3InstallPostgresqlDatabaseHost'));
         $I->click('Continue');
 
         // DatabaseData step
index ef4823b..5ee450e 100644 (file)
@@ -24,7 +24,6 @@ use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
  */
 class MemcachedBackendTest extends FunctionalTestCase
 {
-
     /**
      * Sets up this test case
      */
@@ -34,13 +33,28 @@ class MemcachedBackendTest extends FunctionalTestCase
         if (!extension_loaded('memcache') && !extension_loaded('memcached')) {
             $this->markTestSkipped('Neither "memcache" nor "memcached" extension was available');
         }
-        try {
-            if (!@fsockopen('localhost', 11211)) {
-                $this->markTestSkipped('memcached not reachable');
-            }
-        } catch (\Exception $e) {
-            $this->markTestSkipped('memcached not reachable');
+        if (!getenv('typo3TestingMemcachedHost')) {
+            $this->markTestSkipped('environment variable "typo3TestingMemcachedHost" must be set to run this test');
         }
+        // Note we assume that if that typo3TestingMemcachedHost env is set, we can use that for testing,
+        // there is no test to see if the daemon is actually up and running. Tests will fail if env
+        // is set but daemon is down.
+    }
+
+    /**
+     * Initialize MemcacheBackend ($subject)
+     */
+    protected function initializeSubject(): MemcachedBackend
+    {
+        // We know this env is set, otherwise setUp() would skip the tests
+        $memcachedHost = getenv('typo3TestingMemcachedHost');
+        // If typo3TestingMemcachedPort env is set, use it, otherwise fall back to standard port
+        $env = getenv('typo3TestingMemcachedPort');
+        $memcachedPort = is_string($env) ? (int)$env : 11211;
+
+        $subject = new MemcachedBackend('Testing', [ 'servers' => [$memcachedHost . ':' . $memcachedPort] ]);
+        $subject->initializeObject();
+        return $subject;
     }
 
     /**
@@ -48,8 +62,7 @@ class MemcachedBackendTest extends FunctionalTestCase
      */
     public function setThrowsExceptionIfNoFrontEndHasBeenSet()
     {
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
 
         $this->expectException(Exception::class);
         $this->expectExceptionCode(1207149215);
@@ -76,8 +89,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $identifier = $this->getUniqueId('MyIdentifier');
@@ -93,8 +105,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'Some data';
@@ -111,8 +122,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = [
@@ -141,8 +151,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = str_repeat('abcde', 1024 * 1024);
@@ -159,8 +168,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'Some data';
@@ -178,8 +186,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'Some data';
@@ -198,8 +205,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'Some data';
@@ -219,8 +225,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'Some data';
@@ -238,8 +243,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $identifier = $this->getUniqueId('NonExistingIdentifier');
@@ -254,8 +258,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $identifier = $this->getUniqueId('NonExistingIdentifier');
@@ -270,8 +273,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'some data' . microtime();
@@ -292,8 +294,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'some data' . microtime();
@@ -314,8 +315,7 @@ class MemcachedBackendTest extends FunctionalTestCase
         $frontendProphecy = $this->prophesize(FrontendInterface::class);
         $frontendProphecy->getIdentifier()->willReturn('cache_pages');
 
-        $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $subject->initializeObject();
+        $subject = $this->initializeSubject();
         $subject->setCache($frontendProphecy->reveal());
 
         $data = 'some data' . microtime();
@@ -335,14 +335,12 @@ class MemcachedBackendTest extends FunctionalTestCase
     {
         $thisFrontendProphecy = $this->prophesize(FrontendInterface::class);
         $thisFrontendProphecy->getIdentifier()->willReturn('thisCache');
-        $thisBackend = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $thisBackend->initializeObject();
+        $thisBackend = $this->initializeSubject();
         $thisBackend->setCache($thisFrontendProphecy->reveal());
 
         $thatFrontendProphecy = $this->prophesize(FrontendInterface::class);
         $thatFrontendProphecy->getIdentifier()->willReturn('thatCache');
-        $thatBackend = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
-        $thatBackend->initializeObject();
+        $thatBackend = $this->initializeSubject();
         $thatBackend->setCache($thatFrontendProphecy->reveal());
 
         $thisBackend->set('thisEntry', 'Hello');
index 76a8bc3..77525ac 100644 (file)
@@ -51,15 +51,21 @@ class RedisSessionBackendTest extends FunctionalTestCase
         if (!extension_loaded('redis')) {
             $this->markTestSkipped('redis extension was not available');
         }
-        try {
-            if (!@fsockopen('127.0.0.1', 6379)) {
-                $this->markTestSkipped('redis server not reachable');
-            }
-        } catch (\Exception $e) {
-            $this->markTestSkipped('redis server not reachable');
+        if (!getenv('typo3TestingRedisHost')) {
+            $this->markTestSkipped('environment variable "typo3TestingRedisHost" must be set to run this test');
         }
+        // Note we assume that if that typo3TestingRedisHost env is set, we can use that for testing,
+        // there is no test to see if the daemon is actually up and running. Tests will fail if env
+        // is set but daemon is down.
+
+        // We know this env is set, otherwise setUp() would skip the tests
+        $redisHost = getenv('typo3TestingRedisHost');
+        // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
+        $env = getenv('typo3TestingRedisPort');
+        $redisPort = is_string($env) ? (int)$env : 6379;
+
         $redis = new \Redis();
-        $redis->connect('127.0.0.1');
+        $redis->connect($redisHost, $redisPort);
         $redis->select(0);
         // Clear db to ensure no sessions exist currently
         $redis->flushDB();
@@ -69,8 +75,8 @@ class RedisSessionBackendTest extends FunctionalTestCase
             'default',
             [
                 'database' => 0,
-                'port' => 6379,
-                'hostname' => 'localhost',
+                'port' => $redisPort,
+                'hostname' => $redisHost
             ]
         );
     }
index 92bf2f5..523fbee 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Core\Tests\Unit\Cache\Backend;
  * The TYPO3 project - inspiring people to share!
  */
 use TYPO3\CMS\Core\Cache\Exception\InvalidDataException;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
  * Testcase for the cache to redis backend
@@ -26,9 +27,10 @@ use TYPO3\CMS\Core\Cache\Exception\InvalidDataException;
  * to the internal data structure are done.
  *
  * Warning:
- * The unit tests use and flush redis database numbers 0 and 1!
+ * The unit tests use and flush redis database numbers 0 and 1 on the
+ * redis host specified by environment variable typo3RedisHost
  */
-class RedisBackendTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+class RedisBackendTest extends UnitTestCase
 {
     /**
      * If set, the tearDown() method will flush the cache used by this unit test.
@@ -40,7 +42,7 @@ class RedisBackendTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
     /**
      * Own redis instance used in implementation tests
      *
-     * @var Redis
+     * @var \Redis
      */
     protected $redis;
 
@@ -52,13 +54,12 @@ class RedisBackendTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
         if (!extension_loaded('redis')) {
             $this->markTestSkipped('redis extension was not available');
         }
-        try {
-            if (!@fsockopen('127.0.0.1', 6379)) {
-                $this->markTestSkipped('redis server not reachable');
-            }
-        } catch (\Exception $e) {
-            $this->markTestSkipped('redis server not reachable');
+        if (!getenv('typo3TestingRedisHost')) {
+            $this->markTestSkipped('environment variable "typo3TestingRedisHost" must be set to run this test');
         }
+        // Note we assume that if that typo3TestingRedisHost env is set, we can use that for testing,
+        // there is no test to see if the daemon is actually up and running. Tests will fail if env
+        // is set but daemon is down.
     }
 
     /**
@@ -68,6 +69,11 @@ class RedisBackendTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
     {
         $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class);
         $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('TestCache'));
+        // We know this env is set, otherwise setUp() would skip the tests
+        $backendOptions['hostname'] = getenv('typo3TestingRedisHost');
+        // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
+        $env = getenv('typo3TestingRedisPort');
+        $backendOptions['port'] = is_string($env) ? (int)$env : 6379;
         $this->backend = new \TYPO3\CMS\Core\Cache\Backend\RedisBackend('Testing', $backendOptions);
         $this->backend->setCache($mockCache);
         $this->backend->initializeObject();
@@ -78,8 +84,14 @@ class RedisBackendTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
      */
     protected function setUpRedis()
     {
+        // We know this env is set, otherwise setUp() would skip the tests
+        $redisHost = getenv('typo3TestingRedisHost');
+        // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
+        $env = getenv('typo3TestingRedisPort');
+        $redisPort = is_string($env) ? (int)$env : 6379;
+
         $this->redis = new \Redis();
-        $this->redis->connect('127.0.0.1', 6379);
+        $this->redis->connect($redisHost, $redisPort);
     }
 
     /**