[TASK] bamboo plan for security pre-merge tests 48/60648/3
authorChristian Kuhn <lolli@schwarzbu.ch>
Tue, 30 Apr 2019 10:37:39 +0000 (12:37 +0200)
committerSusanne Moog <look@susi.dev>
Mon, 6 May 2019 10:49:58 +0000 (12:49 +0200)
Change-Id: Ic1e1d0f8fd1a128e542e7cada389d681ac41e10f
Resolves: #88265
Releases: master, 9.5, 8.7
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/60648
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Susanne Moog <look@susi.dev>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Susanne Moog <look@susi.dev>
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/bamboo/src/main/java/core/SecuritySpec.java [new file with mode: 0644]
Build/bamboo/src/test/java/core/SecuritySpecTest.java [new file with mode: 0644]

index b2534a3..a103531 100644 (file)
@@ -59,11 +59,25 @@ abstract public class AbstractCoreSpec {
     protected PlanPermissions getDefaultPlanPermissions(String projectKey, String planKey) {
         return new PlanPermissions(new PlanIdentifier(projectKey, planKey))
             .permissions(new Permissions()
-            .groupPermissions("TYPO3 GmbH", PermissionType.ADMIN, PermissionType.VIEW, PermissionType.EDIT, PermissionType.BUILD, PermissionType.CLONE)
-            .groupPermissions("TYPO3 Core Team", PermissionType.VIEW, PermissionType.BUILD)
-            .loggedInUserPermissions(PermissionType.VIEW)
-            .anonymousUserPermissionView()
-        );
+                .groupPermissions("TYPO3 GmbH", PermissionType.ADMIN, PermissionType.VIEW, PermissionType.EDIT, PermissionType.BUILD, PermissionType.CLONE)
+                .groupPermissions("TYPO3 Core Team", PermissionType.VIEW, PermissionType.BUILD)
+                .loggedInUserPermissions(PermissionType.VIEW)
+                .anonymousUserPermissionView()
+            );
+    }
+
+    /**
+     * Default permissions on core security plans
+     *
+     * @param projectName
+     * @param planName
+     * @return
+     */
+    protected PlanPermissions getSecurityPlanPermissions(String projectKey, String planKey) {
+        return new PlanPermissions(new PlanIdentifier(projectKey, planKey))
+            .permissions(new Permissions()
+                .groupPermissions("TYPO3 GmbH", PermissionType.ADMIN, PermissionType.VIEW, PermissionType.EDIT, PermissionType.BUILD, PermissionType.CLONE)
+            );
     }
 
     /**
@@ -162,14 +176,15 @@ abstract public class AbstractCoreSpec {
      * Job composer validate
      *
      * @param String requirementIdentifier
+     * @param Boolean isSecurity
      */
-    protected Job getJobComposerValidate(String requirementIdentifier) {
+    protected Job getJobComposerValidate(String requirementIdentifier, Boolean isSecurity) {
         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(),
+            this.getTaskGitCherryPick(isSecurity),
             this.getTaskStopDanglingContainers(),
             new ScriptTask()
                 .description("composer validate")
@@ -192,14 +207,15 @@ abstract public class AbstractCoreSpec {
      * Job checking CGL of last git commit
      *
      * @param String requirementIdentifier
+     * @param Boolean isSecurity
      */
-    protected Job getJobCglCheckGitCommit(String requirementIdentifier) {
+    protected Job getJobCglCheckGitCommit(String requirementIdentifier, Boolean isSecurity) {
         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.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 this.getTaskComposerInstall(requirementIdentifier),
                 new ScriptTask()
@@ -233,14 +249,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobCglCheckFullCore(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobCglCheckFullCore(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Integration CGL " + stageNumber, new BambooKey("CGLCHECK" + stageNumber))
             .description("Check coding guidelines of full core")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 composerTask,
                 new ScriptTask()
@@ -275,14 +292,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobAcceptanceTestInstallMysql(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobAcceptanceTestInstallMysql(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Accept inst my " + stageNumber + " " + requirementIdentifier, new BambooKey("ACINSTMY" +stageNumber + requirementIdentifier))
             .description("Install TYPO3 on mariadb and load introduction package " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 composerTask,
                 this.getTaskPrepareAcceptanceTest(),
@@ -333,14 +351,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobAcceptanceTestInstallPgsql(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobAcceptanceTestInstallPgsql(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Accept inst pg " + stageNumber + " " + requirementIdentifier, new BambooKey("ACINSTPG" + stageNumber + requirementIdentifier))
         .description("Install TYPO3 on pgsql and load introduction package " + requirementIdentifier)
         .pluginConfigurations(this.getDefaultJobPluginConfiguration())
         .tasks(
             this.getTaskGitCloneRepository(),
-            this.getTaskGitCherryPick(),
+            this.getTaskGitCherryPick(isSecurity),
             this.getTaskStopDanglingContainers(),
             composerTask,
             this.getTaskPrepareAcceptanceTest(),
@@ -391,14 +410,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobAcceptanceTestInstallSqlite(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobAcceptanceTestInstallSqlite(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Accept inst sq " + stageNumber + " " + requirementIdentifier, new BambooKey("ACINSTSQ" + stageNumber + requirementIdentifier))
         .description("Install TYPO3 on sqlite and load introduction package " + requirementIdentifier)
         .pluginConfigurations(this.getDefaultJobPluginConfiguration())
         .tasks(
             this.getTaskGitCloneRepository(),
-            this.getTaskGitCherryPick(),
+            this.getTaskGitCherryPick(isSecurity),
             this.getTaskStopDanglingContainers(),
             composerTask,
             this.getTaskPrepareAcceptanceTest(),
@@ -446,8 +466,9 @@ abstract public class AbstractCoreSpec {
      * @param int numberOfChunks
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected ArrayList<Job> getJobsAcceptanceTestsBackendMysql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask) {
+    protected ArrayList<Job> getJobsAcceptanceTestsBackendMysql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -460,7 +481,7 @@ abstract public class AbstractCoreSpec {
                 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
                 .tasks(
                     this.getTaskGitCloneRepository(),
-                    this.getTaskGitCherryPick(),
+                    this.getTaskGitCherryPick(isSecurity),
                     this.getTaskStopDanglingContainers(),
                     composerTask,
                     this.getTaskPrepareAcceptanceTest(),
@@ -534,8 +555,9 @@ abstract public class AbstractCoreSpec {
      * @param int numberOfChunks
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected ArrayList<Job> getJobsFunctionalTestsMysql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask) {
+    protected ArrayList<Job> getJobsFunctionalTestsMysql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -548,7 +570,7 @@ abstract public class AbstractCoreSpec {
                 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
                 .tasks(
                     this.getTaskGitCloneRepository(),
-                    this.getTaskGitCherryPick(),
+                    this.getTaskGitCherryPick(isSecurity),
                     this.getTaskStopDanglingContainers(),
                     composerTask,
                     this.getTaskDockerDependenciesFunctionalMariadb10(),
@@ -601,8 +623,9 @@ abstract public class AbstractCoreSpec {
      * @param int numberOfChunks
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected ArrayList<Job> getJobsFunctionalTestsMssql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask) {
+    protected ArrayList<Job> getJobsFunctionalTestsMssql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -615,7 +638,7 @@ abstract public class AbstractCoreSpec {
                 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
                 .tasks(
                     this.getTaskGitCloneRepository(),
-                    this.getTaskGitCherryPick(),
+                    this.getTaskGitCherryPick(isSecurity),
                     this.getTaskStopDanglingContainers(),
                     composerTask,
                     this.getTaskDockerDependenciesFunctionalMssql(),
@@ -672,8 +695,9 @@ abstract public class AbstractCoreSpec {
      * @param int numberOfChunks
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected ArrayList<Job> getJobsFunctionalTestsPgsql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask) {
+    protected ArrayList<Job> getJobsFunctionalTestsPgsql(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -686,7 +710,7 @@ abstract public class AbstractCoreSpec {
                 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
                 .tasks(
                     this.getTaskGitCloneRepository(),
-                    this.getTaskGitCherryPick(),
+                    this.getTaskGitCherryPick(isSecurity),
                     this.getTaskStopDanglingContainers(),
                     composerTask,
                     this.getTaskDockerDependenciesFunctionalPostgres10(),
@@ -740,8 +764,9 @@ abstract public class AbstractCoreSpec {
      * @param int numberOfChunks
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected ArrayList<Job> getJobsFunctionalTestsSqlite(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask) {
+    protected ArrayList<Job> getJobsFunctionalTestsSqlite(int stageNumber, int numberOfChunks, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfChunks; i++) {
@@ -754,7 +779,7 @@ abstract public class AbstractCoreSpec {
                 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
                 .tasks(
                     this.getTaskGitCloneRepository(),
-                    this.getTaskGitCherryPick(),
+                    this.getTaskGitCherryPick(isSecurity),
                     this.getTaskStopDanglingContainers(),
                     composerTask,
                     this.getTaskSplitFunctionalJobs(numberOfChunks, requirementIdentifier),
@@ -803,14 +828,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobIntegrationAnnotations(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobIntegrationAnnotations(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Integration annotations " + stageNumber, new BambooKey("IANNO" + stageNumber))
             .description("Check docblock-annotations by executing Build/Scripts/annotationChecker.php script")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 composerTask,
                 new ScriptTask()
@@ -844,15 +870,16 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobIntegrationVarious(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobIntegrationVarious(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         // Exception code checker, xlf, permissions, rst file check
         return new Job("Integration various " + stageNumber, new BambooKey("CDECC" + stageNumber))
             .description("Checks duplicate exceptions, git submodules, xlf files, permissions, rst")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 composerTask,
                 new ScriptTask()
@@ -996,14 +1023,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobUnitJavaScript(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobUnitJavaScript(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Unit JavaScript " + stageNumber, new BambooKey("JSUT" + stageNumber))
             .description("Run JavaScript unit tests")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 composerTask,
                 new ScriptTask()
@@ -1066,14 +1094,15 @@ abstract public class AbstractCoreSpec {
      * Job for PHP lint
      *
      * @param String requirementIdentifier
+     * @param Boolean isSecurity
      */
-    protected Job getJobLintPhp(String requirementIdentifier) {
+    protected Job getJobLintPhp(String requirementIdentifier, Boolean isSecurity) {
         return new Job("Lint " + requirementIdentifier, new BambooKey("L" + requirementIdentifier))
             .description("Run php -l on source files for linting " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 new ScriptTask()
                     .description("Run php lint")
@@ -1105,14 +1134,15 @@ abstract public class AbstractCoreSpec {
      * Job for lint npm scss and typescript
      *
      * @param String requirementIdentifier
+     * @param Boolean isSecurity
      */
-    protected Job getJobLintScssTs(String requirementIdentifier) {
+    protected Job getJobLintScssTs(String requirementIdentifier, Boolean isSecurity) {
         return new Job("Lint scss ts", new BambooKey("LSTS"))
             .description("Lint scss and ts, build css and js, test git is clean")
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 new ScriptTask()
                     .description("yarn install in Build/ dir")
@@ -1210,14 +1240,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobUnitPhp(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobUnitPhp(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Unit " + stageNumber + " " + requirementIdentifier, new BambooKey("UT" + stageNumber + requirementIdentifier))
             .description("Run unit tests " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 composerTask,
                 new ScriptTask()
@@ -1256,14 +1287,15 @@ abstract public class AbstractCoreSpec {
      * @param int stageNumber
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected Job getJobUnitDeprecatedPhp(int stageNumber, String requirementIdentifier, Task composerTask) {
+    protected Job getJobUnitDeprecatedPhp(int stageNumber, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         return new Job("Unit deprecated " + stageNumber + " " + requirementIdentifier, new BambooKey("UTD" + stageNumber + requirementIdentifier))
             .description("Run deprecated unit tests " + requirementIdentifier)
             .pluginConfigurations(this.getDefaultJobPluginConfiguration())
             .tasks(
                 this.getTaskGitCloneRepository(),
-                this.getTaskGitCherryPick(),
+                this.getTaskGitCherryPick(isSecurity),
                 this.getTaskStopDanglingContainers(),
                 composerTask,
                 new ScriptTask()
@@ -1303,8 +1335,9 @@ abstract public class AbstractCoreSpec {
      * @param int numberOfRuns
      * @param String requirementIdentifier
      * @param Task composerTask
+     * @param Boolean isSecurity
      */
-    protected ArrayList<Job> getJobUnitPhpRandom(int stageNumber, int numberOfRuns, String requirementIdentifier, Task composerTask) {
+    protected ArrayList<Job> getJobUnitPhpRandom(int stageNumber, int numberOfRuns, String requirementIdentifier, Task composerTask, Boolean isSecurity) {
         ArrayList<Job> jobs = new ArrayList<Job>();
 
         for (int i=1; i<=numberOfRuns; i++) {
@@ -1313,7 +1346,7 @@ abstract public class AbstractCoreSpec {
                 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
                 .tasks(
                     this.getTaskGitCloneRepository(),
-                    this.getTaskGitCherryPick(),
+                    this.getTaskGitCherryPick(isSecurity),
                     this.getTaskStopDanglingContainers(),
                     composerTask,
                     new ScriptTask()
@@ -1361,21 +1394,39 @@ abstract public class AbstractCoreSpec {
 
     /**
      * Task definition to cherry pick a patch set from gerrit on top of cloned core
+     *
+     * @param Boolean isSecurity
      */
-    protected Task getTaskGitCherryPick() {
-        return new ScriptTask()
-            .description("Gerrit cherry pick")
-            .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
-            .inlineBody(
-                this.getScriptTaskBashInlineBody() +
-                "CHANGEURL=${bamboo.changeUrl}\n" +
-                "CHANGEURLID=${CHANGEURL#https://review.typo3.org/}\n" +
-                "PATCHSET=${bamboo.patchset}\n" +
-                "\n" +
-                "if [[ $CHANGEURL ]]; then\n" +
-                "    gerrit-cherry-pick https://review.typo3.org/Packages/TYPO3.CMS $CHANGEURLID/$PATCHSET || exit 1\n" +
-                "fi\n"
-            );
+    protected Task getTaskGitCherryPick(Boolean isSecurity) {
+        if (isSecurity) {
+            return new ScriptTask()
+                .description("Gerrit cherry pick")
+                .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                .inlineBody(
+                    this.getScriptTaskBashInlineBody() +
+                    "CHANGEURL=${bamboo.changeUrl}\n" +
+                    "CHANGEURLID=${CHANGEURL#https://review.typo3.org/}\n" +
+                    "PATCHSET=${bamboo.patchset}\n" +
+                    "\n" +
+                    "if [[ $CHANGEURL ]]; then\n" +
+                    "    gerrit-cherry-pick https://review.typo3.org/Teams/Security/TYPO3v4-Core $CHANGEURLID/$PATCHSET || exit 1\n" +
+                    "fi\n"
+                );
+        } else {
+            return new ScriptTask()
+                .description("Gerrit cherry pick")
+                .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
+                .inlineBody(
+                    this.getScriptTaskBashInlineBody() +
+                    "CHANGEURL=${bamboo.changeUrl}\n" +
+                    "CHANGEURLID=${CHANGEURL#https://review.typo3.org/}\n" +
+                    "PATCHSET=${bamboo.patchset}\n" +
+                    "\n" +
+                    "if [[ $CHANGEURL ]]; then\n" +
+                    "    gerrit-cherry-pick https://review.typo3.org/Packages/TYPO3.CMS $CHANGEURLID/$PATCHSET || exit 1\n" +
+                    "fi\n"
+                );
+        }
     }
 
     /**
index e190dd5..49231fd 100644 (file)
@@ -80,47 +80,47 @@ public class NightlySpec extends AbstractCoreSpec {
         // MAIN stage
         ArrayList<Job> jobsMainStage = new ArrayList<Job>();
 
-        jobsMainStage.add(this.getJobComposerValidate("PHP72"));
+        jobsMainStage.add(this.getJobComposerValidate("PHP72", false));
 
-        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(0, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(0, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(0, "PHP73", this.getTaskComposerInstall("PHP73")));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
 
-        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(0, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(0, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
+        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(0, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(0, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
 
-        jobsMainStage.add(this.getJobCglCheckFullCore(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobCglCheckFullCore(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.add(this.getJobIntegrationAnnotations(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobIntegrationAnnotations(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.add(this.getJobIntegrationVarious(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobIntegrationVarious(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(0, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(0, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(0, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(0, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(0, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(0, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
         // no mssql with php 7.3 yet
-        // jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(0, this.numberOfFunctionalMssqlJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(0, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(0, this.numberOfFunctionalPgsqlJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(0, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(0, this.numberOfFunctionalSqliteJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
+        // jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(0, this.numberOfFunctionalMssqlJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(0, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(0, this.numberOfFunctionalPgsqlJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(0, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(0, this.numberOfFunctionalSqliteJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
 
-        jobsMainStage.add(this.getJobUnitJavaScript(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobUnitJavaScript(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.add(this.getJobLintPhp("PHP72"));
-        jobsMainStage.add(this.getJobLintPhp("PHP73"));
+        jobsMainStage.add(this.getJobLintPhp("PHP72", false));
+        jobsMainStage.add(this.getJobLintPhp("PHP73", false));
 
-        jobsMainStage.add(this.getJobLintScssTs("PHP72"));
+        jobsMainStage.add(this.getJobLintScssTs("PHP72", false));
 
-        jobsMainStage.add(this.getJobUnitPhp(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobUnitPhp(0, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
+        jobsMainStage.add(this.getJobUnitPhp(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobUnitPhp(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
 
         Stage stageMainStage = new Stage("Main stage")
             .jobs(jobsMainStage.toArray(new Job[jobsMainStage.size()]));
@@ -129,42 +129,42 @@ public class NightlySpec extends AbstractCoreSpec {
         // COMPOSER UPDATE MAX stage
         ArrayList<Job> jobsComposerMaxStage = new ArrayList<Job>();
 
-        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallMysql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallMysql(1, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
-        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallPgsql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallPgsql(1, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
-        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallSqlite(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallSqlite(1, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallMysql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallMysql(1, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallPgsql(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallPgsql(1, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallSqlite(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.add(this.getJobAcceptanceTestInstallSqlite(1, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
 
-        jobsComposerMaxStage.addAll(this.getJobsAcceptanceTestsBackendMysql(1, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.addAll(this.getJobsAcceptanceTestsBackendMysql(1, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
+        jobsComposerMaxStage.addAll(this.getJobsAcceptanceTestsBackendMysql(1, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.addAll(this.getJobsAcceptanceTestsBackendMysql(1, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
 
-        jobsComposerMaxStage.add(this.getJobCglCheckFullCore(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobCglCheckFullCore(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
 
-        jobsComposerMaxStage.add(this.getJobIntegrationAnnotations(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobIntegrationAnnotations(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
 
-        jobsComposerMaxStage.add(this.getJobIntegrationVarious(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobIntegrationVarious(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
 
-        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMysql(1, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMysql(1, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
-        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMssql(1, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMysql(1, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMysql(1, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMssql(1, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
         // no mssql with php 7.3 yet
-        // jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMssql(1, this.numberOfFunctionalMssqlJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
-        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsPgsql(1, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsPgsql(1, this.numberOfFunctionalPgsqlJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
-        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsSqlite(1, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsSqlite(1, this.numberOfFunctionalSqliteJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
+        // jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsMssql(1, this.numberOfFunctionalMssqlJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsPgsql(1, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsPgsql(1, this.numberOfFunctionalPgsqlJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsSqlite(1, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.addAll(this.getJobsFunctionalTestsSqlite(1, this.numberOfFunctionalSqliteJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
 
-        jobsComposerMaxStage.add(this.getJobUnitJavaScript(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
+        jobsComposerMaxStage.add(this.getJobUnitJavaScript(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
 
-        jobsComposerMaxStage.add(this.getJobUnitPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.add(this.getJobUnitPhp(1, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
-        jobsComposerMaxStage.add(this.getJobUnitDeprecatedPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.add(this.getJobUnitDeprecatedPhp(1, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
+        jobsComposerMaxStage.add(this.getJobUnitPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.add(this.getJobUnitPhp(1, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
+        jobsComposerMaxStage.add(this.getJobUnitDeprecatedPhp(1, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.add(this.getJobUnitDeprecatedPhp(1, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
 
         // Disabled for now since young phpunit with built-in randomizer collides with this one. Needs investigation.
-        jobsComposerMaxStage.addAll(this.getJobUnitPhpRandom(1, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72")));
-        jobsComposerMaxStage.addAll(this.getJobUnitPhpRandom(1, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73")));
+        jobsComposerMaxStage.addAll(this.getJobUnitPhpRandom(1, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerUpdateMax("PHP72"), false));
+        jobsComposerMaxStage.addAll(this.getJobUnitPhpRandom(1, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerUpdateMax("PHP73"), false));
 
         Stage stageComposerMaxStage = new Stage("Composer update max")
             .jobs(jobsComposerMaxStage.toArray(new Job[jobsComposerMaxStage.size()]));
@@ -172,40 +172,40 @@ public class NightlySpec extends AbstractCoreSpec {
         // COMPOSER UPDATE MIN stage
         ArrayList<Job> jobsComposerMinStage = new ArrayList<Job>();
 
-        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallMysql(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallMysql(2, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallPgsql(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallPgsql(2, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallSqlite(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallSqlite(2, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallMysql(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallMysql(2, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallPgsql(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallPgsql(2, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallSqlite(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.add(this.getJobAcceptanceTestInstallSqlite(2, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
 
-        jobsComposerMinStage.addAll(this.getJobsAcceptanceTestsBackendMysql(2, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.addAll(this.getJobsAcceptanceTestsBackendMysql(2, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
+        jobsComposerMinStage.addAll(this.getJobsAcceptanceTestsBackendMysql(2, this.numberOfAcceptanceTestJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.addAll(this.getJobsAcceptanceTestsBackendMysql(2, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
 
-        jobsComposerMinStage.add(this.getJobCglCheckFullCore(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.add(this.getJobCglCheckFullCore(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
 
-        jobsComposerMinStage.add(this.getJobIntegrationAnnotations(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.add(this.getJobIntegrationAnnotations(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
 
-        jobsComposerMinStage.add(this.getJobIntegrationVarious(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.add(this.getJobIntegrationVarious(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
 
-        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMysql(2, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMysql(2, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMssql(2, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMysql(2, this.numberOfFunctionalMysqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMysql(2, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMssql(2, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
         // no mssql with php 7.3 yet
-        // jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMssql(2, this.numberOfFunctionalMssqlJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsPgsql(2, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsPgsql(2, this.numberOfFunctionalPgsqlJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsSqlite(2, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsSqlite(2, this.numberOfFunctionalSqliteJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-
-        jobsComposerMinStage.add(this.getJobUnitJavaScript(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-
-        jobsComposerMinStage.add(this.getJobUnitPhp(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.add(this.getJobUnitPhp(2, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-        jobsComposerMinStage.add(this.getJobUnitDeprecatedPhp(2, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.add(this.getJobUnitDeprecatedPhp(2, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
-        jobsComposerMinStage.addAll(this.getJobUnitPhpRandom(2, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72")));
-        jobsComposerMinStage.addAll(this.getJobUnitPhpRandom(2, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73")));
+        // jobsComposerMinStage.addAll(this.getJobsFunctionalTestsMssql(2, this.numberOfFunctionalMssqlJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsPgsql(2, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsPgsql(2, this.numberOfFunctionalPgsqlJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsSqlite(2, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.addAll(this.getJobsFunctionalTestsSqlite(2, this.numberOfFunctionalSqliteJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+
+        jobsComposerMinStage.add(this.getJobUnitJavaScript(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+
+        jobsComposerMinStage.add(this.getJobUnitPhp(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.add(this.getJobUnitPhp(2, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+        jobsComposerMinStage.add(this.getJobUnitDeprecatedPhp(2, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.add(this.getJobUnitDeprecatedPhp(2, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
+        jobsComposerMinStage.addAll(this.getJobUnitPhpRandom(2, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerUpdateMin("PHP72"), false));
+        jobsComposerMinStage.addAll(this.getJobUnitPhpRandom(2, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerUpdateMin("PHP73"), false));
 
         Stage stageComposerMinStage = new Stage("Composer update min")
             .jobs(jobsComposerMinStage.toArray(new Job[jobsComposerMinStage.size()]));
index d426f57..3c3190b 100644 (file)
@@ -80,43 +80,43 @@ public class PreMergeSpec extends AbstractCoreSpec {
 
         // EARLY stage
         ArrayList<Job> jobsEarlyStage = new ArrayList<Job>();
-        jobsEarlyStage.add(this.getJobCglCheckGitCommit("PHP72"));
-        jobsEarlyStage.add(this.getJobComposerValidate("PHP72"));
+        jobsEarlyStage.add(this.getJobCglCheckGitCommit("PHP72", false));
+        jobsEarlyStage.add(this.getJobComposerValidate("PHP72", false));
         Stage stageEarly = new Stage("Early")
             .jobs(jobsEarlyStage.toArray(new Job[jobsEarlyStage.size()]));
 
         // MAIN stage
         ArrayList<Job> jobsMainStage = new ArrayList<Job>();
 
-        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(0, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(0, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
+        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(0, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
 
-        jobsMainStage.add(this.getJobIntegrationAnnotations(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobIntegrationAnnotations(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.add(this.getJobIntegrationVarious(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobIntegrationVarious(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(0, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(0, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
         // mssql functionals are not executed as pre-merge
-        // jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(0, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(0, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(0, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
+        // jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(0, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(0, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(0, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.add(this.getJobUnitJavaScript(0, "PHP72", this.getTaskComposerInstall("PHP72")));
+        jobsMainStage.add(this.getJobUnitJavaScript(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
 
-        jobsMainStage.add(this.getJobLintPhp("PHP72"));
-        jobsMainStage.add(this.getJobLintPhp("PHP73"));
+        jobsMainStage.add(this.getJobLintPhp("PHP72", false));
+        jobsMainStage.add(this.getJobLintPhp("PHP73", false));
 
-        jobsMainStage.add(this.getJobLintScssTs("PHP72"));
+        jobsMainStage.add(this.getJobLintScssTs("PHP72", false));
 
-        jobsMainStage.add(this.getJobUnitPhp(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobUnitPhp(0, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP73", this.getTaskComposerInstall("PHP73")));
-        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerInstall("PHP72")));
-        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerInstall("PHP73")));
+        jobsMainStage.add(this.getJobUnitPhp(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobUnitPhp(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP73", this.getTaskComposerInstall("PHP73"), false));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerInstall("PHP72"), false));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerInstall("PHP73"), false));
 
         Stage stageMainStage = new Stage("Main stage")
             .jobs(jobsMainStage.toArray(new Job[jobsMainStage.size()]));
diff --git a/Build/bamboo/src/main/java/core/SecuritySpec.java b/Build/bamboo/src/main/java/core/SecuritySpec.java
new file mode 100644 (file)
index 0000000..53f89f9
--- /dev/null
@@ -0,0 +1,155 @@
+package core;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+import java.util.ArrayList;
+
+import com.atlassian.bamboo.specs.api.BambooSpec;
+import com.atlassian.bamboo.specs.api.builders.AtlassianModule;
+import com.atlassian.bamboo.specs.api.builders.BambooKey;
+import com.atlassian.bamboo.specs.api.builders.Variable;
+import com.atlassian.bamboo.specs.api.builders.notification.AnyNotificationRecipient;
+import com.atlassian.bamboo.specs.api.builders.notification.Notification;
+import com.atlassian.bamboo.specs.api.builders.plan.Job;
+import com.atlassian.bamboo.specs.api.builders.plan.Plan;
+import com.atlassian.bamboo.specs.api.builders.plan.Stage;
+import com.atlassian.bamboo.specs.api.builders.plan.branches.BranchCleanup;
+import com.atlassian.bamboo.specs.api.builders.plan.branches.PlanBranchManagement;
+import com.atlassian.bamboo.specs.api.builders.project.Project;
+import com.atlassian.bamboo.specs.api.builders.requirement.Requirement;
+import com.atlassian.bamboo.specs.builders.notification.PlanCompletedNotification;
+import com.atlassian.bamboo.specs.builders.task.ScriptTask;
+import com.atlassian.bamboo.specs.builders.trigger.RemoteTrigger;
+import com.atlassian.bamboo.specs.builders.trigger.RepositoryPollingTrigger;
+import com.atlassian.bamboo.specs.model.task.ScriptTaskProperties;
+import com.atlassian.bamboo.specs.util.BambooServer;
+
+/**
+ * Core master security test plan.
+ */
+@BambooSpec
+public class SecuritySpec extends AbstractCoreSpec {
+
+    protected static String planName = "Core master security";
+    protected static String planKey = "GTS";
+
+    protected int numberOfAcceptanceTestJobs = 10;
+    protected int numberOfFunctionalMysqlJobs = 10;
+    protected int numberOfFunctionalMssqlJobs = 10;
+    protected int numberOfFunctionalPgsqlJobs = 10;
+    protected int numberOfFunctionalSqliteJobs = 10;
+    protected int numberOfUnitRandomOrderJobs = 1;
+
+    /**
+     * Run main to publish plan on Bamboo
+     */
+    public static void main(final String[] args) throws Exception {
+        // By default credentials are read from the '.credentials' file.
+        BambooServer bambooServer = new BambooServer(bambooServerName);
+        bambooServer.publish(new SecuritySpec().createPlan());
+        bambooServer.publish(new SecuritySpec().getSecurityPlanPermissions(projectKey, planKey));
+    }
+
+    /**
+     * Core master pre-merge plan is in "TYPO3 core" project of bamboo
+     */
+    Project project() {
+        return new Project().name(projectName).key(projectKey);
+    }
+
+    /**
+     * Returns full Plan definition
+     */
+    Plan createPlan() {
+        // PREPARATION stage
+        ArrayList<Job> jobsPreparationStage = new ArrayList<Job>();
+        jobsPreparationStage.add(this.getJobBuildLabels());
+        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", true));
+        jobsEarlyStage.add(this.getJobComposerValidate("PHP72", true));
+        Stage stageEarly = new Stage("Early")
+            .jobs(jobsEarlyStage.toArray(new Job[jobsEarlyStage.size()]));
+
+        // MAIN stage
+        ArrayList<Job> jobsMainStage = new ArrayList<Job>();
+
+        jobsMainStage.add(this.getJobAcceptanceTestInstallMysql(0, "PHP73", this.getTaskComposerInstall("PHP73"), true));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallPgsql(0, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+        jobsMainStage.add(this.getJobAcceptanceTestInstallSqlite(0, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+
+        jobsMainStage.addAll(this.getJobsAcceptanceTestsBackendMysql(0, this.numberOfAcceptanceTestJobs, "PHP73", this.getTaskComposerInstall("PHP73"), true));
+
+        jobsMainStage.add(this.getJobIntegrationAnnotations(0, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+
+        jobsMainStage.add(this.getJobIntegrationVarious(0, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+
+        jobsMainStage.addAll(this.getJobsFunctionalTestsMysql(0, this.numberOfFunctionalMysqlJobs, "PHP73", this.getTaskComposerInstall("PHP73"), true));
+        // mssql functionals are not executed as pre-merge
+        // jobsMainStage.addAll(this.getJobsFunctionalTestsMssql(0, this.numberOfFunctionalMssqlJobs, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsPgsql(0, this.numberOfFunctionalPgsqlJobs, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+        jobsMainStage.addAll(this.getJobsFunctionalTestsSqlite(0, this.numberOfFunctionalSqliteJobs, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+
+        jobsMainStage.add(this.getJobUnitJavaScript(0, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+
+        jobsMainStage.add(this.getJobLintPhp("PHP72", true));
+        jobsMainStage.add(this.getJobLintPhp("PHP73", true));
+
+        jobsMainStage.add(this.getJobLintScssTs("PHP72", true));
+
+        jobsMainStage.add(this.getJobUnitPhp(0, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+        jobsMainStage.add(this.getJobUnitPhp(0, "PHP73", this.getTaskComposerInstall("PHP73"), true));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+        jobsMainStage.add(this.getJobUnitDeprecatedPhp(0, "PHP73", this.getTaskComposerInstall("PHP73"), true));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP72", this.getTaskComposerInstall("PHP72"), true));
+        jobsMainStage.addAll(this.getJobUnitPhpRandom(0, this.numberOfUnitRandomOrderJobs, "PHP73", this.getTaskComposerInstall("PHP73"), true));
+
+        Stage stageMainStage = new Stage("Main stage")
+            .jobs(jobsMainStage.toArray(new Job[jobsMainStage.size()]));
+
+        // Compile plan
+        return new Plan(project(), planName, planKey)
+            .description("Execute TYPO3 core master security tests. Auto generated! See Build/bamboo of core git repository.")
+            .pluginConfigurations(this.getDefaultPlanPluginConfiguration())
+            .stages(
+                stagePreparation,
+                stageEarly,
+                stageMainStage
+            )
+            .linkedRepositories("github TYPO3 TYPO3.CMS")
+            .triggers(
+                new RemoteTrigger()
+                    .name("Remote trigger for security builds")
+                    .description("Gerrit")
+                    .triggerIPAddresses("5.10.165.218,91.184.35.13"))
+            .variables(
+                new Variable("changeUrl", ""),
+                new Variable("patchset", "")
+            )
+            .planBranchManagement(
+                new PlanBranchManagement()
+                    .delete(new BranchCleanup())
+                    .notificationForCommitters()
+            )
+            .notifications(new Notification()
+                .type(new PlanCompletedNotification())
+                .recipients(new AnyNotificationRecipient(new AtlassianModule("com.atlassian.bamboo.plugins.bamboo-slack:recipient.slack"))
+                    .recipientString("https://intercept.typo3.com/bamboo")
+                )
+        );
+    }
+}
diff --git a/Build/bamboo/src/test/java/core/SecuritySpecTest.java b/Build/bamboo/src/test/java/core/SecuritySpecTest.java
new file mode 100644 (file)
index 0000000..588960a
--- /dev/null
@@ -0,0 +1,29 @@
+package core;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+import org.junit.Test;
+
+import com.atlassian.bamboo.specs.api.builders.plan.Plan;
+import com.atlassian.bamboo.specs.api.exceptions.PropertiesValidationException;
+import com.atlassian.bamboo.specs.api.util.EntityPropertiesBuilders;
+
+public class SecuritySpecTest {
+    @Test
+    public void checkYourPlanOffline() throws PropertiesValidationException {
+        Plan plan = new SecuritySpec().createPlan();
+
+        EntityPropertiesBuilders.build(plan);
+    }
+}