diff --git a/.gitignore b/.gitignore index efa962ea28631..79dc38eb3c909 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ /subprojects/*/out /.teamcity/*.iml /.teamcity/target +!/.teamcity/Gradle_Check_dsl.iml # Eclipse # ------- diff --git a/.teamcity/Gradle_AgentTest/settings.kts b/.teamcity/Gradle_AgentTest/settings.kts new file mode 100644 index 0000000000000..77caaf31ce454 --- /dev/null +++ b/.teamcity/Gradle_AgentTest/settings.kts @@ -0,0 +1,62 @@ +package Gradle_AgentTest + +import jetbrains.buildServer.configs.kotlin.v2018_1.project +import jetbrains.buildServer.configs.kotlin.v2018_1.version +import model.CIBuildModel +import model.JvmVersion +import model.NoBuildCache +import model.OS +import model.SpecificBuild +import model.Stage +import model.StageNames +import model.TestCoverage +import model.TestType +import projects.RootProject + +/* +The settings script is an entry point for defining a single +TeamCity project. TeamCity looks for the 'settings.kts' file in a +project directory and runs it if it's found, so the script name +shouldn't be changed and its package should be the same as the +project's id. + +The script should contain a single call to the project() function +with a Project instance or an init function as an argument. + +VcsRoots, BuildTypes, and Templates of this project must be +registered inside project using the vcsRoot(), buildType(), and +template() methods respectively. + +Subprojects can be defined either in their own settings.kts or by +calling the subProjects() method in this project. + +To debug settings scripts in command-line, run the + + mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate + +command and attach your debugger to the port 8000. + +To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View -> +Tool Windows -> Maven Projects), find the generate task +node (Plugins -> teamcity-configs -> teamcity-configs:generate), +the 'Debug' option is available in the context menu for the task. +*/ + +version = "2018.1" +val buildModel = CIBuildModel( + projectPrefix = "Gradle_AgentTest_", + rootProjectName = "Test Build Agents", + masterAndReleaseBranches = listOf("master"), + parentBuildCache = NoBuildCache, + childBuildCache = NoBuildCache, + tagBuilds = false, + publishStatusToGitHub = false, + buildScanTags = listOf("AgentTest"), + stages = listOf( + Stage(StageNames.QUICK_FEEDBACK_LINUX_ONLY, + runsIndependent = true, + specificBuilds = listOf(SpecificBuild.CompileAll, SpecificBuild.SanityCheck), + functionalTests = listOf(TestCoverage(TestType.quick, OS.linux, JvmVersion.java8))) + ) +) +project(RootProject(buildModel)) diff --git a/.teamcity/Gradle_Check/configurations/BaseGradleBuildType.kt b/.teamcity/Gradle_Check/configurations/BaseGradleBuildType.kt new file mode 100644 index 0000000000000..a534fd001e035 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/BaseGradleBuildType.kt @@ -0,0 +1,15 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildType +import model.BuildCache +import model.CIBuildModel +import model.Stage + +open class BaseGradleBuildType(model: CIBuildModel, val stage: Stage? = null, usesParentBuildCache: Boolean = false, init: BaseGradleBuildType.() -> Unit = {}) : BuildType() { + + val buildCache: BuildCache = if (usesParentBuildCache) model.parentBuildCache else model.childBuildCache + + init { + this.init() + } +} diff --git a/.teamcity/Gradle_Check/configurations/BuildDistributions.kt b/.teamcity/Gradle_Check/configurations/BuildDistributions.kt new file mode 100644 index 0000000000000..1f3989cba6de2 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/BuildDistributions.kt @@ -0,0 +1,23 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import model.CIBuildModel +import model.Stage + +class BuildDistributions(model: CIBuildModel, stage: Stage) : BaseGradleBuildType(model, stage = stage, init = { + uuid = "${model.projectPrefix}BuildDistributions" + id = AbsoluteId(uuid) + name = "Build Distributions" + description = "Creation and verification of the distribution and documentation" + + applyDefaults(model, this, "packageBuild", extraParameters = buildScanTag("BuildDistributions") + " -PtestJavaHome=${distributionTestJavaHome}", daemon = false) + + artifactRules = """$artifactRules + build/distributions/*.zip => distributions + build/build-receipt.properties + """.trimIndent() + + params { + param("env.JAVA_HOME", buildJavaHome) + } +}) diff --git a/.teamcity/Gradle_Check/configurations/BuildJavaVersions.kt b/.teamcity/Gradle_Check/configurations/BuildJavaVersions.kt new file mode 100644 index 0000000000000..e748f8a275bb4 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/BuildJavaVersions.kt @@ -0,0 +1,12 @@ +package configurations + + +private val linuxJava8Oracle = "%linux.java8.oracle.64bit%" +private val linuxJava9Oracle = "%linux.java9.oracle.64bit%" + +val buildJavaHome = linuxJava9Oracle +val coordinatorPerformanceTestJavaHome = linuxJava8Oracle +val individualPerformanceTestJavaHome = linuxJava8Oracle +val smokeTestJavaHome = linuxJava8Oracle +val distributionTestJavaHome = linuxJava9Oracle + diff --git a/.teamcity/Gradle_Check/configurations/CompileAll.kt b/.teamcity/Gradle_Check/configurations/CompileAll.kt new file mode 100644 index 0000000000000..cbf1b057aed7f --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/CompileAll.kt @@ -0,0 +1,38 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import model.CIBuildModel +import model.Stage + +class CompileAll(model: CIBuildModel, stage: Stage) : BaseGradleBuildType(model, stage = stage, usesParentBuildCache = true, init = { + uuid = buildTypeId(model) + id = AbsoluteId(uuid) + name = "Compile All" + description = "Compiles all the source code and warms up the build cache" + + params { + param("system.java9Home", "%linux.java9.oracle.64bit%") + param("env.JAVA_HOME", buildJavaHome) + } + + if (model.publishStatusToGitHub) { + features { + publishBuildStatusToGithub() + } + } + + applyDefaults( + model, + this, + ":createBuildReceipt -PignoreIncomingBuildReceipt=true compileAll", + extraParameters = buildScanTag("CompileAll") + ) + + artifactRules = """$artifactRules + build/build-receipt.properties + """.trimIndent() +}) { + companion object { + fun buildTypeId(model: CIBuildModel) = "${model.projectPrefix}CompileAll" + } +} diff --git a/.teamcity/Gradle_Check/configurations/DependenciesCheck.kt b/.teamcity/Gradle_Check/configurations/DependenciesCheck.kt new file mode 100644 index 0000000000000..7d4d4e1dbaa28 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/DependenciesCheck.kt @@ -0,0 +1,24 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import model.CIBuildModel +import model.Stage + +class DependenciesCheck(model: CIBuildModel, stage: Stage) : BaseGradleBuildType(model, stage = stage, init = { + uuid = "${model.projectPrefix}DependenciesCheck" + id = AbsoluteId(uuid) + name = "Dependencies Check - Java8 Linux" + description = "Checks external dependencies in Gradle distribution for known, published vulnerabilities" + + params { + param("env.JAVA_HOME", buildJavaHome) + } + + applyDefaults( + model, + this, + "dependencyCheckAnalyze", + notQuick = true, + extraParameters = buildScanTag("DependenciesCheck") + ) +}) diff --git a/.teamcity/Gradle_Check/configurations/FunctionalTest.kt b/.teamcity/Gradle_Check/configurations/FunctionalTest.kt new file mode 100644 index 0000000000000..09debcf80a3c9 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/FunctionalTest.kt @@ -0,0 +1,41 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import model.CIBuildModel +import model.OS +import model.Stage +import model.TestCoverage +import model.TestType + +class FunctionalTest(model: CIBuildModel, testCoverage: TestCoverage, subProject: String = "", useDaemon: Boolean = true, stage: Stage) : BaseGradleBuildType(model, stage = stage, init = { + uuid = testCoverage.asConfigurationId(model, subProject) + id = AbsoluteId(uuid) + name = testCoverage.asName() + if (!subProject.isEmpty()) " ($subProject)" else "" + val testTask = if (!subProject.isEmpty()) { + subProject + ":" + } else { + "" + } + testCoverage.testType.name + "Test" + val quickTest = testCoverage.testType == TestType.quick + val buildScanTags = listOf("FunctionalTest") + val buildScanValues = mapOf( + "coverageOs" to testCoverage.os.name, + "coverageJvmVendor" to testCoverage.vendor.name, + "coverageJvmVersion" to testCoverage.testJvmVersion.name + ) + applyDefaults(model, this, testTask, notQuick = !quickTest, os = testCoverage.os, + extraParameters = ( + listOf(""""-PtestJavaHome=%${testCoverage.os}.${testCoverage.testJvmVersion}.${testCoverage.vendor}.64bit%"""") + + buildScanTags.map { buildScanTag(it) } + + buildScanValues.map { buildScanCustomValue(it.key, it.value) } + ).joinToString(separator = " "), + timeout = testCoverage.testType.timeout, + daemon = useDaemon) + + params { + param("env.JAVA_HOME", "%${testCoverage.os}.${testCoverage.buildJvmVersion}.oracle.64bit%") + if (testCoverage.os == OS.linux) { + param("env.ANDROID_HOME", "/opt/android/sdk") + } + } +}) diff --git a/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt new file mode 100644 index 0000000000000..dd25dd3966739 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/GradleBuildConfigurationDefaults.kt @@ -0,0 +1,242 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildFeatures +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildStep +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildSteps +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildType +import jetbrains.buildServer.configs.kotlin.v2018_1.CheckoutMode +import jetbrains.buildServer.configs.kotlin.v2018_1.FailureAction +import jetbrains.buildServer.configs.kotlin.v2018_1.ProjectFeatures +import jetbrains.buildServer.configs.kotlin.v2018_1.buildFeatures.commitStatusPublisher +import jetbrains.buildServer.configs.kotlin.v2018_1.buildSteps.GradleBuildStep +import jetbrains.buildServer.configs.kotlin.v2018_1.buildSteps.script +import model.CIBuildModel +import model.GradleSubproject +import model.OS +import model.TestCoverage + +private val java7Homes = mapOf( + OS.windows to """"-Djava7Home=%windows.java7.oracle.64bit%"""", + OS.linux to "-Djava7Home=%linux.jdk.for.gradle.compile%", + OS.macos to "-Djava7Home=%macos.java7.oracle.64bit%" +) + +private val java9Homes = mapOf( + OS.windows to """"-Djava9Home=%windows.java9.oracle.64bit%"""", + OS.linux to "-Djava9Home=%linux.java9.oracle.64bit%", + OS.macos to "-Djava9Home=%macos.java9.oracle.64bit%" +) + + +fun shouldBeSkipped(subProject: GradleSubproject, testConfig: TestCoverage): Boolean { + // TODO: Hacky. We should really be running all the subprojects on macOS + // But we're restricting this to just a subset of projects for now + // since we only have a small pool of macOS agents + return testConfig.os.ignoredSubprojects.contains(subProject.name) +} + +fun gradleParameters(os: OS = OS.linux, daemon: Boolean = true, isContinue: Boolean = true): List = + listOf( + "-PmaxParallelForks=%maxParallelForks%", + "-s", + if (daemon) "--daemon" else "--no-daemon", + if (isContinue) "--continue" else "", + """-I "%teamcity.build.checkoutDir%/gradle/init-scripts/build-scan.init.gradle.kts"""", + java7Homes[os]!!, + java9Homes[os]!!, + "-Dorg.gradle.internal.tasks.createops", + "-Dorg.gradle.internal.plugins.portal.url.override=http://dev12.gradle.org:8081/artifactory/gradle-plugins/") + + +val m2CleanScriptUnixLike = """ + REPO=%teamcity.agent.jvm.user.home%/.m2/repository + if [ -e ${'$'}REPO ] ; then + tree ${'$'}REPO + rm -rf ${'$'}REPO + echo "${'$'}REPO was polluted during the build" + return 1 + else + echo "${'$'}REPO does not exist" + fi +""".trimIndent() + +val m2CleanScriptWindows = """ + IF exist %teamcity.agent.jvm.user.home%\.m2\repository ( + TREE %teamcity.agent.jvm.user.home%\.m2\repository + RMDIR /S /Q %teamcity.agent.jvm.user.home%\.m2\repository + EXIT 1 + ) +""".trimIndent() + +fun applyDefaultSettings(buildType: BuildType, os: OS = OS.linux, timeout: Int = 30, vcsRoot: String = "Gradle_Branches_GradlePersonalBranches") { + buildType.artifactRules = """ + build/report-* => . + buildSrc/build/report-* => . + subprojects/*/build/tmp/test files/** => test-files + build/errorLogs/** => errorLogs + build/reports/incubation/** => incubation-reports + """.trimIndent() + + buildType.vcs { + root(AbsoluteId(vcsRoot)) + checkoutMode = CheckoutMode.ON_AGENT + buildDefaultBranch = !vcsRoot.contains("Branches") + } + + buildType.requirements { + contains("teamcity.agent.jvm.os.name", os.agentRequirement) + } + + buildType.failureConditions { + executionTimeoutMin = timeout + } + + if (os == OS.linux || os == OS.macos) { + buildType.params { + param("env.LC_ALL", "en_US.UTF-8") + } + } +} + +fun BuildFeatures.publishBuildStatusToGithub() { + commitStatusPublisher { + vcsRootExtId = "Gradle_Branches_GradlePersonalBranches" + publisher = github { + githubUrl = "https://api.github.com" + authType = personalToken { + token = "credentialsJSON:5306bfc7-041e-46e8-8d61-1d49424e7b04" + } + } + } +} + +fun ProjectFeatures.buildReportTab(title: String, startPage: String) { + feature { + type = "ReportTab" + param("startPage", startPage) + param("title", title) + param("type", "BuildReportTab") + } +} + +fun applyDefaults(model: CIBuildModel, buildType: BaseGradleBuildType, gradleTasks: String, notQuick: Boolean = false, os: OS = OS.linux, extraParameters: String = "", timeout: Int = 90, extraSteps: BuildSteps.() -> Unit = {}, daemon: Boolean = true) { + applyDefaultSettings(buildType, os, timeout) + + val gradleParameterString = gradleParameters(os, daemon).joinToString(separator = " ") + + val buildScanTags = model.buildScanTags + listOfNotNull(buildType.stage?.id) + + buildType.steps { + gradleWrapper { + name = "CLEAN_BUILD_SRC" + tasks = "clean" + gradleParams = gradleParameterString + workingDir = "buildSrc" + gradleWrapperPath = ".." + buildFile = "build.gradle.kts" + } + gradleWrapper { + name = "GRADLE_RUNNER" + tasks = "clean $gradleTasks" + gradleParams = ( + listOf(gradleParameterString) + + buildType.buildCache.gradleParameters(os) + + listOf(extraParameters) + + "-PteamCityUsername=%teamcity.username.restbot%" + + "-PteamCityPassword=%teamcity.password.restbot%" + + "-PteamCityBuildId=%teamcity.build.id%" + + buildScanTags.map { buildScanTag(it) } + ).joinToString(separator = " ") + } + } + + buildType.steps.extraSteps() + + buildType.steps { + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = if (os == OS.windows) m2CleanScriptWindows else m2CleanScriptUnixLike + } + gradleWrapper { + name = "VERIFY_TEST_FILES_CLEANUP" + tasks = "verifyTestFilesCleanup" + gradleParams = gradleParameterString + } + if (os == OS.windows) { + gradleWrapper { + name = "KILL_PROCESSES_STARTED_BY_GRADLE" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "killExistingProcessesStartedByGradle" + gradleParams = gradleParameterString + } + } + if (model.tagBuilds) { + gradleWrapper { + name = "TAG_BUILD" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "tagBuild" + gradleParams = "$gradleParameterString -PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token%" + } + } + } + + applyDefaultDependencies(model, buildType, notQuick) +} + +fun buildScanTag(tag: String) = """"-Dscan.tag.$tag"""" +fun buildScanCustomValue(key: String, value: String) = """"-Dscan.value.$key=$value"""" + +fun applyDefaultDependencies(model: CIBuildModel, buildType: BuildType, notQuick: Boolean = false) { + if (notQuick) { + // wait for quick feedback phase to finish successfully + buildType.dependencies { + dependency(AbsoluteId("${model.projectPrefix}Stage_QuickFeedback_Trigger")) { + snapshot { + onDependencyFailure = FailureAction.CANCEL + onDependencyCancel = FailureAction.CANCEL + } + } + + } + } + + if (buildType !is CompileAll) { + buildType.dependencies { + val compileAllId = CompileAll.buildTypeId(model) + // Compile All has to succeed before anything else is started + dependency(AbsoluteId(compileAllId)) { + snapshot { + onDependencyFailure = FailureAction.CANCEL + onDependencyCancel = FailureAction.CANCEL + } + } + // Get the build receipt from sanity check to reuse the timestamp + artifacts(AbsoluteId(compileAllId)) { + id = "ARTIFACT_DEPENDENCY_$compileAllId" + cleanDestination = true + artifactRules = "build-receipt.properties => incoming-distributions" + } + } + } +} + +/** + * Adds a [Gradle build step](https://confluence.jetbrains.com/display/TCDL/Gradle) + * that runs with the Gradle wrapper. + * + * @see GradleBuildStep + */ +fun BuildSteps.gradleWrapper(init: GradleBuildStep.() -> Unit): GradleBuildStep = + customGradle(init) { + useGradleWrapper = true + if (buildFile == null) { + buildFile = "" // Let Gradle detect the build script + } + } + +fun BuildSteps.customGradle(init: GradleBuildStep.() -> Unit, custom: GradleBuildStep.() -> Unit): GradleBuildStep = + GradleBuildStep(init) + .apply(custom) + .also { step(it) } diff --git a/.teamcity/Gradle_Check/configurations/Gradleception.kt b/.teamcity/Gradle_Check/configurations/Gradleception.kt new file mode 100644 index 0000000000000..1792f45c32588 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/Gradleception.kt @@ -0,0 +1,42 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildSteps +import jetbrains.buildServer.configs.kotlin.v2018_1.buildSteps.GradleBuildStep +import model.CIBuildModel +import model.Stage + +class Gradleception(model: CIBuildModel, stage: Stage) : BaseGradleBuildType(model, stage = stage, init = { + uuid = "${model.projectPrefix}Gradleception" + id = AbsoluteId(uuid) + name = "Gradleception - Java8 Linux" + description = "Builds Gradle with the version of Gradle which is currently under development (twice)" + + params { + param("env.JAVA_HOME", buildJavaHome) + } + + val buildScanTagForType = buildScanTag("Gradleception") + val defaultParameters = (gradleParameters() + listOf(buildScanTagForType)).joinToString(separator = " ") + + applyDefaults(model, this, ":install", notQuick = true, extraParameters = "-Pgradle_installPath=dogfood-first $buildScanTagForType", extraSteps = { + localGradle { + name = "BUILD_WITH_BUILT_GRADLE" + tasks = "clean :install" + gradleHome = "%teamcity.build.checkoutDir%/dogfood-first" + gradleParams = "-Pgradle_installPath=dogfood-second -PignoreIncomingBuildReceipt=true $defaultParameters" + } + localGradle { + name = "QUICKCHECK_WITH_GRADLE_BUILT_BY_GRADLE" + tasks = "clean sanityCheck test" + gradleHome = "%teamcity.build.checkoutDir%/dogfood-second" + gradleParams = defaultParameters + } + }) +}) + +fun BuildSteps.localGradle(init: GradleBuildStep.() -> Unit): GradleBuildStep = + customGradle(init) { + param("ui.gradleRunner.gradle.wrapper.useWrapper", "false") + buildFile = "" + } diff --git a/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt new file mode 100644 index 0000000000000..e5513390e82ca --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/IndividualPerformanceScenarioWorkers.kt @@ -0,0 +1,57 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildStep +import jetbrains.buildServer.configs.kotlin.v2018_1.buildSteps.script +import model.CIBuildModel +import model.OS + +class IndividualPerformanceScenarioWorkers(model: CIBuildModel) : BaseGradleBuildType(model, init = { + uuid = model.projectPrefix + "IndividualPerformanceScenarioWorkersLinux" + id = AbsoluteId(uuid) + name = "Individual Performance Scenario Workers - Linux" + + applyDefaultSettings(this, timeout = 420) + artifactRules = """ + subprojects/*/build/test-results-*.zip => results + subprojects/*/build/tmp/**/log.txt => failure-logs + """.trimIndent() + + params { + param("baselines", "defaults") + param("channel", "commits") + param("checks", "all") + param("runs", "defaults") + param("warmups", "defaults") + param("templates", "") + param("scenario", "") + + param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") + param("performance.db.username", "tcagent") + + param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") + param("env.ANDROID_HOME", "/opt/android/sdk") + param("env.JAVA_HOME", buildJavaHome) + param("env.PATH", "%env.PATH%:/opt/swift/latest/usr/bin") + } + + steps { + gradleWrapper { + name = "GRADLE_RUNNER" + tasks = "" + gradleParams = ( + gradleParameters(daemon = false, isContinue = false) + + listOf("""clean %templates% fullPerformanceTests --scenarios "%scenario%" --baselines %baselines% --warmups %warmups% --runs %runs% --checks %checks% --channel %channel% -x prepareSamples -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -Porg.gradle.performance.db.password=%performance.db.password.tcagent% -PtimestampedVersion""", + buildScanTag("IndividualPerformanceScenarioWorkers"), "-PtestJavaHome=${individualPerformanceTestJavaHome}") + + model.parentBuildCache.gradleParameters(OS.linux) + ).joinToString(separator = " ") + } + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = m2CleanScriptUnixLike + } + } + + applyDefaultDependencies(model, this) +}) diff --git a/.teamcity/Gradle_Check/configurations/PerformanceTest.kt b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt new file mode 100644 index 0000000000000..ce781fbe69546 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/PerformanceTest.kt @@ -0,0 +1,64 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildStep +import jetbrains.buildServer.configs.kotlin.v2018_1.buildSteps.script +import model.CIBuildModel +import model.OS +import model.PerformanceTestType +import model.Stage + +class PerformanceTest(model: CIBuildModel, type: PerformanceTestType, stage: Stage) : BaseGradleBuildType(model, stage = stage, init = { + uuid = type.asId(model) + id = AbsoluteId(uuid) + name = "Performance ${type.name.capitalize()} Coordinator - Linux" + + applyDefaultSettings(this, timeout = type.timeout) + artifactRules = """ + build/report-*-performance-tests.zip => . + """.trimIndent() + detectHangingBuilds = false + + if (type == PerformanceTestType.test) { + features { + publishBuildStatusToGithub() + } + } + + params { + param("performance.baselines", type.defaultBaselines) + param("env.GRADLE_OPTS", "-Xmx1536m -XX:MaxPermSize=384m") + param("env.JAVA_HOME", buildJavaHome) + param("performance.db.url", "jdbc:h2:ssl://dev61.gradle.org:9092") + param("performance.db.username", "tcagent") + param("TC_USERNAME", "TeamcityRestBot") + } + + steps { + gradleWrapper { + name = "GRADLE_RUNNER" + tasks = "" + gradleParams = ( + gradleParameters(daemon = false) + + listOf("clean distributed${type.taskId}s -x prepareSamples --baselines %performance.baselines% ${type.extraParameters} -PtimestampedVersion -Porg.gradle.performance.branchName=%teamcity.build.branch% -Porg.gradle.performance.db.url=%performance.db.url% -Porg.gradle.performance.db.username=%performance.db.username% -PteamCityUsername=%TC_USERNAME% -PteamCityPassword=%teamcity.password.restbot% -Porg.gradle.performance.buildTypeId=${IndividualPerformanceScenarioWorkers(model).id} -Porg.gradle.performance.workerTestTaskName=fullPerformanceTest -Porg.gradle.performance.coordinatorBuildId=%teamcity.build.id% -Porg.gradle.performance.db.password=%performance.db.password.tcagent%", + buildScanTag("PerformanceTest"), "-PtestJavaHome=${coordinatorPerformanceTestJavaHome}") + + model.parentBuildCache.gradleParameters(OS.linux) + ).joinToString(separator = " ") + } + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = m2CleanScriptUnixLike + } + if (model.tagBuilds) { + gradleWrapper { + name = "TAG_BUILD" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "tagBuild" + gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token% -Djava7Home=%linux.jdk.for.gradle.compile%" + } + } + } + + applyDefaultDependencies(model, this, true) +}) diff --git a/.teamcity/Gradle_Check/configurations/SanityCheck.kt b/.teamcity/Gradle_Check/configurations/SanityCheck.kt new file mode 100644 index 0000000000000..2e286c50dda0b --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/SanityCheck.kt @@ -0,0 +1,34 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import model.CIBuildModel +import model.Stage + +class SanityCheck(model: CIBuildModel, stage: Stage) : BaseGradleBuildType(model, stage = stage, usesParentBuildCache = true, init = { + uuid = buildTypeId(model) + id = AbsoluteId(uuid) + name = "Sanity Check" + description = "Static code analysis, checkstyle, release notes verification, etc." + + params { + param("system.java9Home", "%linux.java9.oracle.64bit%") + param("env.JAVA_HOME", buildJavaHome) + } + + if (model.publishStatusToGitHub) { + features { + publishBuildStatusToGithub() + } + } + + applyDefaults( + model, + this, + "sanityCheck", + extraParameters = "-DenableCodeQuality=true ${buildScanTag("SanityCheck")}" + ) +}) { + companion object { + fun buildTypeId(model: CIBuildModel) = "${model.projectPrefix}SanityCheck" + } +} diff --git a/.teamcity/Gradle_Check/configurations/SmokeTests.kt b/.teamcity/Gradle_Check/configurations/SmokeTests.kt new file mode 100644 index 0000000000000..7621acaa07fb9 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/SmokeTests.kt @@ -0,0 +1,25 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import model.CIBuildModel +import model.Stage + +class SmokeTests(model: CIBuildModel, stage: Stage) : BaseGradleBuildType(model, stage = stage, init = { + uuid = "${model.projectPrefix}SmokeTests" + id = AbsoluteId(uuid) + name = "Smoke Tests with 3rd Party Plugins - Java8 Linux" + description = "Smoke tests against third party plugins to see if they still work with the current Gradle version" + + params { + param("env.ANDROID_HOME", "/opt/android/sdk") + param("env.JAVA_HOME", buildJavaHome) + } + + applyDefaults( + model, + this, + "smokeTest:smokeTest", + notQuick = true, + extraParameters = buildScanTag("SmokeTests") + " -PtestJavaHome=${smokeTestJavaHome}" + ) +}) diff --git a/.teamcity/Gradle_Check/configurations/StagePasses.kt b/.teamcity/Gradle_Check/configurations/StagePasses.kt new file mode 100644 index 0000000000000..843543380ea52 --- /dev/null +++ b/.teamcity/Gradle_Check/configurations/StagePasses.kt @@ -0,0 +1,155 @@ +package configurations + +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildStep +import jetbrains.buildServer.configs.kotlin.v2018_1.FailureAction +import jetbrains.buildServer.configs.kotlin.v2018_1.buildSteps.script +import jetbrains.buildServer.configs.kotlin.v2018_1.triggers.ScheduleTrigger +import jetbrains.buildServer.configs.kotlin.v2018_1.triggers.VcsTrigger +import jetbrains.buildServer.configs.kotlin.v2018_1.triggers.schedule +import jetbrains.buildServer.configs.kotlin.v2018_1.triggers.vcs +import model.CIBuildModel +import model.Stage +import model.TestType +import model.Trigger +import projects.FunctionalTestProject + +class StagePasses(model: CIBuildModel, stage: Stage, prevStage: Stage?, containsDeferredTests: Boolean, rootProjectUuid: String) : BaseGradleBuildType(model, init = { + uuid = stageTriggerUuid(model, stage) + id = stageTriggerId(model, stage) + name = stage.stageName.stageName + " (Trigger)" + + applyDefaultSettings(this) + artifactRules = "build/build-receipt.properties" + + val triggerExcludes = """ + -:design-docs + -:subprojects/docs/src/docs/release + """.trimIndent() + val masterReleaseFiler = model.masterAndReleaseBranches.joinToString(prefix = "+:", separator = "\n+:") + + if (model.publishStatusToGitHub) { + features { + publishBuildStatusToGithub() + } + } + + if (stage.trigger == Trigger.eachCommit) { + triggers.vcs { + quietPeriodMode = VcsTrigger.QuietPeriodMode.USE_CUSTOM + quietPeriod = 90 + triggerRules = triggerExcludes + branchFilter = masterReleaseFiler + } + } else if (stage.trigger != Trigger.never) { + triggers.schedule { + if (stage.trigger == Trigger.weekly) { + schedulingPolicy = weekly { + dayOfWeek = ScheduleTrigger.DAY.Saturday + hour = 1 + } + } else { + schedulingPolicy = daily { + hour = 0 + minute = 30 + } + } + triggerBuild = always() + withPendingChangesOnly = true + param("revisionRule", "lastFinished") + param("branchFilter", masterReleaseFiler) + } + + } + + params { + param("env.JAVA_HOME", buildJavaHome) + } + + steps { + gradleWrapper { + name = "GRADLE_RUNNER" + tasks = "createBuildReceipt" + gradleParams = "-PtimestampedVersion -Djava7Home=%linux.jdk.for.gradle.compile% -Djava9Home=%linux.java9.oracle.64bit% --daemon" + } + script { + name = "CHECK_CLEAN_M2" + executionMode = BuildStep.ExecutionMode.ALWAYS + scriptContent = m2CleanScriptUnixLike + } + if (model.tagBuilds) { + gradleWrapper { + name = "TAG_BUILD" + executionMode = BuildStep.ExecutionMode.ALWAYS + tasks = "tagBuild" + gradleParams = "-PteamCityUsername=%teamcity.username.restbot% -PteamCityPassword=%teamcity.password.restbot% -PteamCityBuildId=%teamcity.build.id% -PgithubToken=%github.ci.oauth.token% ${buildScanTag("StagePasses")}" + } + } + } + + dependencies { + if (!stage.runsIndependent && prevStage != null) { + dependency(stageTriggerId(model, prevStage)) { + snapshot { + onDependencyFailure = FailureAction.ADD_PROBLEM + } + } + } + + stage.specificBuilds.forEach { + dependency(it.create(model, stage)) { + snapshot {} + } + } + + stage.performanceTests.forEach { performanceTest -> + dependency(AbsoluteId(performanceTest.asId(model))) { + snapshot {} + } + } + + stage.functionalTests.forEach { testCoverage -> + val isSplitIntoBuckets = testCoverage.testType != TestType.soak + if (isSplitIntoBuckets) { + model.subProjects.forEach { subProject -> + if (shouldBeSkipped(subProject, testCoverage)) { + return@forEach + } + if (subProject.containsSlowTests && stage.omitsSlowProjects) { + return@forEach + } + if (subProject.unitTests && testCoverage.testType.unitTests) { + dependency(AbsoluteId(testCoverage.asConfigurationId(model, subProject.name))) { snapshot {} } + } else if (subProject.functionalTests && testCoverage.testType.functionalTests) { + dependency(AbsoluteId(testCoverage.asConfigurationId(model, subProject.name))) { snapshot {} } + } else if (subProject.crossVersionTests && testCoverage.testType.crossVersionTests) { + dependency(AbsoluteId(testCoverage.asConfigurationId(model, subProject.name))) { snapshot {} } + } + } + } else { + dependency(AbsoluteId(testCoverage.asConfigurationId(model))) { + snapshot {} + } + } + } + + if (containsDeferredTests) { + model.subProjects.forEach { subProject -> + if (subProject.containsSlowTests) { + FunctionalTestProject.missingTestCoverage.forEach { testConfig -> + if (subProject.unitTests && testConfig.testType.unitTests) { + dependency(AbsoluteId(testConfig.asConfigurationId(model, subProject.name))) { snapshot {} } + } else if (subProject.functionalTests && testConfig.testType.functionalTests) { + dependency(AbsoluteId(testConfig.asConfigurationId(model, subProject.name))) { snapshot {} } + } else if (subProject.crossVersionTests && testConfig.testType.crossVersionTests) { + dependency(AbsoluteId(testConfig.asConfigurationId(model, subProject.name))) { snapshot {} } + } + } + } + } + } + } +}) + +fun stageTriggerUuid(model: CIBuildModel, stage: Stage) = "${model.projectPrefix}Stage_${stage.stageName.uuid}_Trigger" +fun stageTriggerId(model: CIBuildModel, stage: Stage) = AbsoluteId("${model.projectPrefix}Stage_${stage.stageName.id}_Trigger") diff --git a/.teamcity/Gradle_Check/model/CIBuildModel.kt b/.teamcity/Gradle_Check/model/CIBuildModel.kt new file mode 100644 index 0000000000000..ed85bfb8b05c6 --- /dev/null +++ b/.teamcity/Gradle_Check/model/CIBuildModel.kt @@ -0,0 +1,329 @@ +package model + +import configurations.BuildDistributions +import configurations.CompileAll +import configurations.DependenciesCheck +import configurations.Gradleception +import configurations.SanityCheck +import configurations.SmokeTests +import jetbrains.buildServer.configs.kotlin.v2018_1.BuildType + + +enum class StageNames(override val stageName: String, override val description: String, override val uuid: String) : StageName{ + QUICK_FEEDBACK_LINUX_ONLY("Quick Feedback - Linux Only", "Run checks and functional tests (embedded executer, Linux)", "QuickFeedbackLinuxOnly"), + QUICK_FEEDBACK("Quick Feedback", "Run checks and functional tests (embedded executer, Windows)", "QuickFeedback"), + READY_FOR_MERGE("Ready for Merge", "Run performance and functional tests (against distribution)", "BranchBuildAccept"), + READY_FOR_NIGHTLY("Ready for Nightly", "Rerun tests in different environments / 3rd party components", "MasterAccept"), + READY_FOR_RELEASE("Ready for Release", "Once a day: Rerun tests in more environments", "ReleaseAccept"), + HISTORICAL_PERFORMANCE("Historical Performance", "Once a week: Run performance tests for multiple Gradle versions", "HistoricalPerformance"), + EXPERIMENTAL("Experimental", "On demand: Run experimental tests", "Experimental"), +} + + +data class CIBuildModel ( + val projectPrefix: String = "Gradle_Check_", + val rootProjectName: String = "Check", + val tagBuilds: Boolean = true, + val publishStatusToGitHub: Boolean = true, + val masterAndReleaseBranches: List = listOf("master", "release"), + val parentBuildCache: BuildCache = RemoteBuildCache("%gradle.cache.remote.url%"), + val childBuildCache: BuildCache = RemoteBuildCache("%gradle.cache.remote.url%"), + val buildScanTags: List = emptyList(), + val stages: List = listOf( + Stage(StageNames.QUICK_FEEDBACK_LINUX_ONLY, + specificBuilds = listOf( + SpecificBuild.CompileAll, SpecificBuild.SanityCheck), + functionalTests = listOf( + TestCoverage(TestType.quick, OS.linux, JvmVersion.java11, vendor = JvmVendor.openjdk)), omitsSlowProjects = true), + Stage(StageNames.QUICK_FEEDBACK, + functionalTests = listOf( + TestCoverage(TestType.quick, OS.windows, JvmVersion.java8)), + functionalTestsDependOnSpecificBuilds = true, + omitsSlowProjects = true, + dependsOnSanityCheck = true), + Stage(StageNames.READY_FOR_MERGE, + specificBuilds = listOf( + SpecificBuild.BuildDistributions, + SpecificBuild.Gradleception, + SpecificBuild.SmokeTests), + functionalTests = listOf( + TestCoverage(TestType.platform, OS.linux, JvmVersion.java8), + TestCoverage(TestType.platform, OS.windows, JvmVersion.java11, vendor = JvmVendor.openjdk)), + performanceTests = listOf(PerformanceTestType.test), + omitsSlowProjects = true), + Stage(StageNames.READY_FOR_NIGHTLY, + trigger = Trigger.eachCommit, + functionalTests = listOf( + TestCoverage(TestType.quickFeedbackCrossVersion, OS.linux, JvmVersion.java8), + TestCoverage(TestType.quickFeedbackCrossVersion, OS.windows, JvmVersion.java8), + TestCoverage(TestType.parallel, OS.linux, JvmVersion.java11, vendor = JvmVendor.openjdk)) + ), + Stage(StageNames.READY_FOR_RELEASE, + trigger = Trigger.daily, + functionalTests = listOf( + TestCoverage(TestType.soak, OS.linux, JvmVersion.java11, vendor = JvmVendor.openjdk), + TestCoverage(TestType.soak, OS.windows, JvmVersion.java8), + TestCoverage(TestType.allVersionsCrossVersion, OS.linux, JvmVersion.java8), + TestCoverage(TestType.allVersionsCrossVersion, OS.windows, JvmVersion.java8), + TestCoverage(TestType.noDaemon, OS.linux, JvmVersion.java8), + TestCoverage(TestType.noDaemon, OS.windows, JvmVersion.java11, vendor = JvmVendor.openjdk), + TestCoverage(TestType.platform, OS.macos, JvmVersion.java8), + TestCoverage(TestType.forceRealizeDependencyManagement, OS.linux, JvmVersion.java8)), + performanceTests = listOf( + PerformanceTestType.experiment)), + Stage(StageNames.HISTORICAL_PERFORMANCE, + trigger = Trigger.weekly, + performanceTests = listOf( + PerformanceTestType.historical)), + Stage(StageNames.EXPERIMENTAL, + trigger = Trigger.never, + runsIndependent = true, + functionalTests = listOf( + TestCoverage(TestType.platform, OS.linux, JvmVersion.java12, vendor = JvmVendor.openjdk), + TestCoverage(TestType.platform, OS.windows, JvmVersion.java12, vendor = JvmVendor.openjdk)) + ) + ), + val subProjects : List = listOf( + GradleSubproject("announce"), + GradleSubproject("antlr"), + GradleSubproject("baseServices"), + GradleSubproject("baseServicesGroovy", functionalTests = false), + GradleSubproject("buildCache"), + GradleSubproject("buildCacheHttp"), + GradleSubproject("buildCachePackaging"), + GradleSubproject("buildComparison"), + GradleSubproject("buildProfile"), + GradleSubproject("buildOption"), + GradleSubproject("buildInit"), + GradleSubproject("cli", functionalTests = false), + GradleSubproject("codeQuality"), + GradleSubproject("compositeBuilds"), + GradleSubproject("core", crossVersionTests = true), + GradleSubproject("coreApi", functionalTests = false), + GradleSubproject("dependencyManagement", crossVersionTests = true), + GradleSubproject("diagnostics"), + GradleSubproject("ear"), + GradleSubproject("execution"), + GradleSubproject("files"), + GradleSubproject("ide", crossVersionTests = true), + GradleSubproject("ideNative"), + GradleSubproject("idePlay"), + GradleSubproject("integTest", crossVersionTests = true), + GradleSubproject("internalIntegTesting"), + GradleSubproject("internalPerformanceTesting"), + GradleSubproject("internalTesting", functionalTests = false), + GradleSubproject("ivy", crossVersionTests = true), + GradleSubproject("jacoco"), + GradleSubproject("javascript"), + GradleSubproject("jvmServices", functionalTests = false), + GradleSubproject("languageGroovy"), + GradleSubproject("languageJava", crossVersionTests = true), + GradleSubproject("languageJvm"), + GradleSubproject("languageNative"), + GradleSubproject("languageScala"), + GradleSubproject("launcher"), + GradleSubproject("logging"), + GradleSubproject("maven", crossVersionTests = true), + GradleSubproject("messaging"), + GradleSubproject("modelCore"), + GradleSubproject("modelGroovy"), + GradleSubproject("native"), + GradleSubproject("osgi"), + GradleSubproject("persistentCache"), + GradleSubproject("platformBase"), + GradleSubproject("platformJvm"), + GradleSubproject("platformNative"), + GradleSubproject("platformPlay", containsSlowTests = true), + GradleSubproject("pluginDevelopment"), + GradleSubproject("pluginUse", crossVersionTests = true), + GradleSubproject("plugins"), + GradleSubproject("processServices"), + GradleSubproject("publish"), + GradleSubproject("reporting"), + GradleSubproject("resources"), + GradleSubproject("resourcesGcs"), + GradleSubproject("resourcesHttp"), + GradleSubproject("resourcesS3"), + GradleSubproject("resourcesSftp"), + GradleSubproject("scala"), + GradleSubproject("signing"), + GradleSubproject("snapshots"), + GradleSubproject("testKit"), + GradleSubproject("testingBase"), + GradleSubproject("testingJvm"), + GradleSubproject("testingJunitPlatform"), + GradleSubproject("testingNative"), + GradleSubproject("toolingApi", crossVersionTests = true, useDaemon = false), + GradleSubproject("toolingApiBuilders", functionalTests = false), + GradleSubproject("toolingNative", unitTests = false, functionalTests = false, crossVersionTests = true), + GradleSubproject("versionControl"), + GradleSubproject("workers"), + GradleSubproject("wrapper", crossVersionTests = true, useDaemon = false), + + GradleSubproject("soak", unitTests = false, functionalTests = false), + + GradleSubproject("apiMetadata", unitTests = false, functionalTests = false), + GradleSubproject("architectureTest", unitTests = false, functionalTests = false), + GradleSubproject("distributionsDependencies", unitTests = false, functionalTests = false), + GradleSubproject("buildScanPerformance", unitTests = false, functionalTests = false), + GradleSubproject("distributions", unitTests = false, functionalTests = false), + GradleSubproject("docs", unitTests = false, functionalTests = false), + GradleSubproject("installationBeacon", unitTests = false, functionalTests = false), + GradleSubproject("internalAndroidPerformanceTesting", unitTests = false, functionalTests = false), + GradleSubproject("performance", unitTests = false, functionalTests = false), + GradleSubproject("runtimeApiInfo", unitTests = false, functionalTests = false), + GradleSubproject("smokeTest", unitTests = false, functionalTests = false)) + ) + +data class GradleSubproject(val name: String, val unitTests: Boolean = true, val functionalTests: Boolean = true, val crossVersionTests: Boolean = false, val containsSlowTests: Boolean = false, val useDaemon: Boolean = true) { + fun asDirectoryName(): String { + return name.replace(Regex("([A-Z])"), { "-" + it.groups[1]!!.value.toLowerCase() }) + } + + fun hasTestsOf(type: TestType) = (unitTests && type.unitTests) || (functionalTests && type.functionalTests) || (crossVersionTests && type.crossVersionTests) + + fun useDaemonFor(type: TestType) = useDaemon && type != TestType.noDaemon +} + +interface BuildCache { + fun gradleParameters(os: OS): List +} + +data class RemoteBuildCache(val url: String, val username: String = "%gradle.cache.remote.username%", val password: String = "%gradle.cache.remote.password%") : BuildCache { + override fun gradleParameters(os: OS): List { + return listOf("--build-cache", + os.escapeKeyValuePair("-Dgradle.cache.remote.url", url), + os.escapeKeyValuePair("-Dgradle.cache.remote.username", username), + os.escapeKeyValuePair("-Dgradle.cache.remote.password", password) + ) + } +} + +private +fun OS.escapeKeyValuePair(key: String, value: String) = if (this == OS.windows) """$key="$value"""" else """"$key=$value"""" + +object NoBuildCache : BuildCache { + override fun gradleParameters(os: OS): List { + return emptyList() + } +} + +interface StageName { + val stageName: String + val description: String + val uuid: String + get() = id + val id: String + get() = stageName.replace(" ", "").replace("-", "") +} + +data class Stage(val stageName: StageName, val specificBuilds: List = emptyList(), val performanceTests: List = emptyList(), val functionalTests: List = emptyList(), val trigger: Trigger = Trigger.never, val functionalTestsDependOnSpecificBuilds: Boolean = false, val runsIndependent: Boolean = false, val omitsSlowProjects : Boolean = false, val dependsOnSanityCheck: Boolean = false) { + val id = stageName.id +} + +data class TestCoverage(val testType: TestType, val os: OS, val testJvmVersion: JvmVersion, val vendor: JvmVendor = JvmVendor.oracle, val buildJvmVersion: JvmVersion = JvmVersion.java9) { + fun asId(model : CIBuildModel): String { + return "${model.projectPrefix}$testCoveragePrefix" + } + + private + val testCoveragePrefix + get() = "${testType.name.capitalize()}_${testJvmVersion.name.capitalize()}_${vendor.name.capitalize()}_${os.name.capitalize()}" + + fun asConfigurationId(model : CIBuildModel, subproject: String = ""): String { + val prefix = "${testCoveragePrefix}_" + val shortenedSubprojectName = shortenSubprojectName(model.projectPrefix, prefix + subproject) + return model.projectPrefix + if (!subproject.isEmpty()) shortenedSubprojectName else "${prefix}0" + } + + private + fun shortenSubprojectName(prefix: String, subprojectName: String): String { + val shortenedSubprojectName = subprojectName.replace("internal", "i").replace("Testing", "T") + if (shortenedSubprojectName.length + prefix.length <= 80) { + return shortenedSubprojectName + } + return shortenedSubprojectName.replace(Regex("[aeiou]"), "") + } + + fun asName(): String { + return "Test Coverage - ${testType.name.capitalize()} ${testJvmVersion.name.capitalize()} ${vendor.name.capitalize()} ${os.name.capitalize()}" + } +} + +enum class OS(val agentRequirement: String, val ignoredSubprojects: List = emptyList()) { + linux("Linux"), windows("Windows"), macos("Mac", listOf("integTest", "native", "plugins", "resources", "scala", "workers", "wrapper", "platformPlay")) +} + +enum class JvmVersion { + java8, java9, java10, java11, java12 +} + +enum class TestType(val unitTests: Boolean = true, val functionalTests: Boolean = true, val crossVersionTests: Boolean = false, val timeout: Int = 180) { + // Include cross version tests, these take care of selecting a very small set of versions to cover when run as part of this stage, including the current version + quick(true, true, true, 60), + // Include cross version tests, these take care of selecting a very small set of versions to cover when run as part of this stage, including the current version + platform(true, true, true), + // Cross version tests select a small set of versions to cover when run as part of this stage + quickFeedbackCrossVersion(false, false, true), + // Cross version tests select all versions to cover when run as part of this stage + allVersionsCrossVersion(false, true, true, 240), + parallel(false, true, false), + noDaemon(false, true, false, 240), + soak(false, false, false), + forceRealizeDependencyManagement(false, true, false) +} + +enum class JvmVendor { + oracle, ibm, openjdk +} + +enum class PerformanceTestType(val taskId: String, val timeout : Int, val defaultBaselines: String = "", val extraParameters : String = "") { + test("PerformanceTest", 420, "defaults"), + experiment("PerformanceExperiment", 420, "defaults"), + historical("FullPerformanceTest", 2280, "2.14.1,3.5.1,4.0,last", "--checks none"); + + fun asId(model : CIBuildModel): String { + return "${model.projectPrefix}Performance${name.capitalize()}Coordinator" + } +} + +enum class Trigger { + never, eachCommit, daily, weekly +} + +enum class SpecificBuild { + CompileAll { + override fun create(model: CIBuildModel, stage: Stage): BuildType { + return CompileAll(model, stage) + } + }, + SanityCheck { + override fun create(model: CIBuildModel, stage: Stage): BuildType { + return SanityCheck(model, stage) + } + }, + BuildDistributions { + override fun create(model: CIBuildModel, stage: Stage): BuildType { + return BuildDistributions(model, stage) + } + + }, + Gradleception { + override fun create(model: CIBuildModel, stage: Stage): BuildType { + return Gradleception(model, stage) + } + + }, + SmokeTests { + override fun create(model: CIBuildModel, stage: Stage): BuildType { + return SmokeTests(model, stage) + } + }, + DependenciesCheck { + override fun create(model: CIBuildModel, stage: Stage): BuildType { + return DependenciesCheck(model, stage) + } + }; + + abstract fun create(model: CIBuildModel, stage: Stage): BuildType +} diff --git a/.teamcity/Gradle_Check/pluginData/plugin-settings.xml b/.teamcity/Gradle_Check/pluginData/plugin-settings.xml new file mode 100644 index 0000000000000..8400423b31013 --- /dev/null +++ b/.teamcity/Gradle_Check/pluginData/plugin-settings.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Check/projects/FunctionalTestProject.kt b/.teamcity/Gradle_Check/projects/FunctionalTestProject.kt new file mode 100644 index 0000000000000..35a8f85ca4eaa --- /dev/null +++ b/.teamcity/Gradle_Check/projects/FunctionalTestProject.kt @@ -0,0 +1,37 @@ +package projects + +import configurations.FunctionalTest +import configurations.shouldBeSkipped +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.Project +import model.CIBuildModel +import model.Stage +import model.TestCoverage + +class FunctionalTestProject(model: CIBuildModel, testConfig: TestCoverage, stage: Stage) : Project({ + this.uuid = testConfig.asId(model) + this.id = AbsoluteId(uuid) + this.name = testConfig.asName() + + model.subProjects.forEach { subProject -> + if (shouldBeSkipped(subProject, testConfig)) { + return@forEach + } + if (subProject.containsSlowTests && stage.omitsSlowProjects) { + addMissingTestCoverage(testConfig) + return@forEach + } + + if (subProject.hasTestsOf(testConfig.testType)) { + buildType(FunctionalTest(model, testConfig, subProject.name, subProject.useDaemonFor(testConfig.testType), stage)) + } + } +}){ + companion object { + val missingTestCoverage = mutableListOf() + + private fun addMissingTestCoverage(coverage: TestCoverage) { + this.missingTestCoverage.add(coverage) + } + } +} diff --git a/.teamcity/Gradle_Check/projects/RootProject.kt b/.teamcity/Gradle_Check/projects/RootProject.kt new file mode 100644 index 0000000000000..3b4cca30cd54f --- /dev/null +++ b/.teamcity/Gradle_Check/projects/RootProject.kt @@ -0,0 +1,45 @@ +package projects + +import configurations.StagePasses +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.Project +import jetbrains.buildServer.configs.kotlin.v2018_1.projectFeatures.VersionedSettings +import jetbrains.buildServer.configs.kotlin.v2018_1.projectFeatures.versionedSettings +import model.CIBuildModel +import model.Stage + +class RootProject(model: CIBuildModel) : Project({ + uuid = model.projectPrefix.removeSuffix("_") + id = AbsoluteId(uuid) + parentId = AbsoluteId("Gradle") + name = model.rootProjectName + + features { + versionedSettings { + id = "PROJECT_EXT_3" + mode = VersionedSettings.Mode.ENABLED + buildSettingsMode = VersionedSettings.BuildSettingsMode.PREFER_CURRENT_SETTINGS + rootExtId = "Gradle_Branches_VersionedSettings" + showChanges = false + settingsFormat = VersionedSettings.Format.KOTLIN + param("credentialsStorageType", "credentialsJSON") + } + } + + var prevStage: Stage? = null + var deferredAlreadyDeclared = false + model.stages.forEach { stage -> + val containsDeferredTests = !stage.omitsSlowProjects && !deferredAlreadyDeclared + deferredAlreadyDeclared = deferredAlreadyDeclared || containsDeferredTests + buildType(StagePasses(model, stage, prevStage, containsDeferredTests, uuid)) + subProject(StageProject(model, stage, containsDeferredTests, uuid)) + prevStage = stage + } + + if (model.stages.map { stage -> stage.performanceTests }.flatten().isNotEmpty()) { + subProject(WorkersProject(model)) + } + + buildTypesOrder = buildTypes + subProjectsOrder = subProjects +}) diff --git a/.teamcity/Gradle_Check/projects/StageProject.kt b/.teamcity/Gradle_Check/projects/StageProject.kt new file mode 100644 index 0000000000000..fb5ac7ce8ba3c --- /dev/null +++ b/.teamcity/Gradle_Check/projects/StageProject.kt @@ -0,0 +1,92 @@ +package projects + +import configurations.FunctionalTest +import configurations.PerformanceTest +import configurations.SanityCheck +import configurations.buildReportTab +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.FailureAction +import jetbrains.buildServer.configs.kotlin.v2018_1.IdOwner +import jetbrains.buildServer.configs.kotlin.v2018_1.Project +import model.CIBuildModel +import model.GradleSubproject +import model.SpecificBuild +import model.Stage +import model.TestType + +class StageProject(model: CIBuildModel, stage: Stage, containsDeferredTests: Boolean, rootProjectUuid: String) : Project({ + this.uuid = "${model.projectPrefix}Stage_${stage.stageName.uuid}" + this.id = AbsoluteId("${model.projectPrefix}Stage_${stage.stageName.id}") + this.name = stage.stageName.stageName + this.description = stage.stageName.description + + features { + if (stage.specificBuilds.contains(SpecificBuild.SanityCheck)) { + buildReportTab("API Compatibility Report", "report-distributions-binary-compatibility-report.html") + buildReportTab("Incubating APIs Report", "incubation-reports/all-incubating.html") + } + if (!stage.performanceTests.isEmpty()) { + buildReportTab("Performance", "report-performance-performance-tests.zip!report/index.html") + } + } + + val specificBuildTypes = stage.specificBuilds.map { + it.create(model, stage) + } + specificBuildTypes.forEach { buildType(it) } + + stage.performanceTests.forEach { + buildType(PerformanceTest(model, it, stage)) + } + + stage.functionalTests.forEach { testCoverage -> + val isSplitIntoBuckets = testCoverage.testType != TestType.soak + if (isSplitIntoBuckets) { + val functionalTests = FunctionalTestProject(model, testCoverage, stage) + subProject(functionalTests) + if (stage.functionalTestsDependOnSpecificBuilds) { + specificBuildTypes.forEach { specificBuildType -> + functionalTests.addDependencyForAllBuildTypes(specificBuildType) + } + } + if (!(stage.functionalTestsDependOnSpecificBuilds && stage.specificBuilds.contains(SpecificBuild.SanityCheck)) && stage.dependsOnSanityCheck) { + functionalTests.addDependencyForAllBuildTypes(AbsoluteId(SanityCheck.buildTypeId(model))) + } + } else { + buildType(FunctionalTest(model, testCoverage, stage = stage)) + } + } + + if (containsDeferredTests) { + val deferredTestsProject = Project { + uuid = "${rootProjectUuid}_deferred_tests" + id = AbsoluteId(uuid) + name = "Test coverage deferred from Quick Feedback and Ready for Merge" + model.subProjects + .filter(GradleSubproject::containsSlowTests) + .forEach { subProject -> + FunctionalTestProject.missingTestCoverage + .filter { testConfig -> + subProject.hasTestsOf(testConfig.testType) + } + .forEach { testConfig -> + buildType(FunctionalTest(model, testConfig, subProject.name, subProject.useDaemonFor(testConfig.testType), stage)) + } + } + } + subProject(deferredTestsProject) + } +}) + +private fun Project.addDependencyForAllBuildTypes(dependency: IdOwner) { + buildTypes.forEach { functionalTestBuildType -> + functionalTestBuildType.dependencies { + dependency(dependency) { + snapshot { + onDependencyFailure = FailureAction.CANCEL + onDependencyCancel = FailureAction.CANCEL + } + } + } + } +} diff --git a/.teamcity/Gradle_Check/projects/WorkersProject.kt b/.teamcity/Gradle_Check/projects/WorkersProject.kt new file mode 100644 index 0000000000000..8bee9927bc3df --- /dev/null +++ b/.teamcity/Gradle_Check/projects/WorkersProject.kt @@ -0,0 +1,14 @@ +package projects + +import configurations.IndividualPerformanceScenarioWorkers +import jetbrains.buildServer.configs.kotlin.v2018_1.AbsoluteId +import jetbrains.buildServer.configs.kotlin.v2018_1.Project +import model.CIBuildModel + +class WorkersProject(model: CIBuildModel) : Project({ + this.uuid = model.projectPrefix + "Workers" + this.id = AbsoluteId(uuid) + this.name = "Workers" + + buildType(IndividualPerformanceScenarioWorkers(model)) +}) diff --git a/.teamcity/Gradle_Check/settings.kts b/.teamcity/Gradle_Check/settings.kts new file mode 100644 index 0000000000000..c53c819db10b0 --- /dev/null +++ b/.teamcity/Gradle_Check/settings.kts @@ -0,0 +1,29 @@ +package Gradle_Check + +import jetbrains.buildServer.configs.kotlin.v2018_1.project +import jetbrains.buildServer.configs.kotlin.v2018_1.version +import model.CIBuildModel +import projects.RootProject + +/* +The settings script is an entry point for defining a single +TeamCity project. TeamCity looks for the 'settings.kts' file in a +project directory and runs it if it's found, so the script name +shouldn't be changed and its package should be the same as the +project's external id. + +The script should contain a single call to the project() function +with a Project instance or an init function as an argument, you +can also specify both of them to refine the specified Project in +the init function. + +VcsRoots, BuildTypes, and Templates of this project must be +registered inside project using the vcsRoot(), buildType(), and +template() methods respectively. + +Subprojects can be defined either in their own settings.kts or by +calling the subProjects() method in this project. +*/ + +version = "2018.1" +project(RootProject(CIBuildModel(buildScanTags = listOf("Check")))) diff --git a/.teamcity/Gradle_Check_dsl.iml b/.teamcity/Gradle_Check_dsl.iml new file mode 100644 index 0000000000000..5ac25c89f3a58 --- /dev/null +++ b/.teamcity/Gradle_Check_dsl.iml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.xml new file mode 100644 index 0000000000000..886e228eeeef9 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_FinalRelease.xml @@ -0,0 +1,45 @@ + + + Release - Final + Promotes the latest successful change on 'release' as a new release + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.xml new file mode 100644 index 0000000000000..8a204857322c0 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterNightlySnapshotManual.xml @@ -0,0 +1,43 @@ + + + Master - Nightly Snapshot (from Quick Feedback) + Promotes the latest change on 'master' that passed the 'Quick Feedback' stage as new nightly. This build configuration can be triggered manually if there are issues further down the pipeline we can ignore temporarily. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.xml new file mode 100644 index 0000000000000..00f4bca9602d1 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MasterSanityCheck.xml @@ -0,0 +1,45 @@ + + + Master - Sanity Check + Compilation and test execution of buildSrc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.xml new file mode 100644 index 0000000000000..b7ccdb45f510e --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_MilestoneMaster.xml @@ -0,0 +1,46 @@ + + + Release - Milestone + Promotes the latest successful change on 'release' as the new snapshot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml new file mode 100644 index 0000000000000..46d53988599a2 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_PublishBranchSnapshotFromQuickFeedback.xml @@ -0,0 +1,40 @@ + + + Publish Branch Snapshot (from Quick Feedback) + Deploys a new wrapper for the selected build/branch. Does not update master or the documentation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.xml new file mode 100644 index 0000000000000..e935d3c5c7ef7 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_ReleaseSnapshotFromQuickFeedback.xml @@ -0,0 +1,41 @@ + + + Release - Release Nightly Snapshot (from Quick Feedback) + Deploys the latest successful change on 'release' as a new release nightly snapshot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.xml b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.xml new file mode 100644 index 0000000000000..9918d04c6d204 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/Gradle_Promotion_StartReleaseCycle.xml @@ -0,0 +1,45 @@ + + + Master - Start Release Cycle + Promotes a successful build on master as the start of a new release cycle on the release branch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt39.xml b/.teamcity/Gradle_Promotion/buildTypes/bt39.xml new file mode 100644 index 0000000000000..6f1108a583592 --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/bt39.xml @@ -0,0 +1,59 @@ + + + Master - Nightly Snapshot + Promotes the latest successful change on 'master' as the new nightly + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt60.xml b/.teamcity/Gradle_Promotion/buildTypes/bt60.xml new file mode 100644 index 0000000000000..821cdfa9ed8ee --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/bt60.xml @@ -0,0 +1,45 @@ + + + Release - Release Candidate + Promotes the latest successful change on 'release' as a new release candidate + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/buildTypes/bt61.xml b/.teamcity/Gradle_Promotion/buildTypes/bt61.xml new file mode 100644 index 0000000000000..e0535b90a139c --- /dev/null +++ b/.teamcity/Gradle_Promotion/buildTypes/bt61.xml @@ -0,0 +1,58 @@ + + + Release - Release Nightly Snapshot + Deploys the latest successful change on 'release' as a new release nightly snapshot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml new file mode 100644 index 0000000000000..a4fa185bc879d --- /dev/null +++ b/.teamcity/Gradle_Promotion/pluginData/plugin-settings.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/project-config.xml b/.teamcity/Gradle_Promotion/project-config.xml new file mode 100644 index 0000000000000..87311aa2a67d4 --- /dev/null +++ b/.teamcity/Gradle_Promotion/project-config.xml @@ -0,0 +1,30 @@ + + + Promotion + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.xml b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.xml new file mode 100644 index 0000000000000..fb3f3ab812928 --- /dev/null +++ b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion_GradlePromotionBranches.xml @@ -0,0 +1,17 @@ + + + Gradle Promotion Branches + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.xml b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.xml new file mode 100644 index 0000000000000..18f29ceaa6a6d --- /dev/null +++ b/.teamcity/Gradle_Promotion/vcsRoots/Gradle_Promotion__master_.xml @@ -0,0 +1,16 @@ + + + Gradle Promotion + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.xml b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.xml new file mode 100644 index 0000000000000..cb400adac9186 --- /dev/null +++ b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestLinux.xml @@ -0,0 +1,101 @@ + + + AdHoc Functional Test - Linux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.xml b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.xml new file mode 100644 index 0000000000000..731cd745afab8 --- /dev/null +++ b/.teamcity/Gradle_Util/buildTypes/Gradle_Util_AdHocFunctionalTestWindows.xml @@ -0,0 +1,97 @@ + + + AdHoc Functional Test - Windows + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Util/pluginData/plugin-settings.xml b/.teamcity/Gradle_Util/pluginData/plugin-settings.xml new file mode 100644 index 0000000000000..677e924ad523a --- /dev/null +++ b/.teamcity/Gradle_Util/pluginData/plugin-settings.xml @@ -0,0 +1,3 @@ + + + diff --git a/.teamcity/Gradle_Util/project-config.xml b/.teamcity/Gradle_Util/project-config.xml new file mode 100644 index 0000000000000..5cfe45692ba2f --- /dev/null +++ b/.teamcity/Gradle_Util/project-config.xml @@ -0,0 +1,18 @@ + + + Util + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.xml b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.xml new file mode 100644 index 0000000000000..3ea3c764de038 --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_AdHocPerformanceScenarioLinux.xml @@ -0,0 +1,67 @@ + + + AdHoc Performance Scenario - Linux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.xml b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.xml new file mode 100644 index 0000000000000..8470ccb4f19cd --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/buildTypes/Gradle_Util_Performance_PerformanceTestCoordinatorLinux.xml @@ -0,0 +1,102 @@ + + + AdHoc Performance Test Coordinator - Linux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.teamcity/Gradle_Util_Performance/pluginData/plugin-settings.xml b/.teamcity/Gradle_Util_Performance/pluginData/plugin-settings.xml new file mode 100644 index 0000000000000..677e924ad523a --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/pluginData/plugin-settings.xml @@ -0,0 +1,3 @@ + + + diff --git a/.teamcity/Gradle_Util_Performance/project-config.xml b/.teamcity/Gradle_Util_Performance/project-config.xml new file mode 100644 index 0000000000000..842ef873cfae2 --- /dev/null +++ b/.teamcity/Gradle_Util_Performance/project-config.xml @@ -0,0 +1,7 @@ + + + Performance + + + + diff --git a/.teamcity/README.md b/.teamcity/README.md new file mode 100644 index 0000000000000..58e1a069753e8 --- /dev/null +++ b/.teamcity/README.md @@ -0,0 +1,16 @@ +# CI Pipeline Configuration + +- Currently there are three subprojects in the [Gradle](https://builds.gradle.org/project.html?projectId=Gradle) TeamCity project which are configured here + - [Check](https://builds.gradle.org/project.html?projectId=Gradle_Check) - Main build pipeline + (_Configured with [TeamCity's Kotlin DSL](https://confluence.jetbrains.com/display/TCD10/Kotlin+DSL)_) + - [Promotion](https://builds.gradle.org/project.html?projectId=Gradle_Promotion) - Jobs to publish Gradle versions + (_Configured directly in the TeamCity UI and stored in XML_) + - [Util](https://builds.gradle.org/project.html?projectId=Gradle_Util) - Manually triggered utility jobs + (_Configured directly in the TeamCity UI and stored in XML_) +- To configure/modify the _Check_ pipeline + - The configurations are stored in the `.teamcity` folder and [tests](https://blog.jetbrains.com/teamcity/2017/02/kotlin-configuration-scripts-testing-configuration-scripts) in the `.teamcityTest` folder + - Open the `.teamcity` folder in IDEA + - Revert the changes made by IDEA to `Gradle_Check_dsl.iml` + - The main pipeline configuration can be found and modified in [CIBuildModel.kt](https://github.com/gradle/gradle/blob/teamcity-versioned-settings/.teamcity/Gradle_Check/model/CIBuildModel.kt) + - After modifying, make sure that the configuration can be processed by running `CIConfigIntegrationTests` + - Commit and push the changes diff --git a/.teamcity/pom.xml b/.teamcity/pom.xml new file mode 100644 index 0000000000000..5860f723d98c1 --- /dev/null +++ b/.teamcity/pom.xml @@ -0,0 +1,126 @@ + + + 4.0.0 + Gradle_Check Config DSL Script + + 1.2.50 + 2018.1 + + Gradle_Check + Gradle_Check_dsl + 1.0-SNAPSHOT + + + + jetbrains-all + http://download.jetbrains.com/teamcity-repository + + true + + + + teamcity-server + https://builds.gradle.org/app/dsl-plugins-repository + + true + + + + + + + JetBrains + http://download.jetbrains.com/teamcity-repository + + + + + . + ../.teamcityTest/Gradle_Check_Tests + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + + + compile + process-sources + + compile + + + + test-compile + process-test-sources + + test-compile + + + + + + org.jetbrains.teamcity + teamcity-configs-maven-plugin + ${teamcity.dsl.version} + + kotlin + target/generated-configs + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20 + + + org.apache.maven.surefire + surefire-junit47 + 2.20 + + + + + + + + + org.jetbrains.teamcity + configs-dsl-kotlin + ${teamcity.dsl.version} + compile + + + org.jetbrains.teamcity + configs-dsl-kotlin-plugins + 1.0-SNAPSHOT + pom + compile + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + compile + + + org.jetbrains.kotlin + kotlin-script-runtime + ${kotlin.version} + compile + + + org.jetbrains.kotlin + kotlin-test-junit + ${kotlin.version} + test + + + junit + junit + 4.12 + + + diff --git a/.teamcityTest/Gradle_Check_Tests/CIConfigIntegrationTests.kt b/.teamcityTest/Gradle_Check_Tests/CIConfigIntegrationTests.kt new file mode 100644 index 0000000000000..6cf7bd19ed5e8 --- /dev/null +++ b/.teamcityTest/Gradle_Check_Tests/CIConfigIntegrationTests.kt @@ -0,0 +1,280 @@ + +import configurations.shouldBeSkipped +import jetbrains.buildServer.configs.kotlin.v2018_1.Project +import model.CIBuildModel +import model.GradleSubproject +import model.JvmVendor +import model.JvmVersion +import model.NoBuildCache +import model.OS +import model.SpecificBuild +import model.Stage +import model.StageName +import model.StageNames +import model.TestCoverage +import model.TestType +import org.junit.Test +import projects.RootProject +import java.io.File +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class CIConfigIntegrationTests { + @Test + fun configurationTreeCanBeGenerated() { + val m = CIBuildModel() + val p = RootProject(m) + printTree(p) + assertEquals(p.subProjects.size, m.stages.size + 1) + } + + @Test + fun macOSBuildsSubset() { + val m = CIBuildModel() + val p = RootProject(m) + val readyForRelease = p.subProjects.find { it.name.contains(StageNames.READY_FOR_RELEASE.stageName) }!! + val macOS = readyForRelease.subProjects.find { it.name.contains("Macos") }!! + + macOS.buildTypes.forEach { buildType -> + assertFalse(OS.macos.ignoredSubprojects.any { subproject -> + buildType.name.endsWith("($subproject)") + }) + } + } + + @Test + fun configurationsHaveDependencies() { + val m = CIBuildModel() + val p = RootProject(m) + val stagePassConfigs = p.buildTypes + stagePassConfigs.forEach { + val stageNumber = stagePassConfigs.indexOf(it) + 1 + println(it.id) + it.dependencies.items.forEach { + println("--> " + it.buildTypeId) + } + if (stageNumber <= m.stages.size) { + val stage = m.stages[stageNumber - 1] + val prevStage = if (stageNumber > 1) m.stages[stageNumber - 2] else null + var functionalTestCount = 0 + + if (stage.runsIndependent) { + return@forEach + } + + stage.functionalTests.forEach { testCoverage -> + m.subProjects.forEach { subProject -> + if (subProject.containsSlowTests && stage.omitsSlowProjects) { + return@forEach + } + if (shouldBeSkipped(subProject, testCoverage)) { + return@forEach + } + if (subProject.unitTests && testCoverage.testType.unitTests) { + functionalTestCount++ + } else if (subProject.functionalTests && testCoverage.testType.functionalTests) { + functionalTestCount++ + } else if (subProject.crossVersionTests && testCoverage.testType.crossVersionTests) { + functionalTestCount++ + } + } + if (testCoverage.testType == TestType.soak) { + functionalTestCount++ + } + } + + // hacky way to consider deferred tests + val deferredTestCount = if (stage.stageName == StageNames.READY_FOR_NIGHTLY) 10 else 0 + assertEquals( + stage.specificBuilds.size + functionalTestCount + stage.performanceTests.size + (if (prevStage != null) 1 else 0) + deferredTestCount, + it.dependencies.items.size, stage.stageName.stageName) + } else { + assertEquals(2, it.dependencies.items.size) //Individual Performance Worker + } + } + } + + @Test + fun canDeactivateBuildCacheAndAdjustCIModel() { + val m = CIBuildModel( + projectPrefix = "Gradle_BuildCacheDeactivated_", + parentBuildCache = NoBuildCache, + childBuildCache = NoBuildCache, + stages = listOf( + Stage(StageNames.QUICK_FEEDBACK, + specificBuilds = listOf( + SpecificBuild.CompileAll, + SpecificBuild.SanityCheck, + SpecificBuild.BuildDistributions), + functionalTests = listOf( + TestCoverage(TestType.quick, OS.linux, JvmVersion.java8), + TestCoverage(TestType.quick, OS.windows, JvmVersion.java11, vendor = JvmVendor.openjdk)), + omitsSlowProjects = true) + ) + ) + val p = RootProject(m) + printTree(p) + assertTrue(p.subProjects.size == 1) + } + + @Test + fun canDeferSlowTestsToLaterStage() { + + data class DefaultStageName(override val stageName: String, override val description: String) : StageName + + + val m = CIBuildModel( + projectPrefix = "", + parentBuildCache = NoBuildCache, + childBuildCache = NoBuildCache, + stages = listOf( + Stage(DefaultStageName("Stage1", "Stage1 description"), + functionalTests = listOf( + TestCoverage(TestType.quick, OS.linux, JvmVersion.java8), + TestCoverage(TestType.quick, OS.windows, JvmVersion.java8)), + omitsSlowProjects = true), + Stage(DefaultStageName("Stage2", "Stage2 description"), + functionalTests = listOf( + TestCoverage(TestType.noDaemon, OS.linux, JvmVersion.java8), + TestCoverage(TestType.noDaemon, OS.windows, JvmVersion.java8)), + omitsSlowProjects = true), + Stage(DefaultStageName("Stage3", "Stage3 description"), + functionalTests = listOf( + TestCoverage(TestType.platform, OS.linux, JvmVersion.java8), + TestCoverage(TestType.platform, OS.windows, JvmVersion.java8)), + omitsSlowProjects = false), + Stage(DefaultStageName("Stage4", "Stage4 description"), + functionalTests = listOf( + TestCoverage(TestType.parallel, OS.linux, JvmVersion.java8), + TestCoverage(TestType.parallel, OS.windows, JvmVersion.java8)), + omitsSlowProjects = false) + ), + subProjects = listOf( + GradleSubproject("fastBuild"), + GradleSubproject("slowBuild", containsSlowTests = true) + ) + ) + val p = RootProject(m) + assertTrue(!p.hasSubProject("Stage1", "deferred")) + assertTrue(!p.hasSubProject("Stage2", "deferred")) + assertTrue( p.hasSubProject("Stage3", "deferred")) + assertTrue(!p.hasSubProject("Stage4", "deferred")) + assertTrue(p.findSubProject("Stage3", "deferred")!!.hasBuildType("Quick", "slowBuild")) + assertTrue(p.findSubProject("Stage3", "deferred")!!.hasBuildType("NoDaemon", "slowBuild")) + } + + private fun Project.hasSubProject(vararg patterns: String): Boolean { + return findSubProject(*patterns) != null + } + + private fun Project.findSubProject(vararg patterns: String): Project? { + val tail = patterns.drop(1).toTypedArray() + val sub = this.subProjects.find { it.name.contains(patterns[0]) } + return if (sub == null || tail.isEmpty()) sub else sub.findSubProject(*tail) + } + + private fun Project.hasBuildType(vararg patterns: String): Boolean { + return this.buildTypes.find { buildType -> + patterns.all { pattern -> + buildType.name.contains(pattern) + } + } != null + } + + @Test + fun allSubprojectsAreListed() { + val m = CIBuildModel() + subProjectFolderList().forEach { + assertTrue(m.subProjects.map { it.asDirectoryName() }.contains(it.name), "Not defined: $it") + } + } + + @Test + fun allSubprojectsDefineTheirUnitTestPropertyCorrectly() { + val projectsWithUnitTests = CIBuildModel().subProjects.filter { it.unitTests } + val projectFoldersWithUnitTests = subProjectFolderList().filter { File(it, "src/test").exists() + && it.name != "docs" //docs:check is part of Sanity Check + && it.name != "architecture-test" //architectureTest:test is part of Sanity Check + } + assertFalse(projectFoldersWithUnitTests.isEmpty()) + projectFoldersWithUnitTests.forEach { + assertTrue(projectsWithUnitTests.map { it.asDirectoryName() }.contains(it.name), "Contains unit tests: $it") + } + } + + @Test + fun allSubprojectsDefineTheirFunctionTestPropertyCorrectly() { + val projectsWithFunctionalTests = CIBuildModel().subProjects.filter { it.functionalTests } + val projectFoldersWithFunctionalTests = subProjectFolderList().filter { File(it, "src/integTest").exists() + && it.name != "distributions" //distributions:integTest is part of Build Distributions + && it.name != "soak" //soak tests have their own test category + } + assertFalse(projectFoldersWithFunctionalTests.isEmpty()) + projectFoldersWithFunctionalTests.forEach { + assertTrue(projectsWithFunctionalTests.map { it.asDirectoryName() }.contains(it.name), "Contains functional tests: $it") + } + } + + @Test + fun allSubprojectsDefineTheirCrossVersionTestPropertyCorrectly() { + val projectsWithCrossVersionTests = CIBuildModel().subProjects.filter { it.crossVersionTests } + val projectFoldersWithCrossVersionTests = subProjectFolderList().filter { File(it, "src/crossVersionTest").exists() } + assertFalse(projectFoldersWithCrossVersionTests.isEmpty()) + projectFoldersWithCrossVersionTests.forEach { + assertTrue(projectsWithCrossVersionTests.map { it.asDirectoryName() }.contains(it.name), "Contains cross-version tests: $it") + } + } + + @Test + fun integTestFolderDoesNotContainCrossVersionTests() { + val projectFoldersWithFunctionalTests = subProjectFolderList().filter { File(it, "src/integTest").exists() } + assertFalse(projectFoldersWithFunctionalTests.isEmpty()) + projectFoldersWithFunctionalTests.forEach { + assertFalse(containsSrcFileWithString(File(it, "src/integTest"), "CrossVersion", listOf("package org.gradle.testkit" ,"CrossVersionPerformanceTest"))) + } + } + + @Test + fun long_ids_are_shortened() { + val testCoverage = TestCoverage(TestType.quickFeedbackCrossVersion, OS.windows, JvmVersion.java11, JvmVendor.oracle) + val shortenedId = testCoverage.asConfigurationId(CIBuildModel(), "veryLongSubprojectNameLongerThanEverythingWeHave") + assertTrue(shortenedId.length < 80) + assertEquals(shortenedId, "Gradle_Check_QckFdbckCrssVrsn_Jv11_Orcl_Wndws_vryLngSbprjctNmLngrThnEvrythngWHv") + + assertEquals("Gradle_Check_QuickFeedbackCrossVersion_Java11_Oracle_Windows_iIntegT", testCoverage.asConfigurationId(CIBuildModel(), "internalIntegTesting")) + + assertEquals("Gradle_Check_QuickFeedbackCrossVersion_Java11_Oracle_Windows_buildCache", testCoverage.asConfigurationId(CIBuildModel(), "buildCache")) + + assertEquals("Gradle_Check_QuickFeedbackCrossVersion_Java11_Oracle_Windows_0", testCoverage.asConfigurationId(CIBuildModel())) + } + + private fun containsSrcFileWithString(srcRoot: File, content: String, exceptions: List): Boolean { + srcRoot.walkTopDown().forEach { + if (it.extension == "groovy" || it.extension == "java") { + val text = it.readText() + if (text.contains(content) && exceptions.all { !text.contains(it) }) { + println("Found suspicious test file: $it") + return true + } + } + } + return false + } + + private fun subProjectFolderList() : List { + val subprojectFolders = File("../subprojects").listFiles().filter { it.isDirectory } + assertFalse(subprojectFolders.isEmpty()) + return subprojectFolders + } + + private fun printTree(project: Project, indent: String = "") { + println(indent + project.id + " (Project)") + project.buildTypes.forEach { bt -> + println("$indent+- ${bt.id} (Config)") + } + project.subProjects.forEach { subProject -> + printTree(subProject, "$indent ") + } + } +}