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