You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by GitBox <gi...@apache.org> on 2018/11/21 11:07:19 UTC

[GitHub] marcoabreu closed pull request #13344: Refactor Jenkinsfiles

marcoabreu closed pull request #13344: Refactor Jenkinsfiles
URL: https://github.com/apache/incubator-mxnet/pull/13344
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/Jenkinsfile b/Jenkinsfile
index fca85395194..a7e3dbd9bcc 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -20,6 +20,32 @@
 // Jenkins pipeline
 // See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
 
+
+/***
+ *      _____  _                          
+ *     |  __ \| |                         
+ *     | |__) | | ___  __ _ ___  ___      
+ *     |  ___/| |/ _ \/ _` / __|/ _ \     
+ *     | | | || |  __/ (_| \__ \  __/     
+ *     |_|_| ||_|\___|\__,_|___/\___|     
+ *      / _` |/ _ \                       
+ *     | (_| | (_) |_                     
+ *      \__,_|\___/| |                    
+ *      _ __   ___ | |_                   
+ *     | '_ \ / _ \| __|    _ _  __       
+ *     | | | | (_) | |_    | (_)/ _|      
+ *     |_|_|_|\___/_\__| __| |_| |_ _   _ 
+ *     | '_ ` _ \ / _ \ / _` | |  _| | | |
+ *     | | | | | | (_) | (_| | | | | |_| |
+ *     |_| |_| |_|\___/ \__,_|_|_|  \__, |
+ *                                   __/ |
+ *                                  |___/ 
+ *
+ * This file is about to be deprecated! See https://github.com/apache/incubator-mxnet/pull/13344
+ * for more details
+ */
+
+
 // mxnet libraries
 mx_lib = 'lib/libmxnet.so, lib/libmxnet.a, 3rdparty/dmlc-core/libdmlc.a, 3rdparty/tvm/nnvm/lib/libnnvm.a'
 
diff --git a/ci/Jenkinsfile_utils.groovy b/ci/Jenkinsfile_utils.groovy
index 43f296aacc5..8794ad301ce 100644
--- a/ci/Jenkinsfile_utils.groovy
+++ b/ci/Jenkinsfile_utils.groovy
@@ -65,8 +65,10 @@ def init_git_win() {
 // pack libraries for later use
 def pack_lib(name, libs, include_gcov_data = false) {
   sh """
+set +e
 echo "Packing ${libs} into ${name}"
 echo ${libs} | sed -e 's/,/ /g' | xargs md5sum
+return 0
 """
   stash includes: libs, name: name
 
@@ -82,8 +84,10 @@ def unpack_and_init(name, libs, include_gcov_data = false) {
   init_git()
   unstash name
   sh """
+set +e
 echo "Unpacked ${libs} from ${name}"
 echo ${libs} | sed -e 's/,/ /g' | xargs md5sum
+return 0
 """
   if (include_gcov_data) {
     // Restore GCNO files that are required for GCOV to operate during runtime
@@ -91,23 +95,32 @@ echo ${libs} | sed -e 's/,/ /g' | xargs md5sum
   }
 }
 
+def get_jenkins_master_url() {
+    return env.BUILD_URL.split('/')[2].split(':')[0]
+}
+
+def get_git_commit_hash() {
+  lastCommitMessage = sh (script: "git log -1 --pretty=%B", returnStdout: true)
+  lastCommitMessage = lastCommitMessage.trim()
+  if (lastCommitMessage.startsWith("Merge commit '") && lastCommitMessage.endsWith("' into HEAD")) {
+      // Merge commit applied by Jenkins, skip that commit
+      git_commit_hash = sh (script: "git rev-parse @~", returnStdout: true)
+  } else {
+      git_commit_hash = sh (script: "git rev-parse @", returnStdout: true)
+  }
+  return git_commit_hash
+}
+
 def publish_test_coverage() {
     // CodeCovs auto detection has trouble with our CIs PR validation due the merging strategy
-    lastCommitMessage = sh (script: "git log -1 --pretty=%B", returnStdout: true)
-    lastCommitMessage = lastCommitMessage.trim()
-    if (lastCommitMessage.startsWith("Merge commit '") && lastCommitMessage.endsWith("' into HEAD")) {
-        // Merge commit applied by Jenkins, skip that commit
-        GIT_COMMIT_HASH = sh (script: "git rev-parse @~", returnStdout: true)
-    } else {
-        GIT_COMMIT_HASH = sh (script: "git rev-parse @", returnStdout: true)
-    }
+    git_commit_hash = get_git_commit_hash()
    
     if (env.CHANGE_ID) {
       // PR execution
-      codecovArgs = "-B ${env.CHANGE_TARGET} -C ${GIT_COMMIT_HASH} -P ${env.CHANGE_ID}"
+      codecovArgs = "-B ${env.CHANGE_TARGET} -C ${git_commit_hash} -P ${env.CHANGE_ID}"
     } else {
       // Branch execution
-      codecovArgs = "-B ${env.BRANCH_NAME} -C ${GIT_COMMIT_HASH}"
+      codecovArgs = "-B ${env.BRANCH_NAME} -C ${git_commit_hash}"
     }
 
     // To make sure we never fail because test coverage reporting is not available
@@ -144,9 +157,78 @@ def docker_run(platform, function_name, use_nvidia, shared_mem = '500m') {
   sh command
 }
 
+// Allow publishing to GitHub with a custom context (the status shown under a PR)
+// Credit to https://plugins.jenkins.io/github
+def get_repo_url() {
+  checkout scm
+  sh "git config --get remote.origin.url > .git/remote-url"
+  return readFile(".git/remote-url").trim()
+}
 
+def update_github_commit_status(state, message) {
+  node(NODE_LINUX_CPU) {
+    // NOTE: https://issues.jenkins-ci.org/browse/JENKINS-39482
+    //The GitHubCommitStatusSetter requires that the Git Server is defined under 
+    //*Manage Jenkins > Configure System > GitHub > GitHub Servers*. 
+    //Otherwise the GitHubCommitStatusSetter is not able to resolve the repository name 
+    //properly and you would see an empty list of repos:
+    //[Set GitHub commit status (universal)] PENDING on repos [] (sha:xxxxxxx) with context:test/mycontext
+    //See https://cwiki.apache.org/confluence/display/MXNET/Troubleshooting#Troubleshooting-GitHubcommit/PRstatusdoesnotgetpublished
+    repoUrl = get_repo_url()
+    commitSha = get_git_commit_hash()
+    context = get_github_context()
+
+    step([
+      $class: 'GitHubCommitStatusSetter',
+      reposSource: [$class: "ManuallyEnteredRepositorySource", url: repoUrl],
+      contextSource: [$class: "ManuallyEnteredCommitContextSource", context: context],
+      commitShaSource: [$class: "ManuallyEnteredShaSource", sha: commitSha],
+      statusBackrefSource: [$class: "ManuallyEnteredBackrefSource", backref: "${env.RUN_DISPLAY_URL}"],
+      errorHandlers: [[$class: 'ShallowAnyErrorHandler']],
+      statusResultSource: [
+        $class: 'ConditionalStatusResultSource',
+        results: [[$class: "AnyBuildResult", message: message, state: state]]
+      ]
+    ])
+  }
+}
+
+def get_github_context() {
+  // Since we use multi-branch pipelines, Jenkins appends the branch name to the job name
+  if (JOB_NAME.contains('/')) {
+    short_job_name = JOB_NAME.split('/')[0] 
+  } else {
+    short_job_name = JOB_NAME
+  }
+  
+  return "ci/jenkins/${short_job_name}"
+}
+
+def parallel_stage(stage_name, steps) {
+    // Allow to pass an array of steps that will be executed in parallel in a stage
+    new_map = [:]
+    
+    for (def step in steps) {
+        new_map = new_map << step
+    }
+    
+    stage(stage_name) {
+      parallel new_map
+    }
+}
 
 def assign_node_labels(args) {
+  // This function allows to assign instance labels to the generalized placeholders. 
+  // This serves two purposes:
+  // 1. Allow generalized placeholders (e.g. NODE_WINDOWS_CPU) in the job definition
+  //    in order to abstract away the underlying node label. This allows to schedule a job
+  //    onto a different node for testing or security reasons. This could be, for example,
+  //    when you want to test a new set of slaves on separate labels or when a job should
+  //    only be run on restricted slaves
+  // 2. Restrict the allowed job types within a Jenkinsfile. For example, a UNIX-CPU-only
+  //    Jenkinsfile should not allowed access to Windows or GPU instances. This prevents
+  //    users from just copy&pasting something into an existing Jenkinsfile without
+  //    knowing about the limitations.
   NODE_LINUX_CPU = args.linux_cpu
   NODE_LINUX_GPU = args.linux_gpu
   NODE_LINUX_GPU_P3 = args.linux_gpu_p3
@@ -164,15 +246,18 @@ def main_wrapper(args) {
   // assign any caught errors here
   err = null
   try {
+    update_github_commit_status('PENDING', 'Job has been enqueued')
     args['core_logic']()
 
     // set build status to success at the end
     currentBuild.result = "SUCCESS"
+    update_github_commit_status('SUCCESS', 'Job succeeded')
   } catch (caughtError) {
     node(NODE_LINUX_CPU) {
       sh "echo caught ${caughtError}"
       err = caughtError
       currentBuild.result = "FAILURE"
+      update_github_commit_status('FAILURE', 'Job failed')
     }
   } finally {
     node(NODE_LINUX_CPU) {
diff --git a/ci/jenkins/Jenkins_steps.groovy b/ci/jenkins/Jenkins_steps.groovy
new file mode 100644
index 00000000000..f48a2673730
--- /dev/null
+++ b/ci/jenkins/Jenkins_steps.groovy
@@ -0,0 +1,1137 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// This file contains the steps that will be used in the 
+// Jenkins pipelines
+
+utils = load('ci/Jenkinsfile_utils.groovy')
+
+// mxnet libraries
+mx_lib = 'lib/libmxnet.so, lib/libmxnet.a, 3rdparty/dmlc-core/libdmlc.a, 3rdparty/tvm/nnvm/lib/libnnvm.a'
+
+// Python wheels
+mx_pip = 'build/*.whl'
+
+// for scala build, need to pass extra libs when run with dist_kvstore
+mx_dist_lib = 'lib/libmxnet.so, lib/libmxnet.a, 3rdparty/dmlc-core/libdmlc.a, 3rdparty/tvm/nnvm/lib/libnnvm.a, 3rdparty/ps-lite/build/libps.a, deps/lib/libprotobuf-lite.a, deps/lib/libzmq.a'
+// mxnet cmake libraries, in cmake builds we do not produce a libnvvm static library by default.
+mx_cmake_lib = 'build/libmxnet.so, build/libmxnet.a, build/3rdparty/dmlc-core/libdmlc.a, build/tests/mxnet_unit_tests, build/3rdparty/openmp/runtime/src/libomp.so'
+// mxnet cmake libraries, in cmake builds we do not produce a libnvvm static library by default.
+mx_cmake_lib_debug = 'build/libmxnet.so, build/libmxnet.a, build/3rdparty/dmlc-core/libdmlc.a, build/tests/mxnet_unit_tests'
+mx_cmake_mkldnn_lib = 'build/libmxnet.so, build/libmxnet.a, build/3rdparty/dmlc-core/libdmlc.a, build/tests/mxnet_unit_tests, build/3rdparty/openmp/runtime/src/libomp.so, build/3rdparty/mkldnn/src/libmkldnn.so.0'
+mx_mkldnn_lib = 'lib/libmxnet.so, lib/libmxnet.a, lib/libiomp5.so, lib/libmkldnn.so.0, lib/libmklml_intel.so, 3rdparty/dmlc-core/libdmlc.a, 3rdparty/tvm/nnvm/lib/libnnvm.a'
+mx_tensorrt_lib = 'lib/libmxnet.so, lib/libnvonnxparser_runtime.so.0, lib/libnvonnxparser.so.0, lib/libonnx_proto.so, lib/libonnx.so'
+mx_lib_cpp_examples = 'lib/libmxnet.so, lib/libmxnet.a, 3rdparty/dmlc-core/libdmlc.a, 3rdparty/tvm/nnvm/lib/libnnvm.a, 3rdparty/ps-lite/build/libps.a, deps/lib/libprotobuf-lite.a, deps/lib/libzmq.a, build/cpp-package/example/*'
+mx_lib_cpp_examples_cpu = 'build/libmxnet.so, build/cpp-package/example/*'
+
+// Python unittest for CPU
+// Python 2
+def python2_ut(docker_container_name) {
+  timeout(time: max_time, unit: 'MINUTES') {
+    utils.docker_run(docker_container_name, 'unittest_ubuntu_python2_cpu', false)
+  }
+}
+
+// Python 3
+def python3_ut(docker_container_name) {
+  timeout(time: max_time, unit: 'MINUTES') {
+    utils.docker_run(docker_container_name, 'unittest_ubuntu_python3_cpu', false)
+  }
+}
+
+// Python 3
+def python3_ut_asan(docker_container_name) {
+  timeout(time: max_time, unit: 'MINUTES') {
+    utils.docker_run(docker_container_name, 'unittest_ubuntu_python3_cpu_asan', false)
+  }
+}
+
+def python3_ut_mkldnn(docker_container_name) {
+  timeout(time: max_time, unit: 'MINUTES') {
+    utils.docker_run(docker_container_name, 'unittest_ubuntu_python3_cpu_mkldnn', false)
+  }
+}
+
+// GPU test has two parts. 1) run unittest on GPU, 2) compare the results on
+// both CPU and GPU
+// Python 2
+def python2_gpu_ut(docker_container_name) {
+  timeout(time: max_time, unit: 'MINUTES') {
+    utils.docker_run(docker_container_name, 'unittest_ubuntu_python2_gpu', true)
+  }
+}
+
+// Python 3
+def python3_gpu_ut(docker_container_name) {
+  timeout(time: max_time, unit: 'MINUTES') {
+    utils.docker_run(docker_container_name, 'unittest_ubuntu_python3_gpu', true)
+  }
+}
+
+// Python 3 NOCUDNN
+def python3_gpu_ut_nocudnn(docker_container_name) {
+  timeout(time: max_time, unit: 'MINUTES') {
+    utils.docker_run(docker_container_name, 'unittest_ubuntu_python3_gpu_nocudnn', true)
+  }
+}
+
+//------------------------------------------------------------------------------------------
+
+def compile_unix_cpu_openblas() {
+    return ['CPU: Openblas': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-openblas') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_openblas', false)
+            utils.pack_lib('cpu', mx_dist_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_openblas_debug_cpu() {
+    return ['CPU: Openblas, debug': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-openblas') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_cmake_debug', false)
+            utils.pack_lib('cpu_debug', mx_cmake_lib_debug, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_mkldnn_cpu() {
+    return ['CPU: MKLDNN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-mkldnn-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_mkldnn', false)
+            utils.pack_lib('mkldnn_cpu', mx_mkldnn_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_mkldnn_gpu() {
+    return ['GPU: MKLDNN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-mkldnn-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_build_cuda', 'build_ubuntu_gpu_mkldnn', false)
+            utils.pack_lib('mkldnn_gpu', mx_mkldnn_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_mkldnn_nocudnn_gpu() {
+    return ['GPU: MKLDNN_CUDNNOFF': {
+       node(NODE_LINUX_CPU) {
+         ws('workspace/build-mkldnn-gpu-nocudnn') {
+           timeout(time: max_time, unit: 'MINUTES') {
+             utils.init_git()
+             utils.docker_run('ubuntu_build_cuda', 'build_ubuntu_gpu_mkldnn_nocudnn', false)
+             utils.pack_lib('mkldnn_gpu_nocudnn', mx_mkldnn_lib, true)
+           }
+         }
+       }
+    }]
+}
+
+def compile_unix_full_gpu() {
+    return ['GPU: CUDA9.1+cuDNN7': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_build_cuda', 'build_ubuntu_gpu_cuda91_cudnn7', false)
+            utils.pack_lib('gpu', mx_lib_cpp_examples, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_cmake_mkldnn_gpu() {
+    return ['GPU: CMake MKLDNN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cmake-mkldnn-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_gpu', 'build_ubuntu_gpu_cmake_mkldnn', false)
+            utils.pack_lib('cmake_mkldnn_gpu', mx_cmake_mkldnn_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_cmake_gpu() {
+    return ['GPU: CMake': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cmake-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_gpu', 'build_ubuntu_gpu_cmake', false)
+            utils.pack_lib('cmake_gpu', mx_cmake_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_tensorrt_gpu() {
+    return ['TensorRT': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-tensorrt') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_gpu_tensorrt', 'build_ubuntu_gpu_tensorrt', false)
+            utils.pack_lib('tensorrt', mx_tensorrt_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_centos7_cpu() {
+    return ['CPU: CentOS 7': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-centos7-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('centos7_cpu', 'build_centos7_cpu', false)
+            utils.pack_lib('centos7_cpu', mx_dist_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_centos7_cpu_mkldnn() {
+    return ['CPU: CentOS 7 MKLDNN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-centos7-mkldnn') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('centos7_cpu', 'build_centos7_mkldnn', false)
+            utils.pack_lib('centos7_mkldnn', mx_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_centos7_gpu() {
+    return ['GPU: CentOS 7': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-centos7-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('centos7_gpu', 'build_centos7_gpu', false)
+            utils.pack_lib('centos7_gpu', mx_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_clang_3_9_cpu() {
+    return ['CPU: Clang 3.9': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-clang39') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_clang39', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_clang_6_cpu() {
+    return ['CPU: Clang 6': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-clang60') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_clang60', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_clang_tidy_cpu() {
+    return ['CPU: Clang Tidy': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-clang60_tidy') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_clang_tidy', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_clang_3_9_mkldnn_cpu() {
+    return ['CPU: Clang 3.9 MKLDNN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-mkldnn-clang39') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_clang39_mkldnn', false)
+            utils.pack_lib('mkldnn_cpu_clang3', mx_mkldnn_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_clang_6_mkldnn_cpu() {
+    return ['CPU: Clang 6 MKLDNN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-mkldnn-clang60') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_clang60_mkldnn', false)
+            utils.pack_lib('mkldnn_cpu_clang6', mx_mkldnn_lib, true)
+          }
+        }
+      }
+    }]
+}
+
+def compile_armv8_jetson_gpu() {
+    return ['NVidia Jetson / ARMv8':{
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-jetson-armv8') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('jetson', 'build_jetson', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_armv7_cpu() {
+    return ['ARMv7':{
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-ARMv7') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('armv7', 'build_armv7', false)
+            utils.pack_lib('armv7', mx_pip)
+          }
+        }
+      }
+    }]
+}
+
+def compile_armv6_cpu() {
+    return ['ARMv6':{
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-ARMv6') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('armv6', 'build_armv6', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_armv8_cpu() {
+    return ['ARMv8':{
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-ARMv8') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('armv8', 'build_armv8', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_armv8_android_cpu() {
+    return ['Android / ARMv8':{
+      node(NODE_LINUX_CPU) {
+        ws('workspace/android64') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('android_armv8', 'build_android_armv8', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_armv7_android_cpu() {
+    return ['Android / ARMv7':{
+      node(NODE_LINUX_CPU) {
+        ws('workspace/androidv7') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('android_armv7', 'build_android_armv7', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_asan_cpu() {
+    return ['CPU: ASAN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-cpu-asan') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_cmake_asan', false)
+            utils.pack_lib('cpu_asan', mx_lib_cpp_examples_cpu)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_amalgamation_min() {
+    return ['Amalgamation MIN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/amalgamationmin') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_amalgamation_min', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_unix_amalgamation() {
+    return ['Amalgamation': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/amalgamation') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'build_ubuntu_amalgamation', false)
+          }
+        }
+      }
+    }]
+}
+
+def compile_windows_cpu() {
+    return ['Build CPU windows':{
+      node(NODE_WINDOWS_CPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/build-cpu') {
+            withEnv(['OpenBLAS_HOME=C:\\mxnet\\openblas', 'OpenCV_DIR=C:\\mxnet\\opencv_vc14', 'CUDA_PATH=C:\\CUDA\\v8.0']) {
+              utils.init_git_win()
+              powershell 'python ci/build_windows.py -f WIN_CPU'
+              stash includes: 'windows_package.7z', name: 'windows_package_cpu'
+            }
+          }
+        }
+      }
+    }]
+}
+
+def compile_windows_gpu() {
+    return ['Build GPU windows':{
+      node(NODE_WINDOWS_CPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/build-gpu') {
+            withEnv(['OpenBLAS_HOME=C:\\mxnet\\openblas', 'OpenCV_DIR=C:\\mxnet\\opencv_vc14', 'CUDA_PATH=C:\\CUDA\\v8.0']) {
+              utils.init_git_win()
+              powershell 'python ci/build_windows.py -f WIN_GPU'
+              stash includes: 'windows_package.7z', name: 'windows_package_gpu'
+            }
+          }
+        }
+      }
+    }]
+}
+
+def compile_windows_gpu_mkldnn() {
+    return ['Build GPU MKLDNN windows':{
+      node(NODE_WINDOWS_CPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/build-gpu') {
+            withEnv(['OpenBLAS_HOME=C:\\mxnet\\openblas', 'OpenCV_DIR=C:\\mxnet\\opencv_vc14', 'CUDA_PATH=C:\\CUDA\\v8.0','BUILD_NAME=vc14_gpu_mkldnn']) {
+              utils.init_git_win()
+              powershell 'python ci/build_windows.py -f WIN_GPU_MKLDNN'
+              stash includes: 'windows_package.7z', name: 'windows_package_gpu_mkldnn'
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python2_cpu() {
+    return ['Python2: CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-python2-cpu') {
+          try {
+            utils.unpack_and_init('cpu', mx_lib, true)
+            python2_ut('ubuntu_cpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_unittest.xml', 'nosetests_python2_cpu_unittest.xml')
+            utils.collect_test_results_unix('nosetests_train.xml', 'nosetests_python2_cpu_train.xml')
+            utils.collect_test_results_unix('nosetests_quantization.xml', 'nosetests_python2_cpu_quantization.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python2_gpu() {
+    return ['Python2: GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-python2-gpu') {
+          try {
+            utils.unpack_and_init('gpu', mx_lib, true)
+            python2_gpu_ut('ubuntu_gpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_gpu.xml', 'nosetests_python2_gpu.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python2_quantize_gpu() {
+    return ['Python2: Quantize GPU': {
+      node(NODE_LINUX_GPU_P3) {
+        ws('workspace/ut-python2-quantize-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            try {
+              utils.unpack_and_init('gpu', mx_lib, true)
+              utils.docker_run('ubuntu_gpu', 'unittest_ubuntu_python2_quantization_gpu', true)
+              utils.publish_test_coverage()
+            } finally {
+              utils.collect_test_results_unix('nosetests_quantization_gpu.xml', 'nosetests_python2_quantize_gpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python2_mkldnn_gpu() {
+    return ['Python2: MKLDNN-GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-python2-mkldnn-gpu') {
+          try {
+            utils.unpack_and_init('mkldnn_gpu', mx_mkldnn_lib, true)
+            python2_gpu_ut('ubuntu_gpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_gpu.xml', 'nosetests_python2_mkldnn_gpu.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_cpu() {
+    return ['Python3: CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-python3-cpu') {
+          try {
+            utils.unpack_and_init('cpu', mx_lib, true)
+            python3_ut('ubuntu_cpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_unittest.xml', 'nosetests_python3_cpu_unittest.xml')
+            utils.collect_test_results_unix('nosetests_quantization.xml', 'nosetests_python3_cpu_quantization.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_gpu() {
+    return ['Python3: GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-python3-gpu') {
+          try {
+            utils.unpack_and_init('gpu', mx_lib, true)
+            python3_gpu_ut('ubuntu_gpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_gpu.xml', 'nosetests_python3_gpu.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_quantize_gpu() {
+    return ['Python3: Quantize GPU': {
+      node(NODE_LINUX_GPU_P3) {
+        ws('workspace/ut-python3-quantize-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            try {
+              utils.unpack_and_init('gpu', mx_lib, true)
+              utils.docker_run('ubuntu_gpu', 'unittest_ubuntu_python3_quantization_gpu', true)
+              utils.publish_test_coverage()
+            } finally {
+              utils.collect_test_results_unix('nosetests_quantization_gpu.xml', 'nosetests_python3_quantize_gpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_debug_cpu() {
+    return ['Python3: CPU debug': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-python3-cpu-debug') {
+          try {
+            utils.unpack_and_init('cpu_debug', mx_cmake_lib_debug, true)
+            python3_ut('ubuntu_cpu')
+          } finally {
+            utils.collect_test_results_unix('nosetests_unittest.xml', 'nosetests_python3_cpu_debug_unittest.xml')
+            utils.collect_test_results_unix('nosetests_quantization.xml', 'nosetests_python3_cpu_debug_quantization.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python2_mkldnn_cpu() {
+    return ['Python2: MKLDNN-CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-python2-mkldnn-cpu') {
+          try {
+            utils.unpack_and_init('mkldnn_cpu', mx_mkldnn_lib, true)
+            python2_ut('ubuntu_cpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_unittest.xml', 'nosetests_python2_mkldnn_cpu_unittest.xml')
+            utils.collect_test_results_unix('nosetests_train.xml', 'nosetests_python2_mkldnn_cpu_train.xml')
+            utils.collect_test_results_unix('nosetests_quantization.xml', 'nosetests_python2_mkldnn_cpu_quantization.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_mkldnn_cpu() {
+    return ['Python3: MKLDNN-CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-python3-mkldnn-cpu') {
+          try {
+            utils.unpack_and_init('mkldnn_cpu', mx_mkldnn_lib, true)
+            python3_ut_mkldnn('ubuntu_cpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_unittest.xml', 'nosetests_python3_mkldnn_cpu_unittest.xml')
+            utils.collect_test_results_unix('nosetests_mkl.xml', 'nosetests_python3_mkldnn_cpu_mkl.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_mkldnn_gpu() {
+    return ['Python3: MKLDNN-GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-python3-mkldnn-gpu') {
+          try {
+            utils.unpack_and_init('mkldnn_gpu', mx_mkldnn_lib, true)
+            python3_gpu_ut('ubuntu_gpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_gpu.xml', 'nosetests_python3_mkldnn_gpu.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_mkldnn_nocudnn_gpu() {
+    return ['Python3: MKLDNN-GPU-NOCUDNN': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-python3-mkldnn-gpu-nocudnn') {
+          try {
+            utils.unpack_and_init('mkldnn_gpu_nocudnn', mx_mkldnn_lib, true)
+            python3_gpu_ut_nocudnn('ubuntu_gpu')
+            utils.publish_test_coverage()
+          } finally {
+            utils.collect_test_results_unix('nosetests_gpu.xml', 'nosetests_python3_mkldnn_gpu_nocudnn.xml')
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_tensorrt_gpu() {
+    return ['Python3: TensorRT GPU': {
+      node(NODE_LINUX_GPU_P3) {
+        ws('workspace/build-tensorrt') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            try {
+              utils.unpack_and_init('tensorrt', mx_tensorrt_lib, true)
+              utils.docker_run('ubuntu_gpu_tensorrt', 'unittest_ubuntu_tensorrt_gpu', true)
+              utils.publish_test_coverage()
+            } finally {
+              utils.collect_test_results_unix('nosetests_tensorrt.xml', 'nosetests_python3_tensorrt_gpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_python3_integration_gpu() {
+    return ['Python Integration GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/it-python-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('gpu', mx_lib, true)
+            utils.docker_run('ubuntu_gpu', 'integrationtest_ubuntu_gpu_python', true)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_caffe_gpu() {
+    return ['Caffe GPU': {
+        node(NODE_LINUX_GPU) {
+            ws('workspace/it-caffe') {
+            timeout(time: max_time, unit: 'MINUTES') {
+                utils.init_git()
+                utils.unpack_lib('gpu', mx_lib)
+                utils.docker_run('ubuntu_gpu', 'integrationtest_ubuntu_gpu_caffe', true)
+                utils.publish_test_coverage()
+            }
+            }
+        }
+    }]
+}
+
+def test_unix_cpp_package_gpu() {
+    return ['cpp-package GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/it-cpp-package') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('gpu', mx_lib_cpp_examples, true)
+            utils.docker_run('ubuntu_gpu', 'integrationtest_ubuntu_gpu_cpp_package', true)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_scala_cpu() {
+    return ['Scala: CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-scala-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cpu', mx_dist_lib, true)
+            utils.docker_run('ubuntu_cpu', 'unittest_ubuntu_cpu_scala', false)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_scala_gpu() {
+    return ['Scala: GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-scala-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('gpu', mx_dist_lib, true)
+            utils.docker_run('ubuntu_gpu', 'integrationtest_ubuntu_gpu_scala', true)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_clojure_cpu() {
+    return ['Clojure: CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-clojure-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cpu', mx_dist_lib, true)
+            utils.docker_run('ubuntu_cpu', 'unittest_ubuntu_cpu_clojure', false)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_r_cpu() {
+    return ['Perl: CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-perl-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cpu', mx_lib, true)
+            utils.docker_run('ubuntu_cpu', 'unittest_ubuntu_cpugpu_perl', false)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_cpp_gpu() {
+    return ['Cpp: GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-cpp-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cmake_gpu', mx_cmake_lib, true)
+            utils.docker_run('ubuntu_gpu', 'unittest_ubuntu_gpu_cpp', true)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_cpp_mkldnn_gpu() {
+    return ['Cpp: MKLDNN+GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-cpp-mkldnn-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cmake_mkldnn_gpu', mx_cmake_mkldnn_lib, true)
+            utils.docker_run('ubuntu_gpu', 'unittest_ubuntu_gpu_cpp', true)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_r_gpu() {
+    return ['Perl: GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/ut-perl-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('gpu', mx_lib, true)
+            utils.docker_run('ubuntu_gpu', 'unittest_ubuntu_cpugpu_perl', true)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_julia_cpu() {
+    return ['Julia 0.6: CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-julia06-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cpu', mx_lib)
+            utils.docker_run('ubuntu_cpu', 'unittest_ubuntu_cpu_julia06', false)
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_onnx_cpu() {
+    return ['Onnx CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/it-onnx-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cpu', mx_lib, true)
+            utils.docker_run('ubuntu_cpu', 'integrationtest_ubuntu_cpu_onnx', false)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_distributed_kvstore_cpu() {
+    return ['dist-kvstore tests CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/it-dist-kvstore') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cpu', mx_lib, true)
+            utils.docker_run('ubuntu_cpu', 'integrationtest_ubuntu_cpu_dist_kvstore', false)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_unix_distributed_kvstore_gpu() {
+    return ['dist-kvstore tests GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/it-dist-kvstore') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('gpu', mx_lib, true)
+            utils.docker_run('ubuntu_gpu', 'integrationtest_ubuntu_gpu_dist_kvstore', true)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_centos7_python3_cpu() {
+    return ['Python3: CentOS 7 CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/build-centos7-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            try {
+              utils.unpack_and_init('centos7_cpu', mx_lib, true)
+              utils.docker_run('centos7_cpu', 'unittest_centos7_cpu', false)
+              utils.publish_test_coverage()
+            } finally {
+              utils.collect_test_results_unix('nosetests_unittest.xml', 'nosetests_python3_centos7_cpu_unittest.xml')
+              utils.collect_test_results_unix('nosetests_train.xml', 'nosetests_python3_centos7_cpu_train.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_centos7_python3_gpu() {
+    return ['Python3: CentOS 7 GPU': {
+      node(NODE_LINUX_GPU) {
+        ws('workspace/build-centos7-gpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            try {
+              utils.unpack_and_init('centos7_gpu', mx_lib, true)
+              utils.docker_run('centos7_gpu', 'unittest_centos7_gpu', true)
+              utils.publish_test_coverage()
+            } finally {
+              utils.collect_test_results_unix('nosetests_gpu.xml', 'nosetests_python3_centos7_gpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_centos7_scala_cpu() {
+    return ['Scala: CentOS CPU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-scala-centos7-cpu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('centos7_cpu', mx_dist_lib, true)
+            utils.docker_run('centos7_cpu', 'unittest_centos7_cpu_scala', false)
+            utils.publish_test_coverage()
+          }
+        }
+      }
+    }]
+}
+
+def test_windows_python2_cpu() {
+    return ['Python 2: CPU Win':{
+      node(NODE_WINDOWS_CPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/ut-python-cpu') {
+            try {
+              utils.init_git_win()
+              unstash 'windows_package_cpu'
+              powershell 'ci/windows/test_py2_cpu.ps1'
+            } finally {
+              utils.collect_test_results_windows('nosetests_unittest.xml', 'nosetests_unittest_windows_python2_cpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_windows_python2_gpu() {
+    return ['Python 2: GPU Win':{
+      node(NODE_WINDOWS_GPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/ut-python-gpu') {
+            try {
+              utils.init_git_win()
+              unstash 'windows_package_gpu'
+              powershell 'ci/windows/test_py2_gpu.ps1'
+            } finally {
+              utils.collect_test_results_windows('nosetests_forward.xml', 'nosetests_gpu_forward_windows_python2_gpu.xml')
+              utils.collect_test_results_windows('nosetests_operator.xml', 'nosetests_gpu_operator_windows_python2_gpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_windows_python3_gpu() {
+    return ['Python 3: GPU Win':{
+      node(NODE_WINDOWS_GPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/ut-python-gpu') {
+            try {
+              utils.init_git_win()
+              unstash 'windows_package_gpu'
+              powershell 'ci/windows/test_py3_gpu.ps1'
+            } finally {
+              utils.collect_test_results_windows('nosetests_forward.xml', 'nosetests_gpu_forward_windows_python3_gpu.xml')
+              utils.collect_test_results_windows('nosetests_operator.xml', 'nosetests_gpu_operator_windows_python3_gpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_windows_python3_gpu_mkldnn() {
+    return ['Python 3: MKLDNN-GPU Win':{
+      node(NODE_WINDOWS_GPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/ut-python-gpu') {
+            try {
+              utils.init_git_win()
+              unstash 'windows_package_gpu_mkldnn'
+              powershell 'ci/windows/test_py3_gpu.ps1'
+            } finally {
+              utils.collect_test_results_windows('nosetests_forward.xml', 'nosetests_gpu_forward_windows_python3_gpu_mkldnn.xml')
+              utils.collect_test_results_windows('nosetests_operator.xml', 'nosetests_gpu_operator_windows_python3_gpu_mkldnn.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_windows_python3_cpu() {
+    return ['Python 3: CPU Win': {
+      node(NODE_WINDOWS_CPU) {
+        timeout(time: max_time, unit: 'MINUTES') {
+          ws('workspace/ut-python-cpu') {
+            try {
+              utils.init_git_win()
+              unstash 'windows_package_cpu'
+              powershell 'ci/windows/test_py3_cpu.ps1'
+            } finally {
+              utils.collect_test_results_windows('nosetests_unittest.xml', 'nosetests_unittest_windows_python3_cpu.xml')
+            }
+          }
+        }
+      }
+    }]
+}
+
+def test_qemu_armv7_cpu() {
+    return ['ARMv7 QEMU': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-armv7-qemu') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('armv7', mx_pip)
+            sh "ci/build.py --docker-registry ${env.DOCKER_CACHE_REGISTRY} -p test.arm_qemu ./runtime_functions.py run_ut_py3_qemu"
+          }
+        }
+      }
+    }]
+}
+
+def docs_website() {
+    return ['Docs': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/docs') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.init_git()
+            utils.docker_run('ubuntu_cpu', 'deploy_docs', false)
+
+            master_url = utils.get_jenkins_master_url()
+            if ( master_url == 'jenkins.mxnet-ci.amazon-ml.com') {
+                sh "ci/other/ci_deploy_doc.sh ${env.BRANCH_NAME} ${env.BUILD_NUMBER}"
+            } else {
+                print "Skipping staging documentation publishing since we are not running in prod. Host: {$master_url}" 
+            }
+          }
+        }
+      }
+    }]
+}
+
+def docs_julia() {
+    return ['Julia docs': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/julia-docs') {
+          timeout(time: max_time, unit: 'MINUTES') {
+            utils.unpack_and_init('cpu', mx_lib)
+            utils.docker_run('ubuntu_cpu', 'deploy_jl_docs', false)
+          }
+        }
+      }
+    }]
+}
+
+def misc_asan_cpu() {
+    return ['CPU ASAN': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/ut-python3-cpu-asan') {
+            utils.unpack_and_init('cpu_asan', mx_lib_cpp_examples_cpu)
+            utils.docker_run('ubuntu_cpu', 'integrationtest_ubuntu_cpu_asan', false)
+        }
+      }
+    }]
+}
+
+def sanity_lint() {
+    return ['Lint': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/sanity-lint') {
+          utils.init_git()
+          utils.docker_run('ubuntu_cpu', 'sanity_check', false)
+        }
+      }
+    }]
+}
+
+def sanity_rat_license() {
+    return ['RAT License': {
+      node(NODE_LINUX_CPU) {
+        ws('workspace/sanity-rat') {
+          utils.init_git()
+          utils.docker_run('ubuntu_rat', 'nightly_test_rat_check', false)
+        }
+      }
+    }]
+}
+
+return this
diff --git a/ci/jenkins/Jenkinsfile_centos_cpu b/ci/jenkins/Jenkinsfile_centos_cpu
new file mode 100644
index 00000000000..6d704bf008c
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_centos_cpu
@@ -0,0 +1,53 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_centos7_cpu(),
+    custom_steps.compile_centos7_cpu_mkldnn()
+  ]) 
+
+  utils.parallel_stage('Tests', [
+    custom_steps.test_centos7_python3_cpu(),
+    custom_steps.test_centos7_scala_cpu()
+  ]) 
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_centos_gpu b/ci/jenkins/Jenkinsfile_centos_gpu
new file mode 100644
index 00000000000..d99177eb32c
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_centos_gpu
@@ -0,0 +1,51 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', linux_gpu: 'mxnetlinux-gpu', linux_gpu_p3: 'mxnetlinux-gpu-p3')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_centos7_gpu()
+  ]) 
+  
+  utils.parallel_stage('Tests', [
+    custom_steps.test_centos7_python3_gpu()
+  ]) 
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_clang b/ci/jenkins/Jenkinsfile_clang
new file mode 100644
index 00000000000..2fa9b83fe43
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_clang
@@ -0,0 +1,51 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', linux_gpu: 'mxnetlinux-gpu', linux_gpu_p3: 'mxnetlinux-gpu-p3')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_unix_clang_3_9_cpu(),
+    custom_steps.compile_unix_clang_6_cpu(),
+    custom_steps.compile_unix_clang_tidy_cpu(),
+    custom_steps.compile_unix_clang_3_9_mkldnn_cpu(),
+    custom_steps.compile_unix_clang_6_mkldnn_cpu()
+  ]) 
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_edge b/ci/jenkins/Jenkinsfile_edge
new file mode 100644
index 00000000000..64324ccff55
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_edge
@@ -0,0 +1,56 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', linux_gpu: 'mxnetlinux-gpu', linux_gpu_p3: 'mxnetlinux-gpu-p3')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_armv8_jetson_gpu(),
+    custom_steps.compile_armv7_cpu(),
+    custom_steps.compile_armv6_cpu(),
+    custom_steps.compile_armv8_cpu(),
+    custom_steps.compile_armv8_android_cpu(),
+    custom_steps.compile_armv7_android_cpu()
+  ]) 
+
+  utils.parallel_stage('Tests', [
+    custom_steps.test_qemu_armv7_cpu()
+  ]) 
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_miscellaneous b/ci/jenkins/Jenkinsfile_miscellaneous
new file mode 100644
index 00000000000..367cd6ffba0
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_miscellaneous
@@ -0,0 +1,54 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', linux_gpu: 'mxnetlinux-gpu', linux_gpu_p3: 'mxnetlinux-gpu-p3', windows_cpu: 'mxnetwindows-cpu', windows_gpu: 'mxnetwindows-gpu')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_unix_asan_cpu(),
+    custom_steps.compile_unix_amalgamation_min(),
+    custom_steps.compile_unix_amalgamation()
+  ]) 
+
+  utils.parallel_stage('Tests', [
+    custom_steps.misc_asan_cpu()
+  ]) 
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_sanity b/ci/jenkins/Jenkinsfile_sanity
new file mode 100644
index 00000000000..cb74b0354b2
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_sanity
@@ -0,0 +1,48 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', linux_gpu: 'mxnetlinux-gpu', linux_gpu_p3: 'mxnetlinux-gpu-p3', windows_cpu: 'mxnetwindows-cpu', windows_gpu: 'mxnetwindows-gpu')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Sanity Check', [
+    custom_steps.sanity_lint(),
+    custom_steps.sanity_rat_license()
+  ])    
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_unix_cpu b/ci/jenkins/Jenkinsfile_unix_cpu
new file mode 100644
index 00000000000..65da4169019
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_unix_cpu
@@ -0,0 +1,68 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_unix_cpu_openblas(),
+    custom_steps.compile_unix_openblas_debug_cpu(),
+    custom_steps.compile_unix_mkldnn_cpu()
+  ]) 
+
+  utils.parallel_stage('Tests', [
+    custom_steps.test_unix_python2_cpu(),
+    custom_steps.test_unix_python3_cpu(),
+    custom_steps.test_unix_python3_debug_cpu(),
+    custom_steps.test_unix_python2_mkldnn_cpu(),
+    custom_steps.test_unix_python3_mkldnn_cpu(),
+    custom_steps.test_unix_scala_cpu(),
+    custom_steps.test_unix_clojure_cpu(),
+    custom_steps.test_unix_r_cpu(),
+    custom_steps.test_unix_julia_cpu(),
+    custom_steps.test_unix_onnx_cpu(),
+
+    /*  Disabled due to master build failure:
+     *  http://jenkins.mxnet-ci.amazon-ml.com/blue/organizations/jenkins/incubator-mxnet/detail/master/1221/pipeline/
+     *  https://github.com/apache/incubator-mxnet/issues/11801
+    custom_steps.test_unix_distributed_kvstore_cpu()
+    */
+  ])
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_unix_gpu b/ci/jenkins/Jenkinsfile_unix_gpu
new file mode 100644
index 00000000000..f02458deab4
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_unix_gpu
@@ -0,0 +1,73 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', linux_gpu: 'mxnetlinux-gpu', linux_gpu_p3: 'mxnetlinux-gpu-p3')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_unix_mkldnn_gpu(),
+    custom_steps.compile_unix_mkldnn_nocudnn_gpu(),
+    custom_steps.compile_unix_full_gpu(),
+    custom_steps.compile_unix_cmake_mkldnn_gpu(),
+    custom_steps.compile_unix_cmake_gpu(),
+    custom_steps.compile_unix_tensorrt_gpu(),
+  ]) 
+
+  utils.parallel_stage('Tests', [
+    custom_steps.test_unix_python2_gpu(),
+    custom_steps.test_unix_python3_gpu(),
+    custom_steps.test_unix_python2_quantize_gpu(),
+    custom_steps.test_unix_python3_quantize_gpu(),
+    custom_steps.test_unix_python2_mkldnn_gpu(),
+    custom_steps.test_unix_python3_mkldnn_gpu(),
+    custom_steps.test_unix_python3_mkldnn_nocudnn_gpu(),
+    custom_steps.test_unix_python3_tensorrt_gpu(),
+    custom_steps.test_unix_r_gpu(),
+    custom_steps.test_unix_cpp_gpu(),
+    custom_steps.test_unix_cpp_mkldnn_gpu(),
+    custom_steps.test_unix_python3_integration_gpu(),
+    custom_steps.test_unix_cpp_package_gpu(),
+    custom_steps.test_unix_scala_gpu(),
+    custom_steps.test_unix_distributed_kvstore_gpu()
+
+    // Disabled due to: https://github.com/apache/incubator-mxnet/issues/11407
+    //custom_steps.test_unix_caffe_gpu()
+  ]) 
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_website b/ci/jenkins/Jenkinsfile_website
new file mode 100644
index 00000000000..a2c151e6280
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_website
@@ -0,0 +1,52 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_unix_cpu_openblas()
+  ])
+
+  utils.parallel_stage('Deploy', [
+    custom_steps.docs_website(),
+    custom_steps.docs_julia()
+  ])
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_windows_cpu b/ci/jenkins/Jenkinsfile_windows_cpu
new file mode 100644
index 00000000000..f7f5442f715
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_windows_cpu
@@ -0,0 +1,52 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', windows_cpu: 'mxnetwindows-cpu')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_windows_cpu()
+  ]) 
+
+  utils.parallel_stage('Tests', [
+    custom_steps.test_windows_python2_cpu(),
+    custom_steps.test_windows_python3_cpu()
+  ]) 
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)
diff --git a/ci/jenkins/Jenkinsfile_windows_gpu b/ci/jenkins/Jenkinsfile_windows_gpu
new file mode 100644
index 00000000000..906b6c7b52c
--- /dev/null
+++ b/ci/jenkins/Jenkinsfile_windows_gpu
@@ -0,0 +1,54 @@
+// -*- mode: groovy -*-
+
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Jenkins pipeline
+// See documents at https://jenkins.io/doc/book/pipeline/jenkinsfile/
+
+// timeout in minutes
+max_time = 120
+
+node('mxnetlinux-cpu') {
+  // Loading the utilities requires a node context unfortunately
+  checkout scm
+  utils = load('ci/Jenkinsfile_utils.groovy')
+  custom_steps = load('ci/jenkins/Jenkins_steps.groovy')
+}
+utils.assign_node_labels(linux_cpu: 'mxnetlinux-cpu', windows_cpu: 'mxnetwindows-cpu', windows_gpu: 'mxnetwindows-gpu')
+
+utils.main_wrapper(
+core_logic: {
+  utils.parallel_stage('Build', [
+    custom_steps.compile_windows_gpu(),
+    custom_steps.compile_windows_gpu_mkldnn()
+  ])
+
+  utils.parallel_stage('Tests', [
+    custom_steps.test_windows_python2_gpu(),
+    custom_steps.test_windows_python3_gpu(),
+    custom_steps.test_windows_python3_gpu_mkldnn()
+  ])
+}
+,
+failure_handler: {
+  // Only send email if master or release branches failed
+  if (currentBuild.result == "FAILURE" && (env.BRANCH_NAME == "master" || env.BRANCH_NAME.startsWith("v"))) {
+    emailext body: 'Build for MXNet branch ${BRANCH_NAME} has broken. Please view the build at ${BUILD_URL}', replyTo: '${EMAIL}', subject: '[BUILD FAILED] Branch ${BRANCH_NAME} build ${BUILD_NUMBER}', to: '${EMAIL}'
+  }
+}
+)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services