netci.groovy 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. // Import the utility functionality.
  6. import jobs.generation.Utilities
  7. // Grab the github project name passed in
  8. def project = GithubProject
  9. def branch = GithubBranchName
  10. def msbuildTypeMap = [
  11. 'debug':'chk',
  12. 'test':'test',
  13. 'release':'fre'
  14. ]
  15. // convert `machine` parameter to OS component of PR task name
  16. def machineTypeToOSTagMap = [
  17. 'Windows 7': 'Windows 7',
  18. 'Windows_NT': 'Windows',
  19. 'Ubuntu14.04': 'Ubuntu14.04',
  20. 'Ubuntu16.04': 'Ubuntu',
  21. 'OSX': 'OSX'
  22. ]
  23. def dailyRegex = 'dailies'
  24. // Only generate PR check triggers for the version of netci.groovy in the master branch
  25. // since those PR checks will apply for all branches.
  26. def jobTypesToGenerate = [false]
  27. if (branch.startsWith('master')) {
  28. // OK to generate PR checks (this ensures we only generate one set of them)
  29. jobTypesToGenerate += true
  30. }
  31. // ---------------
  32. // HELPER CLOSURES
  33. // ---------------
  34. def CreateBuildTasks = { machine, configTag, buildExtra, testExtra, runCodeAnalysis, excludeConfigIf, nonDefaultTaskSetup ->
  35. jobTypesToGenerate.each { isPR ->
  36. ['x86', 'x64', 'arm'].each { buildArch ->
  37. ['debug', 'test', 'release'].each { buildType ->
  38. if (excludeConfigIf && excludeConfigIf(isPR, buildArch, buildType)) {
  39. return // early exit: we don't want to create a job for this configuration
  40. }
  41. def config = "${buildArch}_${buildType}"
  42. config = (configTag == null) ? config : "${configTag}_${config}"
  43. // params: Project, BaseTaskName, IsPullRequest (appends '_prtest')
  44. def jobName = Utilities.getFullJobName(project, config, isPR)
  45. def testableConfig = buildType in ['debug', 'test'] && buildArch != 'arm'
  46. def analysisConfig = buildType in ['release'] && runCodeAnalysis
  47. def buildScript = "call .\\jenkins\\buildone.cmd ${buildArch} ${buildType} "
  48. buildScript += buildExtra ?: ''
  49. buildScript += analysisConfig ? ' "/p:runcodeanalysis=true"' : ''
  50. def testScript = "call .\\jenkins\\testone.cmd ${buildArch} ${buildType} "
  51. testScript += testExtra ?: ''
  52. def analysisScript = '.\\Build\\scripts\\check_prefast_error.ps1 . CodeAnalysis.err'
  53. def newJob = job(jobName) {
  54. // This opens the set of build steps that will be run.
  55. // This looks strange, but it is actually a method call, with a
  56. // closure as a param, since Groovy allows method calls without parens.
  57. // (Compare with '.each' method used above.)
  58. steps {
  59. batchFile(buildScript) // run the parameter as if it were a batch file
  60. if (testableConfig) {
  61. batchFile(testScript)
  62. }
  63. if (analysisConfig) {
  64. powerShell(analysisScript)
  65. }
  66. }
  67. }
  68. def msbuildType = msbuildTypeMap.get(buildType)
  69. def msbuildFlavor = "build_${buildArch}${msbuildType}"
  70. def archivalString = "test/${msbuildFlavor}.*,test/logs/**"
  71. archivalString += analysisConfig ? ',CodeAnalysis.err' : ''
  72. Utilities.addArchival(newJob, archivalString,
  73. '', // no exclusions from archival
  74. false, // doNotFailIfNothingArchived=false ~= failIfNothingArchived
  75. false) // archiveOnlyIfSuccessful=false ~= archiveAlways
  76. Utilities.setMachineAffinity(newJob, machine, 'latest-or-auto')
  77. Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
  78. if (nonDefaultTaskSetup == null) {
  79. if (isPR) {
  80. def osTag = machineTypeToOSTagMap.get(machine)
  81. // Set up checks which apply to PRs targeting any branch
  82. Utilities.addGithubPRTrigger(newJob, "${osTag} ${config}")
  83. // To enable PR checks only for specific target branches, use the following instead:
  84. // Utilities.addGithubPRTriggerForBranch(newJob, branch, checkName)
  85. } else {
  86. Utilities.addGithubPushTrigger(newJob)
  87. }
  88. } else {
  89. // nonDefaultTaskSetup is e.g. DailyBuildTaskSetup (which sets up daily builds)
  90. // These jobs will only be configured for the branch specified below,
  91. // which is the name of the branch netci.groovy was processed for.
  92. // See list of such branches at:
  93. // https://github.com/dotnet/dotnet-ci/blob/master/jobs/data/repolist.txt
  94. nonDefaultTaskSetup(newJob, isPR, config)
  95. }
  96. }
  97. }
  98. }
  99. }
  100. def CreateXPlatBuildTask = { isPR, buildType, staticBuild, machine, platform, configTag,
  101. xplatBranch, nonDefaultTaskSetup, customOption, testVariant ->
  102. def config = (platform == "osx" ? "osx_${buildType}" : "linux_${buildType}")
  103. def numConcurrentCommand = (platform == "osx" ? "sysctl -n hw.logicalcpu" : "nproc")
  104. config = (configTag == null) ? config : "${configTag}_${config}"
  105. config = staticBuild ? "${config}_static" : config
  106. // params: Project, BaseTaskName, IsPullRequest (appends '_prtest')
  107. def jobName = Utilities.getFullJobName(project, config, isPR) + customOption.replaceAll(/[-]+/, "_")
  108. def infoScript = "bash jenkins/get_system_info.sh --${platform}"
  109. def buildFlag = buildType == "release" ? "" : (buildType == "debug" ? "--debug" : "--test-build")
  110. def staticFlag = staticBuild ? "--static" : ""
  111. def icuFlag = (platform == "osx" ? "--icu=/usr/local/opt/icu4c/include" : "")
  112. def compilerPaths = (platform == "osx") ? "" : "--cxx=/usr/bin/clang++-3.8 --cc=/usr/bin/clang-3.8"
  113. def buildScript = "bash ./build.sh ${staticFlag} -j=`${numConcurrentCommand}` ${buildFlag} ${compilerPaths} ${icuFlag} ${customOption}"
  114. def testScript = "bash test/runtests.sh \"${testVariant}\""
  115. def newJob = job(jobName) {
  116. steps {
  117. shell(infoScript)
  118. shell(buildScript)
  119. shell(testScript)
  120. }
  121. }
  122. def archivalString = "BuildLinux/build.log"
  123. Utilities.addArchival(newJob, archivalString,
  124. '', // no exclusions from archival
  125. true, // doNotFailIfNothingArchived=false ~= failIfNothingArchived (true ~= doNotFail)
  126. false) // archiveOnlyIfSuccessful=false ~= archiveAlways
  127. Utilities.setMachineAffinity(newJob, machine, 'latest-or-auto')
  128. Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
  129. if (nonDefaultTaskSetup == null) {
  130. if (isPR) {
  131. def osTag = machineTypeToOSTagMap.get(machine)
  132. // Set up checks which apply to PRs targeting any branch
  133. Utilities.addGithubPRTriggerForBranch(newJob, xplatBranch, "${osTag} ${config}")
  134. } else {
  135. Utilities.addGithubPushTrigger(newJob)
  136. }
  137. } else {
  138. // nonDefaultTaskSetup is e.g. DailyBuildTaskSetup (which sets up daily builds)
  139. // These jobs will only be configured for the branch specified below,
  140. // which is the name of the branch netci.groovy was processed for.
  141. // See list of such branches at:
  142. // https://github.com/dotnet/dotnet-ci/blob/master/jobs/data/repolist.txt
  143. nonDefaultTaskSetup(newJob, isPR, config)
  144. }
  145. }
  146. // Generic task to trigger clang-based cross-plat build tasks
  147. def CreateXPlatBuildTasks = { machine, platform, configTag, xplatBranch, nonDefaultTaskSetup ->
  148. [true, false].each { isPR ->
  149. CreateXPlatBuildTask(isPR, "test", "", machine, platform,
  150. configTag, xplatBranch, nonDefaultTaskSetup, "--no-jit", "--variants disable_jit")
  151. ['debug', 'test', 'release'].each { buildType ->
  152. def staticBuildConfigs = [true, false]
  153. if (platform == "osx") {
  154. staticBuildConfigs = [true]
  155. }
  156. staticBuildConfigs.each { staticBuild ->
  157. CreateXPlatBuildTask(isPR, buildType, staticBuild, machine, platform,
  158. configTag, xplatBranch, nonDefaultTaskSetup, "", "")
  159. }
  160. }
  161. }
  162. }
  163. def DailyBuildTaskSetup = { newJob, isPR, triggerName, groupRegex ->
  164. // The addition of triggers makes the job non-default in GitHub.
  165. if (isPR) {
  166. def triggerRegex = "(${dailyRegex}|${groupRegex}|${triggerName})"
  167. Utilities.addGithubPRTrigger(newJob,
  168. triggerName, // GitHub task name
  169. "(?i).*test\\W+${triggerRegex}.*")
  170. } else {
  171. Utilities.addPeriodicTrigger(newJob, '@daily')
  172. }
  173. }
  174. def CreateStyleCheckTasks = { taskString, taskName, checkName ->
  175. [true, false].each { isPR ->
  176. def jobName = Utilities.getFullJobName(project, taskName, isPR)
  177. def newJob = job(jobName) {
  178. steps {
  179. shell(taskString)
  180. }
  181. }
  182. Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
  183. if (isPR) {
  184. // Set PR trigger.
  185. Utilities.addGithubPRTrigger(newJob, checkName)
  186. } else {
  187. // Set a push trigger
  188. Utilities.addGithubPushTrigger(newJob)
  189. }
  190. Utilities.setMachineAffinity(newJob, 'Ubuntu14.04', 'latest-or-auto')
  191. }
  192. }
  193. // ----------------
  194. // INNER LOOP TASKS
  195. // ----------------
  196. CreateBuildTasks('Windows_NT', null, null, null, true, null, null)
  197. // -----------------
  198. // DAILY BUILD TASKS
  199. // -----------------
  200. if (!branch.endsWith('-ci')) {
  201. // build and test on Windows 7 with VS 2013 (Dev12/MsBuild12)
  202. CreateBuildTasks('Windows 7', 'daily_dev12', 'msbuild12', '-win7 -includeSlow', false,
  203. /* excludeConfigIf */ { isPR, buildArch, buildType -> (buildArch == 'arm') },
  204. /* nonDefaultTaskSetup */ { newJob, isPR, config ->
  205. DailyBuildTaskSetup(newJob, isPR,
  206. "Windows 7 ${config}",
  207. '(dev12|legacy)\\s+tests')})
  208. // build and test on the usual configuration (VS 2015) with -includeSlow
  209. CreateBuildTasks('Windows_NT', 'daily_slow', null, '-includeSlow', false,
  210. /* excludeConfigIf */ null,
  211. /* nonDefaultTaskSetup */ { newJob, isPR, config ->
  212. DailyBuildTaskSetup(newJob, isPR,
  213. "Windows ${config}",
  214. 'slow\\s+tests')})
  215. // build and test on the usual configuration (VS 2015) with JIT disabled
  216. CreateBuildTasks('Windows_NT', 'daily_disablejit', '"/p:BuildJIT=false"', '-disablejit', true,
  217. /* excludeConfigIf */ null,
  218. /* nonDefaultTaskSetup */ { newJob, isPR, config ->
  219. DailyBuildTaskSetup(newJob, isPR,
  220. "Windows ${config}",
  221. '(disablejit|nojit)\\s+tests')})
  222. }
  223. // ----------------
  224. // CODE STYLE TASKS
  225. // ----------------
  226. CreateStyleCheckTasks('./jenkins/check_copyright.sh', 'ubuntu_check_copyright', 'Copyright Check')
  227. CreateStyleCheckTasks('./jenkins/check_eol.sh', 'ubuntu_check_eol', 'EOL Check')
  228. CreateStyleCheckTasks('./jenkins/check_tabs.sh', 'ubuntu_check_tabs', 'Tab Check')
  229. // --------------
  230. // XPLAT BRANCHES
  231. // --------------
  232. // Explicitly enumerate xplat-incompatible branches, because we don't anticipate any future incompatible branches
  233. def isXPlatCompatibleBranch = !(branch in ['release/1.1', 'release/1.1-ci', 'release/1.2', 'release/1.2-ci'])
  234. // Include these explicitly-named branches
  235. def isXPlatDailyBranch = branch in ['master', 'linux', 'xplat']
  236. // Include some release/* branches
  237. if (branch.startsWith('release')) {
  238. // Allows all current and future release/* branches on which we should run daily builds of XPlat configs.
  239. // RegEx matches e.g. release/1.1, release/1.2, release/1.3-ci, but not e.g. release/2.0, release/1.3, or release/1.10
  240. includeReleaseBranch = !(branch =~ /^release\/((1\.[12](\D.*)?)|(\d+\.\d+\D.*))$/)
  241. isXPlatDailyBranch |= includeReleaseBranch
  242. }
  243. // -----------------
  244. // LINUX BUILD TASKS
  245. // -----------------
  246. if (isXPlatCompatibleBranch) {
  247. def osString = 'Ubuntu16.04'
  248. // PR and CI checks
  249. CreateXPlatBuildTasks(osString, "linux", "ubuntu", branch, null)
  250. // daily builds
  251. if (isXPlatDailyBranch) {
  252. CreateXPlatBuildTasks(osString, "linux", "daily_ubuntu", branch,
  253. /* nonDefaultTaskSetup */ { newJob, isPR, config ->
  254. DailyBuildTaskSetup(newJob, isPR,
  255. "Ubuntu ${config}",
  256. 'linux\\s+tests')})
  257. }
  258. }
  259. // ---------------
  260. // OSX BUILD TASKS
  261. // ---------------
  262. if (isXPlatCompatibleBranch) {
  263. def osString = 'OSX'
  264. // PR and CI checks
  265. CreateXPlatBuildTasks(osString, "osx", "osx", branch, null)
  266. // daily builds
  267. if (isXPlatDailyBranch) {
  268. CreateXPlatBuildTasks(osString, "osx", "daily_osx", branch,
  269. /* nonDefaultTaskSetup */ { newJob, isPR, config ->
  270. DailyBuildTaskSetup(newJob, isPR,
  271. "OSX ${config}",
  272. 'linux\\s+tests')})
  273. }
  274. }
  275. // ------------
  276. // HELP MESSAGE
  277. // ------------
  278. Utilities.createHelperJob(this, project, branch,
  279. "Welcome to the ${project} Repository", // This is prepended to the help message
  280. "For additional documentation on ChakraCore CI checks, please see:\n" +
  281. "\n" +
  282. "* https://github.com/Microsoft/ChakraCore/wiki/Jenkins-CI-Checks\n" +
  283. "* https://github.com/Microsoft/ChakraCore/wiki/Jenkins-Build-Triggers\n" +
  284. "* https://github.com/Microsoft/ChakraCore/wiki/Jenkins-Repro-Steps\n" +
  285. "\n" +
  286. "Have a nice day!") // This is appended to the help message. You might put known issues here.