#!/usr/bin/groovy
// -*- mode: groovy -*-

/* Jenkins pipeline for Windows AMD64 target */

pipeline {
  agent none
  // Build stages
  stages {
    stage('Jenkins Win64: Get sources') {
      agent { label 'win64 && build' }
      steps {
        script {
          checkoutSrcs()
        }
        stash name: 'srcs'
        milestone ordinal: 1
      }
    }
    stage('Jenkins Win64: Build') {
      agent none
      steps {
        script {
          parallel ([
            'build-win64-cuda9.0': { BuildWin64() }
          ])
        }
        milestone ordinal: 2
      }
    }
    stage('Jenkins Win64: Test') {
      agent none
      steps {
        script {
          parallel ([
            'test-win64-cpu': { TestWin64CPU() },
            'test-win64-gpu-cuda9.0': { TestWin64GPU(cuda_target: 'cuda9') },
            'test-win64-gpu-cuda10.0': { TestWin64GPU(cuda_target: 'cuda10_0') },
            'test-win64-gpu-cuda10.1': { TestWin64GPU(cuda_target: 'cuda10_1') }
          ])
        }
        milestone ordinal: 3
      }
    }
  }
}

// check out source code from git
def checkoutSrcs() {
  retry(5) {
    try {
      timeout(time: 2, unit: 'MINUTES') {
        checkout scm
        sh 'git submodule update --init'
      }
    } catch (exc) {
      deleteDir()
      error "Failed to fetch source codes"
    }
  }
}

def BuildWin64() {
  node('win64 && build') {
    unstash name: 'srcs'
    echo "Building XGBoost for Windows AMD64 target..."
    bat "nvcc --version"
    bat """
    mkdir build
    cd build
    cmake .. -G"Visual Studio 15 2017 Win64" -DUSE_CUDA=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON
    """
    bat """
    cd build
    "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\MSBuild\\15.0\\Bin\\MSBuild.exe" xgboost.sln /m /p:Configuration=Release /nodeReuse:false
    """
    bat """
    cd python-package
    conda activate && python setup.py bdist_wheel --universal
    """
    echo "Insert vcomp140.dll (OpenMP runtime) into the wheel..."
    bat """
    cd python-package\\dist
    COPY /B ..\\..\\tests\\ci_build\\insert_vcomp140.py
    conda activate && python insert_vcomp140.py *.whl
    """
    echo 'Stashing Python wheel...'
    stash name: 'xgboost_whl', includes: 'python-package/dist/*.whl'
    archiveArtifacts artifacts: "python-package/dist/*.whl", allowEmptyArchive: true
    echo 'Stashing C++ test executable (testxgboost)...'
    stash name: 'xgboost_cpp_tests', includes: 'build/testxgboost.exe'
    deleteDir()
  }
}

def TestWin64CPU() {
  node('win64 && cpu') {
    unstash name: 'srcs'
    unstash name: 'xgboost_whl'
    echo "Test Win64 CPU"
    echo "Installing Python wheel..."
    bat "conda activate && (python -m pip uninstall -y xgboost || cd .)"
    bat """
    conda activate && for /R %%i in (python-package\\dist\\*.whl) DO python -m pip install "%%i"
    """
    echo "Running Python tests..."
    bat "conda activate && python -m pytest -v -s --fulltrace tests\\python"
    bat "conda activate && python -m pip uninstall -y xgboost"
    deleteDir()
  }
}

def TestWin64GPU(args) {
  node("win64 && gpu && ${args.cuda_target}") {
    unstash name: 'srcs'
    unstash name: 'xgboost_whl'
    unstash name: 'xgboost_cpp_tests'
    echo "Test Win64 GPU (${args.cuda_target})"
    bat "nvcc --version"
    echo "Running C++ tests..."
    bat "build\\testxgboost.exe"
    echo "Installing Python wheel..."
    bat "conda activate && (python -m pip uninstall -y xgboost || cd .)"
    bat """
    conda activate && for /R %%i in (python-package\\dist\\*.whl) DO python -m pip install "%%i"
    """
    echo "Running Python tests..."
    bat """
    conda activate && python -m pytest -v -s --fulltrace -m "(not slow) and (not mgpu)" tests\\python-gpu
    """
    bat "conda activate && python -m pip uninstall -y xgboost"
    deleteDir()
  }
}
