7759aa17c29833215a61ee8b191ab4dca70afc13
[Packages/TYPO3.CMS.git] / Build / bamboo / src / main / java / core / AbstractCoreSpec.java
1 package core;
2
3 /*
4 * This file is part of the TYPO3 CMS project.
5 *
6 * It is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License, either version 2
8 * of the License, or any later version.
9 *
10 * For the full copyright and license information, please read the
11 * LICENSE.txt file that was distributed with this source code.
12 *
13 * The TYPO3 project - inspiring people to share!
14 */
15
16 import java.util.ArrayList;
17
18 import com.atlassian.bamboo.specs.api.builders.BambooKey;
19 import com.atlassian.bamboo.specs.api.builders.permission.PermissionType;
20 import com.atlassian.bamboo.specs.api.builders.permission.Permissions;
21 import com.atlassian.bamboo.specs.api.builders.permission.PlanPermissions;
22 import com.atlassian.bamboo.specs.api.builders.plan.Job;
23 import com.atlassian.bamboo.specs.api.builders.plan.PlanIdentifier;
24 import com.atlassian.bamboo.specs.api.builders.plan.artifact.Artifact;
25 import com.atlassian.bamboo.specs.api.builders.plan.configuration.AllOtherPluginsConfiguration;
26 import com.atlassian.bamboo.specs.api.builders.plan.configuration.PluginConfiguration;
27 import com.atlassian.bamboo.specs.api.builders.requirement.Requirement;
28 import com.atlassian.bamboo.specs.api.builders.task.Task;
29 import com.atlassian.bamboo.specs.builders.task.CheckoutItem;
30 import com.atlassian.bamboo.specs.builders.task.CommandTask;
31 import com.atlassian.bamboo.specs.builders.task.NpmTask;
32 import com.atlassian.bamboo.specs.builders.task.ScriptTask;
33 import com.atlassian.bamboo.specs.builders.task.TestParserTask;
34 import com.atlassian.bamboo.specs.builders.task.VcsCheckoutTask;
35 import com.atlassian.bamboo.specs.model.task.ScriptTaskProperties;
36 import com.atlassian.bamboo.specs.model.task.TestParserTaskProperties;
37 import com.atlassian.bamboo.specs.util.MapBuilder;
38
39 /**
40 * Abstract class with common methods of pre-merge and nightly plan
41 */
42 abstract public class AbstractCoreSpec {
43
44 protected static String bambooServerName = "https://bamboo.typo3.com:443";
45 protected static String projectName = "TYPO3 Core";
46 protected static String projectKey = "CORE";
47
48 protected String composerRootVersionEnvironment = "COMPOSER_ROOT_VERSION=9.3.0@dev";
49
50 protected String testingFrameworkBuildPath = "vendor/typo3/testing-framework/Resources/Core/Build/";
51
52 protected String credentialsMysql =
53 "typo3DatabaseName=\"func\"" +
54 " typo3DatabaseUsername=\"funcu\"" +
55 " typo3DatabasePassword=\"funcp\"" +
56 " typo3DatabaseHost=\"localhost\"" +
57 " typo3InstallToolPassword=\"klaus\"";
58
59 protected String installCredentialsMysql =
60 "typo3InstallMysqlDatabaseName=\"func_install\"" +
61 " typo3InstallMysqlDatabaseUsername=\"funcu\"" +
62 " typo3InstallMysqlDatabasePassword=\"funcp\"" +
63 " typo3InstallMysqlDatabaseHost=\"localhost\"";
64
65 protected String credentialsMssql =
66 "typo3DatabaseDriver=\"sqlsrv\"" +
67 " typo3DatabaseName=\"func\"" +
68 " typo3DatabasePassword='Test1234!'" +
69 " typo3DatabaseUsername=\"SA\"" +
70 " typo3DatabaseHost=\"localhost\"" +
71 " typo3DatabasePort=\"1433\"" +
72 " typo3DatabaseCharset=\"utf-8\"";
73
74 protected String credentialsPgsql =
75 "typo3DatabaseDriver=\"pdo_pgsql\"" +
76 " typo3DatabaseName=\"func\"" +
77 " typo3DatabaseUsername=\"bamboo\"" +
78 " typo3DatabaseHost=\"localhost\"";
79
80 protected String installCredentialsPgsql =
81 "typo3InstallPostgresqlDatabaseName=\"func_atipgsql\"" +
82 " typo3InstallPostgresqlDatabaseUsername=\"bamboo\"" +
83 " typo3InstallPostgresqlDatabaseHost=\"localhost\"";
84
85 protected String credentialsSqlite =
86 "typo3DatabaseDriver=\"pdo_sqlite\"";
87
88 /**
89 * Default permissions on core plans
90 *
91 * @param projectName
92 * @param planName
93 * @return
94 */
95 protected PlanPermissions getDefaultPlanPermissions(String projectKey, String planKey) {
96 return new PlanPermissions(new PlanIdentifier(projectKey, planKey))
97 .permissions(new Permissions()
98 .groupPermissions("TYPO3 GmbH", PermissionType.ADMIN, PermissionType.VIEW, PermissionType.EDIT, PermissionType.BUILD, PermissionType.CLONE)
99 .groupPermissions("TYPO3 Core Team", PermissionType.VIEW, PermissionType.BUILD)
100 .loggedInUserPermissions(PermissionType.VIEW)
101 .anonymousUserPermissionView()
102 );
103 }
104
105 /**
106 * Default plan plugin configuration
107 *
108 * @return
109 */
110 protected PluginConfiguration getDefaultPlanPluginConfiguration() {
111 return new AllOtherPluginsConfiguration()
112 .configuration(new MapBuilder()
113 .put("custom", new MapBuilder()
114 .put("artifactHandlers.useCustomArtifactHandlers", "false")
115 .put("buildExpiryConfig", new MapBuilder()
116 .put("duration", "30")
117 .put("period", "days")
118 .put("labelsToKeep", "")
119 .put("expiryTypeResult", "true")
120 .put("buildsToKeep", "")
121 .put("enabled", "true")
122 .build()
123 )
124 .build()
125 )
126 .build()
127 );
128 }
129
130 /**
131 * Default job plugin configuration
132 *
133 * @return
134 */
135 protected PluginConfiguration getDefaultJobPluginConfiguration() {
136 return new AllOtherPluginsConfiguration()
137 .configuration(new MapBuilder()
138 .put("repositoryDefiningWorkingDirectory", -1)
139 .put("custom", new MapBuilder()
140 .put("auto", new MapBuilder()
141 .put("regex", "")
142 .put("label", "")
143 .build()
144 )
145 .put("buildHangingConfig.enabled", "false")
146 .put("ncover.path", "")
147 .put("clover", new MapBuilder()
148 .put("path", "")
149 .put("license", "")
150 .put("useLocalLicenseKey", "true")
151 .build()
152 )
153 .build()
154 )
155 .build()
156 );
157 }
158
159 /**
160 * Job composer validate
161 */
162 protected Job getJobComposerValidate() {
163 return new Job("Validate composer.json", new BambooKey("VC"))
164 .description("Validate composer.json before actual tests are executed")
165 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
166 .tasks(
167 this.getTaskGitCloneRepository(),
168 this.getTaskGitCherryPick(),
169 new CommandTask()
170 .description("composer validate")
171 .executable("composer").argument("validate")
172 .environmentVariables(this.composerRootVersionEnvironment)
173 )
174 .cleanWorkingDirectory(true);
175 }
176
177 /**
178 * Job acceptance test installs system on mysql
179 *
180 * @param Requirement requirement
181 * @param String requirementIdentfier
182 */
183 protected Job getJobAcceptanceTestInstallMysql(Requirement requirement, String requirementIdentifier) {
184 return new Job("Accept inst my " + requirementIdentifier, new BambooKey("ACINSTMY" + requirementIdentifier))
185 .description("Install TYPO3 on mysql and load introduction package " + requirementIdentifier)
186 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
187 .tasks(
188 this.getTaskGitCloneRepository(),
189 this.getTaskGitCherryPick(),
190 this.getTaskComposerInstall(),
191 this.getTaskPrepareAcceptanceTest(),
192 new CommandTask()
193 .description("Install TYPO3 on mysql")
194 .executable("codecept")
195 .argument("run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=mysql,headless --xml reports.xml --html reports.html")
196 .environmentVariables(this.installCredentialsMysql)
197 )
198 .finalTasks(
199 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
200 .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
201 this.getTaskDeleteMysqlDatabases(),
202 this.getTaskTearDownAcceptanceTestSetup()
203 )
204 .requirements(
205 requirement
206 )
207 .artifacts(new Artifact()
208 .name("Test Report")
209 .copyPattern("typo3temp/var/tests/AcceptanceReports/")
210 .shared(false)
211 )
212 .cleanWorkingDirectory(true);
213 }
214
215 /**
216 * Job acceptance test installs system and introduction package on pgsql
217 *
218 * @param Requirement requirement
219 * @param String requirementIdentfier
220 */
221 protected Job getJobAcceptanceTestInstallPgsql(Requirement requirement, String requirementIdentifier) {
222 return new Job("Accept inst pg " + requirementIdentifier, new BambooKey("ACINSTPG" + requirementIdentifier))
223 .description("Install TYPO3 on pgsql and load introduction package " + requirementIdentifier)
224 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
225 .tasks(
226 this.getTaskGitCloneRepository(),
227 this.getTaskGitCherryPick(),
228 this.getTaskComposerInstall(),
229 this.getTaskPrepareAcceptanceTest(),
230 new CommandTask()
231 .description("Install TYPO3 on postgresql")
232 .executable("codecept")
233 .argument("run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=postgresql,headless --xml reports.xml --html reports.html")
234 .environmentVariables(this.installCredentialsPgsql)
235 )
236 .finalTasks(
237 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
238 .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
239 this.getTaskDeletePgsqlDatabases(),
240 this.getTaskTearDownAcceptanceTestSetup()
241 )
242 .requirements(
243 requirement
244 )
245 .artifacts(new Artifact()
246 .name("Test Report")
247 .copyPattern("typo3temp/var/tests/AcceptanceReports/")
248 .shared(false)
249 )
250 .cleanWorkingDirectory(true);
251 }
252
253 /**
254 * Job acceptance test installs system and introduction package on sqlite
255 *
256 * @param Requirement requirement
257 * @param String requirementIdentfier
258 */
259 protected Job getJobAcceptanceTestInstallSqlite(Requirement requirement, String requirementIdentifier) {
260 return new Job("Accept inst sq " + requirementIdentifier, new BambooKey("ACINSTSQ" + requirementIdentifier))
261 .description("Install TYPO3 on sqlite and load introduction package " + requirementIdentifier)
262 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
263 .tasks(
264 this.getTaskGitCloneRepository(),
265 this.getTaskGitCherryPick(),
266 this.getTaskComposerInstall(),
267 this.getTaskPrepareAcceptanceTest(),
268 new CommandTask()
269 .description("Install TYPO3 on sqlite")
270 .executable("codecept")
271 .argument("run Install -d -c typo3/sysext/core/Tests/codeception.yml --env=sqlite,headless --xml reports.xml --html reports.html")
272 )
273 .finalTasks(
274 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
275 .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
276 this.getTaskTearDownAcceptanceTestSetup()
277 )
278 .requirements(
279 requirement
280 )
281 .artifacts(new Artifact()
282 .name("Test Report")
283 .copyPattern("typo3temp/var/tests/AcceptanceReports/")
284 .shared(false)
285 )
286 .cleanWorkingDirectory(true);
287 }
288
289 /**
290 * Jobs for mysql based acceptance tests
291 *
292 * @param int numberOfChunks
293 * @param Requirement requirement
294 * @param String requirementIdentifier
295 */
296 protected ArrayList<Job> getJobsAcceptanceTestsMysql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
297 ArrayList<Job> jobs = new ArrayList<Job>();
298
299 for (int i=1; i<=numberOfChunks; i++) {
300 String formattedI = "" + i;
301 if (i < 10) {
302 formattedI = "0" + i;
303 }
304 jobs.add(new Job("Accept my " + requirementIdentifier + " " + formattedI, new BambooKey("ACMY" + requirementIdentifier + formattedI))
305 .description("Run acceptance tests" + requirementIdentifier)
306 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
307 .tasks(
308 this.getTaskGitCloneRepository(),
309 this.getTaskGitCherryPick(),
310 this.getTaskComposerInstall(),
311 this.getTaskPrepareAcceptanceTest(),
312 new ScriptTask()
313 .description("Split acceptance tests")
314 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
315 .inlineBody(
316 this.getScriptTaskBashInlineBody() +
317 "./" + this.testingFrameworkBuildPath + "Scripts/splitAcceptanceTests.sh " + numberOfChunks + "\n"
318 ),
319 new CommandTask()
320 .description("Execute codeception acceptance suite group " + formattedI)
321 .executable("codecept")
322 .argument("run Acceptance -d -g AcceptanceTests-Job-" + i + " -c " + this.testingFrameworkBuildPath + "AcceptanceTests.yml --xml reports.xml --html reports.html")
323 .environmentVariables(this.credentialsMysql)
324 )
325 .finalTasks(
326 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
327 .resultDirectories("typo3temp/var/tests/AcceptanceReports/reports.xml"),
328 this.getTaskDeleteMysqlDatabases(),
329 this.getTaskTearDownAcceptanceTestSetup()
330 )
331 .requirements(
332 requirement
333 )
334 .artifacts(new Artifact()
335 .name("Test Report")
336 .copyPattern("typo3temp/var/tests/AcceptanceReports/")
337 .shared(false)
338 )
339 .cleanWorkingDirectory(true)
340 .enabled(false)
341 );
342 }
343
344 return jobs;
345 }
346
347 /**
348 * Jobs for mysql based functional tests
349 *
350 * @param int numberOfChunks
351 * @param Requirement requirement
352 * @param String requirementIdentifier
353 */
354 protected ArrayList<Job> getJobsFunctionalTestsMysql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
355 ArrayList<Job> jobs = new ArrayList<Job>();
356
357 for (int i=1; i<=numberOfChunks; i++) {
358 String formattedI = "" + i;
359 if (i < 10) {
360 formattedI = "0" + i;
361 }
362 jobs.add(new Job("Func mysql " + requirementIdentifier + " " + formattedI, new BambooKey("FMY" + requirementIdentifier + formattedI))
363 .description("Run functional tests on mysql DB " + requirementIdentifier)
364 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
365 .tasks(
366 this.getTaskGitCloneRepository(),
367 this.getTaskGitCherryPick(),
368 this.getTaskComposerInstall(),
369 this.getTaskSplitFunctionalJobs(numberOfChunks),
370 new ScriptTask()
371 .description("Run phpunit with functional chunk " + formattedI)
372 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
373 .inlineBody(
374 this.getScriptTaskBashInlineBody() +
375 "./bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
376 )
377 .environmentVariables(this.credentialsMysql)
378 )
379 .finalTasks(
380 this.getTaskDeleteMysqlDatabases(),
381 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
382 .resultDirectories("test-reports/phpunit.xml")
383 )
384 .requirements(
385 requirement
386 )
387 .cleanWorkingDirectory(true)
388 );
389 }
390
391 return jobs;
392 }
393
394 /**
395 * Jobs for mssql based functional tests
396 *
397 * @param int numberOfChunks
398 * @param Requirement requirement
399 * @param String requirementIdentifier
400 */
401 protected ArrayList<Job> getJobsFunctionalTestsMssql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
402 ArrayList<Job> jobs = new ArrayList<Job>();
403
404 for (int i=1; i<=numberOfChunks; i++) {
405 String formattedI = "" + i;
406 if (i < 10) {
407 formattedI = "0" + i;
408 }
409 jobs.add(new Job("Func mssql " + requirementIdentifier + " " + formattedI, new BambooKey("FMS" + requirementIdentifier + formattedI))
410 .description("Run functional tests on mysql DB " + requirementIdentifier)
411 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
412 .tasks(
413 this.getTaskGitCloneRepository(),
414 this.getTaskGitCherryPick(),
415 this.getTaskComposerInstall(),
416 this.getTaskSplitFunctionalJobs(numberOfChunks),
417 new ScriptTask()
418 .description("Run phpunit with functional chunk " + formattedI)
419 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
420 .inlineBody(
421 this.getScriptTaskBashInlineBody() +
422 "./bin/phpunit --exclude-group not-mssql --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
423 )
424 .environmentVariables(this.credentialsMssql)
425 )
426 .finalTasks(
427 this.getTaskDeleteMssqlDatabases(),
428 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
429 .resultDirectories("test-reports/phpunit.xml")
430 )
431 .requirements(
432 requirement
433 )
434 .cleanWorkingDirectory(true)
435 .enabled(false)
436 );
437 }
438
439 return jobs;
440 }
441
442 /**
443 * Jobs for pgsql based functional tests
444 *
445 * @param int numberOfChunks
446 * @param Requirement requirement
447 * @param String requirementIdentifier
448 */
449 protected ArrayList<Job> getJobsFunctionalTestsPgsql(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
450 ArrayList<Job> jobs = new ArrayList<Job>();
451
452 for (int i=1; i<=numberOfChunks; i++) {
453 String formattedI = "" + i;
454 if (i < 10) {
455 formattedI = "0" + i;
456 }
457 jobs.add(new Job("Func pgsql " + requirementIdentifier + " " + formattedI, new BambooKey("FPG" + requirementIdentifier + formattedI))
458 .description("Run functional tests on pgsql DB " + requirementIdentifier)
459 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
460 .tasks(
461 this.getTaskGitCloneRepository(),
462 this.getTaskGitCherryPick(),
463 this.getTaskComposerInstall(),
464 this.getTaskSplitFunctionalJobs(numberOfChunks),
465 new ScriptTask()
466 .description("Run phpunit with functional chunk " + formattedI)
467 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
468 .inlineBody(
469 this.getScriptTaskBashInlineBody() +
470 "./bin/phpunit --exclude-group not-postgres --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
471 )
472 .environmentVariables(this.credentialsPgsql)
473 )
474 .finalTasks(
475 this.getTaskDeletePgsqlDatabases(),
476 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
477 .resultDirectories("test-reports/phpunit.xml")
478 )
479 .requirements(
480 requirement
481 )
482 .cleanWorkingDirectory(true)
483 );
484 }
485
486 return jobs;
487 }
488
489 /**
490 * Jobs for sqlite based functional tests
491 *
492 * @param int numberOfChunks
493 * @param Requirement requirement
494 * @param String requirementIdentifier
495 */
496 protected ArrayList<Job> getJobsFunctionalTestsSqlite(int numberOfChunks, Requirement requirement, String requirementIdentifier) {
497 ArrayList<Job> jobs = new ArrayList<Job>();
498
499 for (int i=1; i<=numberOfChunks; i++) {
500 String formattedI = "" + i;
501 if (i < 10) {
502 formattedI = "0" + i;
503 }
504 jobs.add(new Job("Func sqlite " + requirementIdentifier + " " + formattedI, new BambooKey("FSL" + requirementIdentifier + formattedI))
505 .description("Run functional tests on sqlite DB " + requirementIdentifier)
506 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
507 .tasks(
508 this.getTaskGitCloneRepository(),
509 this.getTaskGitCherryPick(),
510 this.getTaskComposerInstall(),
511 this.getTaskSplitFunctionalJobs(numberOfChunks),
512 new ScriptTask()
513 .description("Run phpunit with functional chunk " + formattedI)
514 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
515 .inlineBody(
516 this.getScriptTaskBashInlineBody() +
517 "./bin/phpunit --exclude-group not-sqlite --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "FunctionalTests-Job-" + i + ".xml"
518 )
519 .environmentVariables(this.credentialsSqlite)
520 )
521 .finalTasks(
522 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
523 .resultDirectories("test-reports/phpunit.xml")
524 )
525 .requirements(
526 requirement
527 )
528 .cleanWorkingDirectory(true)
529 );
530 }
531
532 return jobs;
533 }
534
535 /**
536 * Job with integration test checking for valid @xy annotations
537 */
538 protected Job getJobIntegrationAnnotations() {
539 return new Job("Integration annotations", new BambooKey("IANNO"))
540 .description("Check docblock-annotations by executing Build/Scripts/annotationChecker.php script")
541 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
542 .tasks(
543 this.getTaskGitCloneRepository(),
544 this.getTaskGitCherryPick(),
545 this.getTaskComposerInstall(),
546 new ScriptTask()
547 .description("Execute annotations check script")
548 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
549 .inlineBody(
550 this.getScriptTaskBashInlineBody() +
551 "./Build/Scripts/annotationChecker.php\n"
552 )
553 )
554 .requirements(
555 this.getRequirementPhpVersion72()
556 )
557 .cleanWorkingDirectory(true);
558 }
559
560 /**
561 * Job with various smaller script tests
562 */
563 protected Job getJobIntegrationVarious() {
564 // Exception code checker, xlf, permissions, rst file check
565 return new Job("Integration various", new BambooKey("CDECC"))
566 .description("Checks duplicate exceptions, git submodules, xlf files, permissions, rst")
567 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
568 .tasks(
569 this.getTaskGitCloneRepository(),
570 this.getTaskGitCherryPick(),
571 this.getTaskComposerInstall(),
572 new ScriptTask()
573 .description("Run duplicate exception code check script")
574 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
575 .inlineBody(
576 this.getScriptTaskBashInlineBody() +
577 "./Build/Scripts/duplicateExceptionCodeCheck.sh\n"
578 ),
579 new ScriptTask()
580 .description("Run git submodule status and verify there are none")
581 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
582 .inlineBody(
583 this.getScriptTaskBashInlineBody() +
584 "if [[ `git submodule status 2>&1 | wc -l` -ne 0 ]]; then\n" +
585 " echo \\\"Found a submodule definition in repository\\\";\n" +
586 " exit 99;\n" +
587 "fi\n"
588 ),
589 new ScriptTask()
590 .description("Run permission check script")
591 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
592 .inlineBody(
593 this.getScriptTaskBashInlineBody() +
594 "./Build/Scripts/checkFilePermissions.sh\n"
595 ),
596 new ScriptTask()
597 .description("Run xlf check")
598 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
599 .inlineBody(
600 this.getScriptTaskBashInlineBody() +
601 "./Build/Scripts/xlfcheck.sh"
602 ),
603 new ScriptTask()
604 .description("Run rst check")
605 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
606 .inlineBody(
607 this.getScriptTaskBashInlineBody() +
608 "./Build/Scripts/validateRstFiles.php"
609 ),
610 new ScriptTask()
611 .description("Run path length check")
612 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
613 .inlineBody(
614 this.getScriptTaskBashInlineBody() +
615 "./Build/Scripts/maxFilePathLength.sh"
616 ),
617 new ScriptTask()
618 .description("Run extension scanner ReST file reference tester")
619 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
620 .inlineBody(
621 this.getScriptTaskBashInlineBody() +
622 "./Build/Scripts/extensionScannerRstFileReferences.php"
623 ),
624 new ScriptTask()
625 .description("Run functional fixture csv format checker")
626 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
627 .inlineBody(
628 this.getScriptTaskBashInlineBody() +
629 "./Build/Scripts/checkIntegrityCsvFixtures.php"
630 ),
631 new ScriptTask()
632 .description("Run composer.json integrity check")
633 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
634 .inlineBody(
635 this.getScriptTaskBashInlineBody() +
636 "./Build/Scripts/checkIntegrityComposer.php"
637 )
638 )
639 .requirements(
640 this.getRequirementPhpVersion72()
641 )
642 .cleanWorkingDirectory(true);
643 }
644
645 /**
646 * Job for javascript unit tests
647 */
648 protected Job getJobUnitJavaScript() {
649 return new Job("Unit JavaScript", new BambooKey("JSUT"))
650 .description("Run JavaScript unit tests")
651 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
652 .tasks(
653 this.getTaskGitCloneRepository(),
654 this.getTaskGitCherryPick(),
655 this.getTaskComposerInstall(),
656 new ScriptTask()
657 .description("yarn install in Build/ dir")
658 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
659 .inlineBody(
660 this.getScriptTaskBashInlineBody() +
661 "yarn install"
662 )
663 .workingSubdirectory("Build/"),
664 new ScriptTask()
665 .description("Run tests")
666 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
667 .inlineBody(
668 this.getScriptTaskBashInlineBody() +
669 "./Build/node_modules/karma/bin/karma start " + this.testingFrameworkBuildPath + "Configuration/JSUnit/karma.conf.js --single-run"
670 )
671 )
672 .finalTasks(
673 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
674 .resultDirectories("typo3temp/var/tests/*")
675 )
676 .requirements(
677 this.getRequirementPhpVersion72()
678 )
679 .artifacts(
680 new Artifact()
681 .name("Clover Report (System)")
682 .copyPattern("**/*.*")
683 .location("Build/target/site/clover")
684 .shared(false)
685 )
686 .cleanWorkingDirectory(true);
687 }
688
689 /**
690 * Job for PHP lint
691 *
692 * @param Requirement requirement
693 * @param String requirementIdentfier
694 */
695 protected Job getJobLintPhp(Requirement requirement, String requirementIdentifier) {
696 return new Job("Lint " + requirementIdentifier, new BambooKey("L" + requirementIdentifier))
697 .description("Run php -l on source files for linting " + requirementIdentifier)
698 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
699 .tasks(
700 this.getTaskGitCloneRepository(),
701 this.getTaskGitCherryPick(),
702 new ScriptTask()
703 .description("Run php lint")
704 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
705 .inlineBody(
706 this.getScriptTaskBashInlineBody() +
707 "find . -name \\*.php -print0 | xargs -0 -n1 -P2 php -l >/dev/null\n"
708 )
709 )
710 .requirements(
711 requirement
712 )
713 .cleanWorkingDirectory(true);
714 }
715
716 /**
717 * Job for lint npm scss and typescript
718 */
719 protected Job getJobLintScssTs() {
720 return new Job("Lint scss ts", new BambooKey("LSTS"))
721 .description("Run npm lint, run npm run build-js")
722 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
723 .tasks(
724 this.getTaskGitCloneRepository(),
725 this.getTaskGitCherryPick(),
726 new ScriptTask()
727 .description("yarn install in Build/ dir")
728 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
729 .inlineBody(
730 this.getScriptTaskBashInlineBody() +
731 "yarn install"
732 )
733 .workingSubdirectory("Build/"),
734 new NpmTask()
735 .description("Run npm lint")
736 .nodeExecutable("Node.js")
737 .workingSubdirectory("Build/")
738 .command("run lint"),
739 new NpmTask()
740 .description("Run npm build-js")
741 .nodeExecutable("Node.js")
742 .workingSubdirectory("Build/")
743 .command("run build-js"),
744 new ScriptTask()
745 .description("git status to check for changed files after build-js")
746 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
747 .inlineBody(
748 this.getScriptTaskBashInlineBody() +
749 "git status | grep -q \"nothing to commit, working tree clean\""
750 )
751 )
752 .requirements(
753 new Requirement("system.imageVersion")
754 )
755 .cleanWorkingDirectory(true);
756 }
757
758 /**
759 * Job for unit testing PHP
760 *
761 * @param Requirement requirement
762 * @param String requirementIdentfier
763 */
764 protected Job getJobUnitPhp(Requirement requirement, String requirementIdentifier) {
765 return new Job("Unit " + requirementIdentifier, new BambooKey("UT" + requirementIdentifier))
766 .description("Run unit tests " + requirementIdentifier)
767 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
768 .tasks(
769 this.getTaskGitCloneRepository(),
770 this.getTaskGitCherryPick(),
771 this.getTaskComposerInstall(),
772 new ScriptTask()
773 .description("Run phpunit")
774 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
775 .inlineBody(
776 this.getScriptTaskBashInlineBody() +
777 "php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTests.xml"
778 )
779 )
780 .finalTasks(
781 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
782 .resultDirectories("test-reports/phpunit.xml")
783 )
784 .requirements(
785 requirement
786 )
787 .cleanWorkingDirectory(true);
788 }
789
790 /**
791 * Job for unit testing deprecated PHP
792 *
793 * @param Requirement requirement
794 * @param String requirementIdentfier
795 */
796 protected Job getJobUnitDeprecatedPhp(Requirement requirement, String requirementIdentifier) {
797 return new Job("Unit deprecated " + requirementIdentifier, new BambooKey("UTD" + requirementIdentifier))
798 .description("Run deprecated unit tests " + requirementIdentifier)
799 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
800 .tasks(
801 this.getTaskGitCloneRepository(),
802 this.getTaskGitCherryPick(),
803 this.getTaskComposerInstall(),
804 new ScriptTask()
805 .description("Run phpunit")
806 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
807 .inlineBody(
808 this.getScriptTaskBashInlineBody() +
809 "php -n -c /etc/php/cli-no-xdebug/php.ini bin/phpunit --log-junit test-reports/phpunit.xml -c " + this.testingFrameworkBuildPath + "UnitTestsDeprecated.xml"
810 )
811 )
812 .finalTasks(
813 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
814 .resultDirectories("test-reports/phpunit.xml")
815 )
816 .requirements(
817 requirement
818 )
819 .cleanWorkingDirectory(true);
820 }
821
822 /**
823 * Jobs for unit testing PHP in random test order
824 *
825 * @param int numberOfRuns
826 * @param Requirement requirement
827 * @param String requirementIdentfier
828 */
829 protected ArrayList<Job> getJobUnitPhpRandom(int numberOfRuns, Requirement requirement, String requirementIdentifier) {
830 ArrayList<Job> jobs = new ArrayList<Job>();
831
832 for (int i=1; i<=numberOfRuns; i++) {
833 jobs.add(new Job("Unit " + requirementIdentifier + " random " + i, new BambooKey("UTR" + requirementIdentifier + i))
834 .description("Run unit tests on " + requirementIdentifier + " in random order 0" + i)
835 .pluginConfigurations(this.getDefaultJobPluginConfiguration())
836 .tasks(
837 this.getTaskGitCloneRepository(),
838 this.getTaskGitCherryPick(),
839 this.getTaskComposerInstall(),
840 new ScriptTask()
841 .description("Run phpunit-randomizer")
842 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
843 .inlineBody(
844 this.getScriptTaskBashInlineBody() +
845 "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"
846 )
847 )
848 .finalTasks(
849 new TestParserTask(TestParserTaskProperties.TestType.JUNIT)
850 .resultDirectories("test-reports/phpunit.xml")
851 )
852 .requirements(
853 requirement
854 )
855 .cleanWorkingDirectory(true)
856 );
857 }
858
859 return jobs;
860 }
861
862 /**
863 * Task definition for basic core clone of linked default repository
864 */
865 protected Task getTaskGitCloneRepository() {
866 return new VcsCheckoutTask()
867 .description("Checkout git core")
868 .checkoutItems(new CheckoutItem().defaultRepository())
869 .cleanCheckout(true);
870 }
871
872 /**
873 * Task definition to cherry pick a patch set from gerrit on top of cloned core
874 */
875 protected Task getTaskGitCherryPick() {
876 return new ScriptTask()
877 .description("Gerrit cherry pick")
878 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
879 .inlineBody(
880 this.getScriptTaskBashInlineBody() +
881 "CHANGEURL=${bamboo.changeUrl}\n" +
882 "CHANGEURLID=${CHANGEURL#https://review.typo3.org/}\n" +
883 "PATCHSET=${bamboo.patchset}\n" +
884 "\n" +
885 "if [[ $CHANGEURL ]]; then\n" +
886 " gerrit-cherry-pick https://review.typo3.org/Packages/TYPO3.CMS $CHANGEURLID/$PATCHSET || exit 1\n" +
887 "fi\n"
888 );
889 }
890
891 /**
892 * Task definition to execute composer install
893 */
894 protected Task getTaskComposerInstall() {
895 return new CommandTask()
896 .description("composer install")
897 .executable("composer")
898 .argument("install -n")
899 .environmentVariables(this.composerRootVersionEnvironment);
900 }
901
902 /**
903 * Task to prepare an acceptance test starting selenium and others
904 */
905 protected Task getTaskPrepareAcceptanceTest() {
906 return new ScriptTask()
907 .description("Start php web server, chromedriver, prepare environment")
908 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
909 .inlineBody(
910 this.getScriptTaskBashInlineBody() +
911 "php -n -c /etc/php/cli-no-xdebug/php.ini -S localhost:8000 >/dev/null 2>&1 &\n" +
912 "echo $! > phpserver.pid\n" +
913 "\n" +
914 "./bin/chromedriver --url-base=/wd/hub >/dev/null 2>&1 &\n" +
915 "echo $! > chromedriver.pid\n" +
916 "\n" +
917 "mkdir -p typo3temp/var/tests/\n"
918 );
919 }
920
921 /**
922 * Task to delete any created mysql test databases, used as final task
923 */
924 protected Task getTaskDeleteMysqlDatabases() {
925 return new ScriptTask()
926 .description("Delete mysql test dbs")
927 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
928 .inlineBody(
929 this.getScriptTaskBashInlineBody() +
930 "DB_STARTS_WITH=\"func_\"\n" +
931 "MUSER=\"funcu\"\n" +
932 "MPWD=\"funcp\"\n" +
933 "MYSQL=\"mysql\"\n" +
934 "DBS=\"$($MYSQL -u $MUSER -p\"$MPWD\" -Bse 'show databases')\"\n" +
935 "\n" +
936 "for db in $DBS; do\n" +
937 " if [[ \"$db\" == $DB_STARTS_WITH* ]]; then\n" +
938 " echo \"Deleting $db\"\n" +
939 " $MYSQL -u $MUSER -p\"$MPWD\" -Bse \"drop database $db\"\n" +
940 " fi\n" +
941 "done\n"
942 );
943 }
944
945 /**
946 * Task to delete any created mssql test databases, used as final task
947 */
948 protected Task getTaskDeleteMssqlDatabases() {
949 return new ScriptTask()
950 .description("Delete mssql test dbs")
951 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
952 .inlineBody(
953 this.getScriptTaskBashInlineBody() +
954 "DBS=`/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Test1234!' -Q 'select name from sys.databases' | grep '^func_'`\n" +
955 "\n" +
956 "for db in $DBS; do\n" +
957 " echo \"Deleteing $db\"\n" +
958 " /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Test1234!' -Q \"drop database $db\"\n" +
959 "done\n"
960 );
961 }
962
963 /**
964 * Task to delete any created pgsql test databases, used as final task
965 */
966 protected Task getTaskDeletePgsqlDatabases() {
967 return new ScriptTask()
968 .description("Delete pgsql test dbs")
969 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
970 .inlineBody(
971 this.getScriptTaskBashInlineBody() +
972 "DB_STARTS_WITH=\"func_\"\n" +
973 "PGUSER=\"bamboo\"\n" +
974 "DBS=\"$(/usr/bin/psql -qtA -c 'SELECT datname FROM pg_database WHERE datistemplate = false;' postgres)\"\n" +
975 "\n" +
976 "for db in $DBS; do\n" +
977 " if [[ \"$db\" == $DB_STARTS_WITH* ]]; then\n" +
978 " echo \"Deleting $db\"\n" +
979 " /usr/bin/psql -qtA -c \"DROP DATABASE $db\" postgres\n" +
980 " fi\n" +
981 "done\n"
982 );
983 }
984
985 /**
986 * Task to stop selenium and friends, opposite of getTaskPrepareAcceptanceTest, used as final task
987 */
988 protected Task getTaskTearDownAcceptanceTestSetup() {
989 return new ScriptTask()
990 .description("Stop acceptance test services like chromedriver and friends")
991 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
992 .inlineBody(
993 this.getScriptTaskBashInlineBody() +
994 "kill -9 `cat phpserver.pid`\n" +
995 "kill `cat chromedriver.pid`\n"
996 );
997 }
998
999 /**
1000 * Task to split functional jobs into chunks
1001 */
1002 protected Task getTaskSplitFunctionalJobs(int numberOfJobs) {
1003 return new ScriptTask()
1004 .description("Create list of test files to execute per job")
1005 .interpreter(ScriptTaskProperties.Interpreter.BINSH_OR_CMDEXE)
1006 .inlineBody(
1007 this.getScriptTaskBashInlineBody() +
1008 "./" + this.testingFrameworkBuildPath + "Scripts/splitFunctionalTests.php " + numberOfJobs + " -v"
1009 );
1010 }
1011
1012 /**
1013 * Requirement for php 7.0
1014 */
1015 protected Requirement getRequirementPhpVersion70() {
1016 return new Requirement("system.phpVersion")
1017 .matchValue("7.0")
1018 .matchType(Requirement.MatchType.EQUALS);
1019 }
1020
1021 /**
1022 * Requirement for php 7.1
1023 */
1024 protected Requirement getRequirementPhpVersion71() {
1025 return new Requirement("system.phpVersion")
1026 .matchValue("7.1")
1027 .matchType(Requirement.MatchType.EQUALS);
1028 }
1029
1030 /**
1031 * Requirement for php 7.2
1032 */
1033 protected Requirement getRequirementPhpVersion72() {
1034 return new Requirement("system.phpVersion")
1035 .matchValue("7.2")
1036 .matchType(Requirement.MatchType.EQUALS);
1037 }
1038
1039 /**
1040 * Requirement for php 7.0 or 7.1
1041 */
1042 protected Requirement getRequirementPhpVersion70Or71() {
1043 return new Requirement("system.phpVersion")
1044 .matchValue("7\\.0|7\\.1")
1045 .matchType(Requirement.MatchType.MATCHES);
1046 }
1047
1048 /**
1049 * Requirement for php 7.0 or 7.1 or 7.2
1050 */
1051 protected Requirement getRequirementPhpVersion70Or71Or72() {
1052 return new Requirement("system.phpVersion")
1053 .matchValue("7\\.0|7\\.1|7\\.2")
1054 .matchType(Requirement.MatchType.MATCHES);
1055 }
1056
1057 /**
1058 * A bash header for script tasks forking a bash if needed
1059 */
1060 protected String getScriptTaskBashInlineBody() {
1061 return
1062 "#!/bin/bash\n" +
1063 "\n" +
1064 "if [ \"$(ps -p \"$$\" -o comm=)\" != \"bash\" ]; then\n" +
1065 " bash \"$0\" \"$@\"\n" +
1066 " exit \"$?\"\n" +
1067 "fi\n" +
1068 "\n";
1069 }
1070 }