Jenkinsfile 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #!groovy
  2. def getSourceArchive() {
  3. deleteDir()
  4. unstash 'source'
  5. }
  6. def readGitTag() {
  7. sh "git describe --exact-match --tags HEAD | tail -n 1 > tag.txt 2>&1 || true"
  8. def tag = readFile('tag.txt').trim()
  9. return tag
  10. }
  11. def readGitSha() {
  12. sh "git rev-parse HEAD | cut -b1-8 > sha.txt"
  13. def sha = readFile('sha.txt').readLines().last().trim()
  14. return sha
  15. }
  16. def buildDockerEnv(name, dockerfile='Dockerfile', extra_args='') {
  17. docker.withRegistry("https://${env.DOCKER_REGISTRY}", "ecr:eu-west-1:aws-ci-user") {
  18. sh "sh ./workflow/docker_build_wrapper.sh $name . ${extra_args}"
  19. }
  20. return docker.image(name)
  21. }
  22. def publishReport(String label) {
  23. // Unfortunately, we cannot add a title or tag to individual coverage reports.
  24. echo "Unstashing coverage-${label}"
  25. unstash("coverage-${label}")
  26. step([
  27. $class: 'CoberturaPublisher',
  28. autoUpdateHealth: false,
  29. autoUpdateStability: false,
  30. coberturaReportFile: "${label}.build/coverage.xml",
  31. failNoReports: true,
  32. failUnhealthy: false,
  33. failUnstable: false,
  34. maxNumberOfBuilds: 0,
  35. onlyStable: false,
  36. sourceEncoding: 'ASCII',
  37. zoomCoverageChart: false
  38. ])
  39. }
  40. if (env.BRANCH_NAME == 'master') {
  41. env.DOCKER_PUSH = "1"
  42. }
  43. def doDockerBuild(String flavor, Boolean withCoverage, Boolean enableSync, String sanitizerFlags = "") {
  44. def sync = enableSync ? "sync" : ""
  45. def label = "${flavor}${enableSync ? '-sync' : ''}"
  46. return {
  47. node('docker') {
  48. getSourceArchive()
  49. def image = buildDockerEnv("ci/realm-object-store:${flavor}")
  50. sshagent(['realm-ci-ssh']) {
  51. image.inside("-v /etc/passwd:/etc/passwd:ro -v ${env.HOME}:${env.HOME} -v ${env.SSH_AUTH_SOCK}:${env.SSH_AUTH_SOCK} -e HOME=${env.HOME}") {
  52. if(withCoverage) {
  53. sh "rm -rf coverage.build ${label}.build && ./workflow/test_coverage.sh ${sync} && mv coverage.build ${label}.build"
  54. } else {
  55. sh "./workflow/build.sh ${flavor} ${sync} ${sanitizerFlags}"
  56. }
  57. }
  58. }
  59. if(withCoverage) {
  60. echo "Stashing coverage-${label}"
  61. stash includes: "${label}.build/coverage.xml", name: "coverage-${label}"
  62. }
  63. }
  64. }
  65. }
  66. def doAndroidDockerBuild() {
  67. return {
  68. node('docker') {
  69. getSourceArchive()
  70. wrap([$class: 'AnsiColorBuildWrapper']) {
  71. def image = buildDockerEnv('ci/realm-object-store:android')
  72. docker.image('tracer0tong/android-emulator').withRun { emulator ->
  73. image.inside("--link ${emulator.id}:emulator") {
  74. sh '''rm -rf build
  75. mkdir build
  76. cd build
  77. cmake -DREALM_PLATFORM=Android -DANDROID_NDK=/opt/android-ndk -GNinja -DCMAKE_MAKE_PROGRAM=ninja ..
  78. ninja
  79. adb connect emulator
  80. timeout 10m adb wait-for-device
  81. adb push tests/tests /data/local/tmp
  82. adb shell '/data/local/tmp/tests || echo __ADB_FAIL__' | tee adb.log
  83. ! grep __ADB_FAIL__ adb.log
  84. '''
  85. }
  86. }
  87. }
  88. }
  89. }
  90. }
  91. def doBuild(String nodeSpec, String flavor, Boolean enableSync, String version) {
  92. def sync = enableSync ? "sync" : "false"
  93. def label = "${flavor}${enableSync ? '-sync' : ''}"
  94. return {
  95. node(nodeSpec) {
  96. getSourceArchive()
  97. sshagent(['realm-ci-ssh']) {
  98. sh "./workflow/test_coverage.sh ${sync} ${version} && mv coverage.build ${label}.build"
  99. }
  100. echo "Stashing coverage-${label}"
  101. stash includes: "${label}.build/coverage.xml", name: "coverage-${label}"
  102. }
  103. }
  104. }
  105. def doWindowsBuild() {
  106. return {
  107. node('windows') {
  108. getSourceArchive()
  109. bat """
  110. "${tool 'cmake'}" . -DCMAKE_SYSTEM_VERSION="8.1"
  111. "${tool 'cmake'}" --build . --config Release
  112. tests\\Release\\tests.exe
  113. """
  114. }
  115. }
  116. }
  117. def doWindowsUniversalBuild() {
  118. return {
  119. node('windows') {
  120. getSourceArchive()
  121. bat """
  122. "${tool 'cmake'}" . -DCMAKE_SYSTEM_NAME="WindowsStore" -DCMAKE_SYSTEM_VERSION="10.0"
  123. "${tool 'cmake'}" --build . --config Release --target realm-object-store
  124. """
  125. }
  126. }
  127. }
  128. def setBuildName(newBuildName) {
  129. currentBuild.displayName = "${currentBuild.displayName} - ${newBuildName}"
  130. }
  131. stage('prepare') {
  132. node('docker') {
  133. checkout scm
  134. sh 'git clean -ffdx -e .????????'
  135. sshagent(['realm-ci-ssh']) {
  136. sh 'git submodule update --init --recursive'
  137. }
  138. gitTag = readGitTag()
  139. gitSha = readGitSha()
  140. echo "tag: ${gitTag}"
  141. if (gitTag == "") {
  142. echo "No tag given for this build"
  143. setBuildName("${gitSha}")
  144. } else {
  145. echo "Building release: '${gitTag}'"
  146. setBuildName("Tag ${gitTag}")
  147. }
  148. stash includes: '**', name: 'source'
  149. }
  150. }
  151. stage('unit-tests') {
  152. parallel(
  153. linux: doDockerBuild('linux', false, false),
  154. linux_sync: doDockerBuild('linux', true, true),
  155. linux_asan: doDockerBuild('linux', false, true, '-DSANITIZE_ADDRESS=1'),
  156. linux_tsan: doDockerBuild('linux', false, true, '-DSANITIZE_THREAD=1'),
  157. android: doAndroidDockerBuild(),
  158. macos: doBuild('osx', 'macOS', false, ''),
  159. macos_sync: doBuild('osx', 'macOS', true, ''),
  160. win32: doWindowsBuild(),
  161. windows_universal: doWindowsUniversalBuild()
  162. )
  163. currentBuild.result = 'SUCCESS'
  164. }
  165. stage('publish') {
  166. node('docker') {
  167. publishReport('linux-sync')
  168. publishReport('macOS-sync')
  169. }
  170. }