Jenkinsfile 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 = docker.build('realm-object-store:ndk21', '-f android.Dockerfile .')
  72. docker.image('tracer0tong/android-emulator').withRun { emulator ->
  73. image.inside("--link ${emulator.id}:emulator") {
  74. sh """
  75. cmake -B build -DREALM_PLATFORM=Android -DANDROID_NDK=\${ANDROID_NDK} -GNinja -DCMAKE_MAKE_PROGRAM=ninja
  76. cmake --build build
  77. adb connect emulator
  78. timeout 10m adb wait-for-device
  79. adb push build/tests/tests /data/local/tmp
  80. adb shell '/data/local/tmp/tests || echo __ADB_FAIL__' | tee adb.log
  81. ! grep __ADB_FAIL__ adb.log
  82. """
  83. }
  84. }
  85. }
  86. }
  87. }
  88. }
  89. def doBuild(String nodeSpec, String flavor, Boolean enableSync, String version) {
  90. def sync = enableSync ? "sync" : "false"
  91. def label = "${flavor}${enableSync ? '-sync' : ''}"
  92. return {
  93. node(nodeSpec) {
  94. getSourceArchive()
  95. sshagent(['realm-ci-ssh']) {
  96. sh "./workflow/test_coverage.sh ${sync} ${version} && mv coverage.build ${label}.build"
  97. }
  98. echo "Stashing coverage-${label}"
  99. stash includes: "${label}.build/coverage.xml", name: "coverage-${label}"
  100. }
  101. }
  102. }
  103. def doWindowsBuild() {
  104. return {
  105. node('windows') {
  106. getSourceArchive()
  107. bat """
  108. "${tool 'cmake'}" . -DCMAKE_SYSTEM_VERSION="8.1"
  109. "${tool 'cmake'}" --build . --config Release
  110. tests\\Release\\tests.exe
  111. """
  112. }
  113. }
  114. }
  115. def doWindowsUniversalBuild() {
  116. return {
  117. node('windows') {
  118. getSourceArchive()
  119. bat """
  120. "${tool 'cmake'}" . -DCMAKE_SYSTEM_NAME="WindowsStore" -DCMAKE_SYSTEM_VERSION="10.0"
  121. "${tool 'cmake'}" --build . --config Release --target realm-object-store
  122. """
  123. }
  124. }
  125. }
  126. def setBuildName(newBuildName) {
  127. currentBuild.displayName = "${currentBuild.displayName} - ${newBuildName}"
  128. }
  129. stage('prepare') {
  130. node('docker') {
  131. checkout scm
  132. sh 'git clean -ffdx -e .????????'
  133. sshagent(['realm-ci-ssh']) {
  134. sh 'git submodule update --init --recursive'
  135. }
  136. gitTag = readGitTag()
  137. gitSha = readGitSha()
  138. echo "tag: ${gitTag}"
  139. if (gitTag == "") {
  140. echo "No tag given for this build"
  141. setBuildName("${gitSha}")
  142. } else {
  143. echo "Building release: '${gitTag}'"
  144. setBuildName("Tag ${gitTag}")
  145. }
  146. stash includes: '**', name: 'source'
  147. }
  148. }
  149. stage('unit-tests') {
  150. parallel(
  151. linux: doDockerBuild('linux', false, false),
  152. linux_sync: doDockerBuild('linux', true, true),
  153. linux_asan: doDockerBuild('linux', false, true, '-DSANITIZE_ADDRESS=1'),
  154. linux_tsan: doDockerBuild('linux', false, true, '-DSANITIZE_THREAD=1'),
  155. android: doAndroidDockerBuild(),
  156. macos: doBuild('osx', 'macOS', false, ''),
  157. macos_sync: doBuild('osx', 'macOS', true, ''),
  158. win32: doWindowsBuild(),
  159. windows_universal: doWindowsUniversalBuild()
  160. )
  161. currentBuild.result = 'SUCCESS'
  162. }
  163. stage('publish') {
  164. node('docker') {
  165. publishReport('linux-sync')
  166. publishReport('macOS-sync')
  167. }
  168. }