1
+ """
2
+ Helper script to prepare for releasing XGBoost JVM packages to
3
+ Maven Central.
4
+
5
+ ## Prerequisite
6
+
7
+ 1. You must have the right to upload artifacts to the Maven Central repo.
8
+ If you do not, contact Hyunsu Cho ([email protected] ) so that
9
+ he can contact Sonatype on your behalf in order to add you as a
10
+ "producer" user for the ml.dmlc namespace. See
11
+ https://central.sonatype.org/pages/support/#status to learn about
12
+ the process for adding or removing users who can publish to the project.
13
+
14
+ 2. Follow instructions in
15
+ https://central.sonatype.org/publish/publish-portal-maven/#credentials
16
+ to set up the authentication token in your machine.
17
+
18
+ 3. Set up GPG for signing artifacts:
19
+ https://central.sonatype.org/publish/requirements/gpg/
20
+
21
+ ## Making the release
22
+ Run this script 4 times:
23
+
24
+ python3 dev/prepare_jvm_release.py --scala-version 2.12 --variant cpu
25
+ python3 dev/prepare_jvm_release.py --scala-version 2.12 --variant gpu
26
+ python3 dev/prepare_jvm_release.py --scala-version 2.13 --variant cpu
27
+ python3 dev/prepare_jvm_release.py --scala-version 2.13 --variant gpu
28
+
29
+ """
30
+
1
31
import argparse
2
32
import errno
3
33
import glob
@@ -52,7 +82,7 @@ def cd(path):
52
82
53
83
def run (command , ** kwargs ):
54
84
print (command )
55
- subprocess .check_call (command , shell = True , ** kwargs )
85
+ subprocess .run (command , shell = True , check = True , ** kwargs )
56
86
57
87
58
88
def get_current_commit_hash ():
@@ -74,141 +104,135 @@ def retrieve(url, filename=None):
74
104
75
105
76
106
def main ():
77
- parser = argparse .ArgumentParser ()
107
+ parser = argparse .ArgumentParser (
108
+ description = __doc__ , formatter_class = argparse .RawTextHelpFormatter
109
+ )
78
110
parser .add_argument (
79
111
"--release-version" ,
80
112
type = str ,
81
113
required = True ,
82
114
help = "Version of the release being prepared" ,
83
115
)
116
+ parser .add_argument (
117
+ "--scala-version" ,
118
+ type = str ,
119
+ required = True ,
120
+ help = "Version of Scala to use in the JVM packages" ,
121
+ choices = ["2.12" , "2.13" ],
122
+ )
123
+ parser .add_argument (
124
+ "--variant" ,
125
+ type = str ,
126
+ required = True ,
127
+ choices = ["cpu" , "gpu" ],
128
+ help = "JVM package variant to package and publish" ,
129
+ )
130
+
84
131
args = parser .parse_args ()
85
132
version = args .release_version
133
+ scala_version = args .scala_version
134
+ use_cuda = args .variant == "gpu"
86
135
87
136
commit_hash = get_current_commit_hash ()
88
137
git_branch = get_current_git_branch ()
89
- print (
90
- f"Using commit { commit_hash } of branch { git_branch } "
138
+ print (f"Using commit { commit_hash } of branch { git_branch } " )
139
+ print (f"====Update pom.xml to use Scala { scala_version } ====" )
140
+ run (
141
+ f"{ sys .executable } ops/script/change_scala_version.py "
142
+ f"--scala-version { scala_version } --purge-artifacts"
91
143
)
92
144
93
145
with cd ("jvm-packages/" ):
94
- print ("====copying pure-Python tracker====" )
95
- for use_cuda in [True , False ]:
96
- xgboost4j = "xgboost4j-gpu" if use_cuda else "xgboost4j"
97
- cp (
98
- "../python-package/xgboost/tracker.py" ,
99
- f"{ xgboost4j } /src/main/resources" ,
100
- )
101
-
102
- print ("====copying resources for testing====" )
146
+ print ("====Copying resources for testing====" )
103
147
with cd ("../demo/CLI/regression" ):
104
148
run (f"{ sys .executable } mapfeat.py" )
105
149
run (f"{ sys .executable } mknfold.py machine.txt 1" )
106
- for use_cuda in [True , False ]:
107
- xgboost4j = "xgboost4j-gpu" if use_cuda else "xgboost4j"
108
- xgboost4j_spark = "xgboost4j-spark-gpu" if use_cuda else "xgboost4j-spark"
109
- maybe_makedirs (f"{ xgboost4j } /src/test/resources" )
110
- maybe_makedirs (f"{ xgboost4j_spark } /src/test/resources" )
111
- for file in glob .glob ("../demo/data/agaricus.*" ):
112
- cp (file , f"{ xgboost4j } /src/test/resources" )
113
- cp (file , f"{ xgboost4j_spark } /src/test/resources" )
114
- for file in glob .glob ("../demo/CLI/regression/machine.txt.t*" ):
115
- cp (file , f"{ xgboost4j_spark } /src/test/resources" )
150
+ xgboost4j_spark = "xgboost4j-spark-gpu" if use_cuda else "xgboost4j-spark"
151
+ maybe_makedirs (f"xgboost4j/src/test/resources" )
152
+ maybe_makedirs (f"{ xgboost4j_spark } /src/test/resources" )
153
+ for file in glob .glob ("../demo/data/agaricus.*" ):
154
+ cp (file , f"xgboost4j/src/test/resources" )
155
+ cp (file , f"{ xgboost4j_spark } /src/test/resources" )
156
+ for file in glob .glob ("../demo/CLI/regression/machine.txt.t*" ):
157
+ cp (file , f"{ xgboost4j_spark } /src/test/resources" )
116
158
117
159
print ("====Creating directories to hold native binaries====" )
118
- for os_ident , arch in [
119
- ("linux" , "x86_64" ),
120
- ("linux" , "aarch64" ),
121
- ("windows" , "x86_64" ),
122
- ("macos" , "x86_64" ),
123
- ("macos" , "aarch64" ),
124
- ]:
160
+ if use_cuda :
161
+ # TODO(hcho3): Add GPU build for linux aarch64
162
+ matrix = [("linux" , "x86_64" )]
163
+ else :
164
+ matrix = [
165
+ ("linux" , "x86_64" ),
166
+ ("linux" , "aarch64" ),
167
+ ("windows" , "x86_64" ),
168
+ ("macos" , "x86_64" ),
169
+ ("macos" , "aarch64" ),
170
+ ]
171
+ for os_ident , arch in matrix :
125
172
output_dir = f"xgboost4j/src/main/resources/lib/{ os_ident } /{ arch } "
126
173
maybe_makedirs (output_dir )
127
- for os_ident , arch in [("linux" , "x86_64" )]:
128
- output_dir = f"xgboost4j-gpu/src/main/resources/lib/{ os_ident } /{ arch } "
129
- maybe_makedirs (output_dir )
130
174
131
175
print ("====Downloading native binaries from CI====" )
132
- nightly_bucket_prefix = (
133
- "https://s3-us-west-2.amazonaws.com/xgboost-nightly-builds"
134
- )
135
- maven_repo_prefix = (
136
- "https://s3-us-west-2.amazonaws.com/xgboost-maven-repo/release/ml/dmlc"
137
- )
138
-
139
- retrieve (
140
- url = f"{ nightly_bucket_prefix } /{ git_branch } /libxgboost4j/xgboost4j_{ commit_hash } .dll" ,
141
- filename = "xgboost4j/src/main/resources/lib/windows/x86_64/xgboost4j.dll" ,
142
- )
143
- retrieve (
144
- url = f"{ nightly_bucket_prefix } /{ git_branch } /libxgboost4j/libxgboost4j_linux_x86_64_{ commit_hash } .so" ,
145
- filename = "xgboost4j/src/main/resources/lib/linux/x86_64/libxgboost4j.so" ,
146
- )
147
- retrieve (
148
- url = f"{ nightly_bucket_prefix } /{ git_branch } /libxgboost4j/libxgboost4j_linux_arm64_{ commit_hash } .so" ,
149
- filename = "xgboost4j/src/main/resources/lib/linux/aarch64/libxgboost4j.so" ,
150
- )
151
- retrieve (
152
- url = f"{ nightly_bucket_prefix } /{ git_branch } /libxgboost4j/libxgboost4j_{ commit_hash } .dylib" ,
153
- filename = "xgboost4j/src/main/resources/lib/macos/x86_64/libxgboost4j.dylib" ,
154
- )
155
- retrieve (
156
- url = f"{ nightly_bucket_prefix } /{ git_branch } /libxgboost4j/libxgboost4j_m1_{ commit_hash } .dylib" ,
157
- filename = "xgboost4j/src/main/resources/lib/macos/aarch64/libxgboost4j.dylib" ,
158
- )
159
-
160
- with tempfile .TemporaryDirectory () as tempdir :
161
- # libxgboost4j.so for Linux x86_64, GPU support
162
- zip_path = os .path .join (tempdir , "xgboost4j-gpu_2.12.jar" )
163
- extract_dir = os .path .join (tempdir , "xgboost4j-gpu" )
164
- retrieve (
165
- url = f"{ maven_repo_prefix } /xgboost4j-gpu_2.12/{ version } /"
166
- f"xgboost4j-gpu_2.12-{ version } .jar" ,
167
- filename = zip_path ,
176
+ if use_cuda :
177
+ url_prefix = (
178
+ "https://s3-us-west-2.amazonaws.com/xgboost-maven-repo/release/ml/dmlc"
179
+ )
180
+ with tempfile .TemporaryDirectory () as tempdir :
181
+ # libxgboost4j.so for Linux x86_64, GPU support
182
+ zip_path = os .path .join (tempdir , "xgboost4j-spark-gpu_2.12.jar" )
183
+ extract_dir = os .path .join (tempdir , "xgboost4j-spark-gpu" )
184
+ retrieve (
185
+ url = f"{ url_prefix } /xgboost4j-spark-gpu_2.12/{ version } /"
186
+ f"xgboost4j-spark-gpu_2.12-{ version } .jar" ,
187
+ filename = zip_path ,
188
+ )
189
+ os .mkdir (extract_dir )
190
+ with zipfile .ZipFile (zip_path , "r" ) as t :
191
+ t .extractall (extract_dir )
192
+ cp (
193
+ os .path .join (
194
+ extract_dir , "lib" , "linux" , "x86_64" , "libxgboost4j.so"
195
+ ),
196
+ "xgboost4j/src/main/resources/lib/linux/x86_64/libxgboost4j.so" ,
197
+ )
198
+ run (
199
+ "mvn --no-transfer-progress install -Pgpu "
200
+ "-DskipTests -Dmaven.test.skip=true -Dskip.native.build=true"
168
201
)
169
- os .mkdir (extract_dir )
170
- with zipfile .ZipFile (zip_path , "r" ) as t :
171
- t .extractall (extract_dir )
172
- cp (
173
- os .path .join (extract_dir , "lib" , "linux" , "x86_64" , "libxgboost4j.so" ),
174
- "xgboost4j-gpu/src/main/resources/lib/linux/x86_64/libxgboost4j.so" ,
202
+ run (
203
+ "mvn deploy -Pgpu,release -pl xgboost4j-spark-gpu "
204
+ "-DskipTests -Dmaven.test.skip=true -Dskip.native.build=true"
205
+ )
206
+ else :
207
+ url_prefix = "https://s3-us-west-2.amazonaws.com/xgboost-nightly-builds"
208
+ for os_ident , arch , src_libname , dest_libname in [
209
+ ("linux" , "x86_64" , "libxgboost4j_linux_x86_64.so" , "libxgboost4j.so" ),
210
+ (
211
+ "linux" ,
212
+ "aarch64" ,
213
+ "libxgboost4j_linux_aarch64.so" ,
214
+ "libxgboost4j.so" ,
215
+ ),
216
+ ("windows" , "x86_64" , "xgboost4j.dll" , "xgboost4j.dll" ),
217
+ ("macos" , "x86_64" , "libxgboost4j_intel.dylib" , "libxgboost4j.dylib" ),
218
+ ("macos" , "aarch64" , "libxgboost4j_m1.dylib" , "libxgboost4j.dylib" ),
219
+ ]:
220
+ retrieve (
221
+ url = f"{ url_prefix } /{ git_branch } /{ commit_hash } /{ src_libname } " ,
222
+ filename = (
223
+ "xgboost4j/src/main/resources/lib/"
224
+ f"{ os_ident } /{ arch } /{ dest_libname } "
225
+ ),
226
+ )
227
+ run (
228
+ "mvn --no-transfer-progress deploy -Pdefault,release "
229
+ "-DskipTests -Dmaven.test.skip=true -Dskip.native.build=true"
175
230
)
176
231
177
232
print ("====Next Steps====" )
178
- print ("1. Gain upload right to Maven Central repo." )
179
- print ("1-1. Sign up for a JIRA account at Sonatype: " )
180
- print (
181
- "1-2. File a JIRA ticket: "
182
- "https://issues.sonatype.org/secure/CreateIssue.jspa?issuetype=21&pid=10134. Example: "
183
- "https://issues.sonatype.org/browse/OSSRH-67724"
184
- )
185
- print (
186
- "2. Store the Sonatype credentials in .m2/settings.xml. See insturctions in "
187
- "https://central.sonatype.org/publish/publish-maven/"
188
- )
189
- print (
190
- "3. Now on a Linux machine, run the following to build Scala 2.12 artifacts. "
191
- "Make sure to use an Internet connection with fast upload speed:"
192
- )
193
- print (
194
- " # Skip native build, since we have all needed native binaries from CI\n "
195
- " GPG_TTY=$(tty) mvn deploy -Prelease -DskipTests -Dskip.native.build=true"
196
- )
197
- print (
198
- "4. Log into https://oss.sonatype.org/. On the left menu panel, click Staging "
199
- "Repositories. Visit the URL https://oss.sonatype.org/content/repositories/mldmlc-xxxx "
200
- "to inspect the staged JAR files. Finally, press Release button to publish the "
201
- "artifacts to the Maven Central repository. The top-level metapackage should be "
202
- "named xgboost-jvm_2.12."
203
- )
204
- print (
205
- "5. Remove the Scala 2.12 artifacts and build Scala 2.13 artifacts:\n "
206
- " python ops/script/change_scala_version.py --scala-version 2.13 --purge-artifacts\n "
207
- " GPG_TTY=$(tty) mvn deploy -Prelease -DskipTests -Dskip.native.build=true"
208
- )
209
233
print (
210
- "6. Go to https://oss .sonatype.org/ to release the Scala 2.13 artifacts . "
211
- "The top-level metapackage should be named xgboost-jvm_2.13 ."
234
+ "Visit https://central .sonatype.com/publishing/deployments to verify the deployment . "
235
+ "You can either drop the deployment or publish it. Note: publishing is final ."
212
236
)
213
237
214
238
0 commit comments