Skip to content

Commit ac9136e

Browse files
authored
Further improvements and savings in Jenkins pipeline (#5904)
* Publish artifacts only on the master and release branches * Build CUDA only for Compute Capability 7.5 when building PRs * Run all Windows jobs in a single worker image * Build nightly XGBoost4J SNAPSHOT JARs with Scala 2.12 only * Show skipped Python tests on Windows * Make Graphviz optional for Python tests * Add back C++ tests * Unstash xgboost_cpp_tests * Fix label to CUDA 10.1 * Install cuPy for CUDA 10.1 * Install jsonschema * Address reviewer's feedback
1 parent 6c0c872 commit ac9136e

File tree

8 files changed

+93
-59
lines changed

8 files changed

+93
-59
lines changed

Jenkinsfile

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,10 @@ def Doxygen() {
173173
sh """
174174
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/doxygen.sh ${BRANCH_NAME}
175175
"""
176-
echo 'Uploading doc...'
177-
s3Upload file: "build/${BRANCH_NAME}.tar.bz2", bucket: 'xgboost-docs', acl: 'PublicRead', path: "doxygen/${BRANCH_NAME}.tar.bz2"
176+
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
177+
echo 'Uploading doc...'
178+
s3Upload file: "build/${BRANCH_NAME}.tar.bz2", bucket: 'xgboost-docs', acl: 'PublicRead', path: "doxygen/${BRANCH_NAME}.tar.bz2"
179+
}
178180
deleteDir()
179181
}
180182
}
@@ -245,17 +247,24 @@ def BuildCUDA(args) {
245247
def container_type = "gpu_build"
246248
def docker_binary = "docker"
247249
def docker_args = "--build-arg CUDA_VERSION=${args.cuda_version}"
250+
def arch_flag = ""
251+
if (env.BRANCH_NAME != 'master' && !(env.BRANCH_NAME.startsWith('release'))) {
252+
arch_flag = "-DGPU_COMPUTE_VER=75"
253+
}
248254
sh """
249-
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_via_cmake.sh -DUSE_CUDA=ON -DUSE_NCCL=ON -DOPEN_MP:BOOL=ON -DHIDE_CXX_SYMBOLS=ON
255+
${dockerRun} ${container_type} ${docker_binary} ${docker_args} tests/ci_build/build_via_cmake.sh -DUSE_CUDA=ON -DUSE_NCCL=ON -DOPEN_MP:BOOL=ON -DHIDE_CXX_SYMBOLS=ON ${arch_flag}
250256
${dockerRun} ${container_type} ${docker_binary} ${docker_args} bash -c "cd python-package && rm -rf dist/* && python setup.py bdist_wheel --universal"
251257
${dockerRun} ${container_type} ${docker_binary} ${docker_args} python3 tests/ci_build/rename_whl.py python-package/dist/*.whl ${commit_id} manylinux2010_x86_64
252258
"""
253259
// Stash wheel for CUDA 10.0 target
254260
if (args.cuda_version == '10.0') {
255261
echo 'Stashing Python wheel...'
256262
stash name: 'xgboost_whl_cuda10', includes: 'python-package/dist/*.whl'
257-
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
258-
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', workingDir: 'python-package/dist', includePathPattern:'**/*.whl'
263+
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
264+
echo 'Uploading Python wheel...'
265+
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
266+
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', workingDir: 'python-package/dist', includePathPattern:'**/*.whl'
267+
}
259268
echo 'Stashing C++ test executable (testxgboost)...'
260269
stash name: 'xgboost_cpp_tests', includes: 'build/testxgboost'
261270
}
@@ -289,8 +298,10 @@ def BuildJVMDoc() {
289298
sh """
290299
${dockerRun} ${container_type} ${docker_binary} tests/ci_build/build_jvm_doc.sh ${BRANCH_NAME}
291300
"""
292-
echo 'Uploading doc...'
293-
s3Upload file: "jvm-packages/${BRANCH_NAME}.tar.bz2", bucket: 'xgboost-docs', acl: 'PublicRead', path: "${BRANCH_NAME}.tar.bz2"
301+
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
302+
echo 'Uploading doc...'
303+
s3Upload file: "jvm-packages/${BRANCH_NAME}.tar.bz2", bucket: 'xgboost-docs', acl: 'PublicRead', path: "${BRANCH_NAME}.tar.bz2"
304+
}
294305
deleteDir()
295306
}
296307
}

Jenkinsfile-win64

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ def commit_id // necessary to pass a variable from one stage to another
1010

1111
pipeline {
1212
agent none
13+
14+
// Setup common job properties
15+
options {
16+
timestamps()
17+
timeout(time: 240, unit: 'MINUTES')
18+
buildDiscarder(logRotator(numToKeepStr: '10'))
19+
preserveStashes()
20+
}
21+
1322
// Build stages
1423
stages {
1524
stage('Jenkins Win64: Initialize') {
@@ -29,7 +38,7 @@ pipeline {
2938
steps {
3039
script {
3140
parallel ([
32-
'build-win64-cuda10.0': { BuildWin64() }
41+
'build-win64-cuda10.1': { BuildWin64() }
3342
])
3443
}
3544
milestone ordinal: 2
@@ -40,8 +49,7 @@ pipeline {
4049
steps {
4150
script {
4251
parallel ([
43-
'test-win64-cpu': { TestWin64CPU() },
44-
'test-win64-gpu-cuda10.1': { TestWin64GPU(cuda_target: 'cuda10_1') }
52+
'test-win64-cuda10.1': { TestWin64() },
4553
])
4654
}
4755
milestone ordinal: 3
@@ -66,14 +74,18 @@ def checkoutSrcs() {
6674
}
6775

6876
def BuildWin64() {
69-
node('win64 && build && cuda10') {
77+
node('win64 && cuda10_unified') {
7078
unstash name: 'srcs'
7179
echo "Building XGBoost for Windows AMD64 target..."
7280
bat "nvcc --version"
81+
def arch_flag = ""
82+
if (env.BRANCH_NAME != 'master' && !(env.BRANCH_NAME.startsWith('release'))) {
83+
arch_flag = "-DGPU_COMPUTE_VER=75"
84+
}
7385
bat """
7486
mkdir build
7587
cd build
76-
cmake .. -G"Visual Studio 15 2017 Win64" -DUSE_CUDA=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON
88+
cmake .. -G"Visual Studio 15 2017 Win64" -DUSE_CUDA=ON -DCMAKE_VERBOSE_MAKEFILE=ON -DGOOGLE_TEST=ON -DUSE_DMLC_GTEST=ON ${arch_flag}
7789
"""
7890
bat """
7991
cd build
@@ -91,61 +103,41 @@ def BuildWin64() {
91103
"""
92104
echo 'Stashing Python wheel...'
93105
stash name: 'xgboost_whl', includes: 'python-package/dist/*.whl'
94-
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
95-
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', workingDir: 'python-package/dist', includePathPattern:'**/*.whl'
106+
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('release')) {
107+
echo 'Uploading Python wheel...'
108+
path = ("${BRANCH_NAME}" == 'master') ? '' : "${BRANCH_NAME}/"
109+
s3Upload bucket: 'xgboost-nightly-builds', path: path, acl: 'PublicRead', workingDir: 'python-package/dist', includePathPattern:'**/*.whl'
110+
}
96111
echo 'Stashing C++ test executable (testxgboost)...'
97112
stash name: 'xgboost_cpp_tests', includes: 'build/testxgboost.exe'
98113
stash name: 'xgboost_cli', includes: 'xgboost.exe'
99114
deleteDir()
100115
}
101116
}
102117

103-
def TestWin64CPU() {
104-
node('win64 && cpu') {
118+
def TestWin64() {
119+
node('win64 && cuda10_unified') {
105120
unstash name: 'srcs'
106121
unstash name: 'xgboost_whl'
107122
unstash name: 'xgboost_cli'
108-
echo "Test Win64 CPU"
109-
echo "Installing Python wheel..."
110-
bat "conda activate && (python -m pip uninstall -y xgboost || cd .)"
111-
bat """
112-
conda activate && for /R %%i in (python-package\\dist\\*.whl) DO python -m pip install "%%i"
113-
"""
114-
echo "Installing Python dependencies..."
115-
bat """
116-
conda activate && conda install -y hypothesis && conda upgrade scikit-learn pandas numpy hypothesis
117-
"""
118-
echo "Running Python tests..."
119-
bat "conda activate && python -m pytest -v -s --fulltrace tests\\python"
120-
bat "conda activate && python -m pip uninstall -y xgboost"
121-
deleteDir()
122-
}
123-
}
124-
125-
def TestWin64GPU(args) {
126-
node("win64 && gpu && ${args.cuda_target}") {
127-
unstash name: 'srcs'
128-
unstash name: 'xgboost_whl'
129123
unstash name: 'xgboost_cpp_tests'
130-
echo "Test Win64 GPU (${args.cuda_target})"
124+
echo "Test Win64"
131125
bat "nvcc --version"
132126
echo "Running C++ tests..."
133127
bat "build\\testxgboost.exe"
134-
echo "Installing Python wheel..."
135-
bat "conda activate && (python -m pip uninstall -y xgboost || cd .)"
136-
bat """
137-
conda activate && for /R %%i in (python-package\\dist\\*.whl) DO python -m pip install "%%i"
138-
"""
139128
echo "Installing Python dependencies..."
140-
def cuda_short_ver = args.cuda_target.replaceAll('_', '')
129+
def env_name = 'win64_' + UUID.randomUUID().toString().replaceAll('-', '')
130+
bat "conda env create -n ${env_name} --file=tests/ci_build/win64_conda_env.yml"
131+
echo "Installing Python wheel..."
141132
bat """
142-
conda activate && conda install -y hypothesis && conda upgrade scikit-learn pandas numpy hypothesis && python -m pip install cupy-${cuda_short_ver}
133+
conda activate ${env_name} && for /R %%i in (python-package\\dist\\*.whl) DO python -m pip install "%%i"
143134
"""
144135
echo "Running Python tests..."
136+
bat "conda activate ${env_name} && python -m pytest -v -s -rxXs --fulltrace tests\\python"
145137
bat """
146-
conda activate && python -m pytest -v -s --fulltrace -m "(not slow) and (not mgpu)" tests\\python-gpu
138+
conda activate ${env_name} && python -m pytest -v -s -rxXs --fulltrace -m "(not slow) and (not mgpu)" tests\\python-gpu
147139
"""
148-
bat "conda activate && python -m pip uninstall -y xgboost"
140+
bat "conda env remove --name ${env_name}"
149141
deleteDir()
150142
}
151143
}

tests/ci_build/deploy_jvm_packages.sh

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,5 @@ cd jvm-packages
2020
# Deploy to S3 bucket xgboost-maven-repo
2121
mvn --no-transfer-progress package deploy -P release-to-s3 -Dspark.version=${spark_version} -DskipTests
2222

23-
# Compile XGBoost4J with Scala 2.11 too
24-
mvn clean
25-
# Rename artifactId of all XGBoost4J packages with suffix _2.11
26-
sed -i -e 's/<artifactId>xgboost\(.*\)_[0-9\.]\+/<artifactId>xgboost\1_2.11/' $(find . -name pom.xml)
27-
# Modify scala.version and scala.binary.version fields
28-
sed -i -e 's/<scala\.version>[0-9\.]\+/<scala.version>2.11.12/' $(find . -name pom.xml)
29-
sed -i -e 's/<scala\.binary\.version>[0-9\.]\+/<scala.binary.version>2.11/' $(find . -name pom.xml)
30-
31-
# Re-build and deploy
32-
mvn --no-transfer-progress package deploy -P release-to-s3 -Dspark.version=${spark_version} -DskipTests
33-
3423
set +x
3524
set +e

tests/ci_build/win64_conda_env.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: win64_env
2+
channels:
3+
- conda-forge
4+
dependencies:
5+
- python=3.7
6+
- numpy
7+
- scipy
8+
- matplotlib
9+
- scikit-learn
10+
- pandas
11+
- pytest
12+
- python-graphviz
13+
- boto3
14+
- hypothesis
15+
- jsonschema
16+
- pip
17+
- pip:
18+
- cupy-cuda101

tests/python-gpu/test_gpu_demos.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import os
22
import subprocess
33
import sys
4+
import pytest
45
sys.path.append("tests/python")
6+
import testing as tm
57
import test_demos as td # noqa
68

79

10+
@pytest.mark.skipif(**tm.no_cupy())
811
def test_data_iterator():
912
script = os.path.join(td.PYTHON_DEMO_DIR, 'data_iterator.py')
1013
cmd = ['python', script]

tests/python/test_plotting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
pass
1616

1717

18-
pytestmark = pytest.mark.skipif(**tm.no_matplotlib())
18+
pytestmark = pytest.mark.skipif(**tm.no_multiple(tm.no_matplotlib(), tm.no_graphviz()))
1919

2020

2121
dpath = 'demo/data/'

tests/python/test_with_sklearn.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ def test_sklearn_api_gblinear():
437437

438438

439439
@pytest.mark.skipif(**tm.no_matplotlib())
440+
@pytest.mark.skipif(**tm.no_graphviz())
440441
def test_sklearn_plotting():
441442
from sklearn.datasets import load_iris
442443

tests/python/testing.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,26 @@ def no_json_schema():
9898
return {'condition': True, 'reason': reason}
9999

100100

101+
def no_graphviz():
102+
reason = 'graphviz is not installed'
103+
try:
104+
import graphviz # noqa
105+
return {'condition': False, 'reason': reason}
106+
except ImportError:
107+
return {'condition': True, 'reason': reason}
108+
109+
110+
def no_multiple(*args):
111+
condition = False
112+
reason = ''
113+
for arg in args:
114+
condition = (condition or arg['condition'])
115+
if arg['condition']:
116+
reason = arg['reason']
117+
break
118+
return {'condition': condition, 'reason': reason}
119+
120+
101121
# Contains a dataset in numpy format as well as the relevant objective and metric
102122
class TestDataset:
103123
def __init__(self, name, get_dataset, objective, metric

0 commit comments

Comments
 (0)