Add helper script and doc for releasing pip package. (#6613)

* Fix `long_description_content_type`.
This commit is contained in:
Jiaming Yuan 2021-01-21 14:46:52 +08:00 committed by GitHub
parent 9d2832a3a3
commit f0fd7629ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 145 additions and 0 deletions

127
dev/release-pypi.py Normal file
View File

@ -0,0 +1,127 @@
"""Simple script for downloading and checking pypi release wheels.
tqdm, sh are required to run this script.
"""
from urllib.request import urlretrieve
import argparse
from typing import List
from sh.contrib import git
from distutils import version
import subprocess
import tqdm
import os
# The package building is managed by Jenkins CI.
PREFIX = "https://s3-us-west-2.amazonaws.com/xgboost-nightly-builds/release_"
DIST = os.path.join(os.path.curdir, "python-package", "dist")
pbar = None
def show_progress(block_num, block_size, total_size):
"Show file download progress."
global pbar
if pbar is None:
pbar = tqdm.tqdm(total=total_size / 1024, unit="kB")
downloaded = block_num * block_size
if downloaded < total_size:
pbar.update(block_size / 1024)
else:
pbar.close()
pbar = None
def retrieve(url, filename=None):
return urlretrieve(url, filename, reporthook=show_progress)
def lastest_hash() -> str:
"Get latest commit hash."
ret = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True)
assert ret.returncode == 0, "Failed to get lastest commit hash."
commit_hash = ret.stdout.decode("utf-8").strip()
return commit_hash
def download_wheels(
platforms: List[str],
dir_URL: str,
src_filename_prefix: str,
target_filename_prefix: str,
) -> None:
"""Download all binary wheels. dir_URL is the URL for remote directory storing the release
wheels
"""
filenames = []
for platform in platforms:
src_wheel = src_filename_prefix + platform + ".whl"
url = dir_URL + src_wheel
target_wheel = target_filename_prefix + platform + ".whl"
filename = os.path.join(DIST, target_wheel)
filenames.append(filename)
print("Downloading from:", url, "to:", filename)
retrieve(url=url, filename=filename)
ret = subprocess.run(["twine", "check", filename], capture_output=True)
assert ret.returncode == 0, "Failed twine check"
stderr = ret.stderr.decode("utf-8")
stdout = ret.stdout.decode("utf-8")
assert stderr.find("warning") == -1, "Unresolved warnings:\n" + stderr
assert stdout.find("warning") == -1, "Unresolved warnings:\n" + stdout
def check_path():
root = os.path.abspath(os.path.curdir)
assert os.path.basename(root) == "xgboost", "Must be run on project root."
def main(args: argparse.Namespace) -> None:
check_path()
rel = version.StrictVersion(args.release)
platforms = [
"win_amd64",
"manylinux2010_x86_64",
"manylinux2014_aarch64",
"macosx_10_14_x86_64.macosx_10_15_x86_64.macosx_11_0_x86_64",
]
print("Release:", rel)
major, minor, patch = rel.version
branch = "release_" + str(major) + "." + str(minor) + ".0"
git.clean("-xdf")
git.checkout(branch)
git.pull("origin", branch)
git.submodule("update")
commit_hash = lastest_hash()
dir_URL = PREFIX + str(major) + "." + str(minor) + ".0" + "/"
src_filename_prefix = "xgboost-" + args.release + "%2B" + commit_hash + "-py3-none-"
target_filename_prefix = "xgboost-" + args.release + "-py3-none-"
if not os.path.exists(DIST):
os.mkdir(DIST)
filenames = download_wheels(
platforms, dir_URL, src_filename_prefix, target_filename_prefix
)
print("List of downloaded wheels:", filenames)
print(
"""
Following steps should be done manually:
- Generate source package by running `python setup.py sdist`.
- Upload pypi package by `python3 -m twine upload dist/<Package Name>` for all wheels.
- Check the uploaded files on `https://pypi.org/project/xgboost/<VERSION>/#files` and `pip
install xgboost==<VERSION>` """
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--release", type=str, required=True, help="Version tag, e.g. '1.3.2'."
)
args = parser.parse_args()
main(args)

View File

@ -11,3 +11,20 @@ Starting from XGBoost 1.0.0, each XGBoost release will be versioned as [MAJOR].[
* MAJOR: We gurantee the API compatibility across releases with the same major version number. We expect to have a 1+ years development period for a new MAJOR release version.
* FEATURE: We ship new features, improvements and bug fixes through feature releases. The cycle length of a feature is decided by the size of feature roadmap. The roadmap is decided right after the previous release.
* MAINTENANCE: Maintenance version only contains bug fixes. This type of release only occurs when we found significant correctness and/or performance bugs and barrier for users to upgrade to a new version of XGBoost smoothly.
Making a Release
-----------------
1. Create an issue for the release, noting the estimated date and expected features or major fixes, pin that issue.
2. Bump release version.
1. Modify ``CMakeLists.txt`` source tree, run CMake.
2. Modify ``DESCRIPTION`` in R-package.
3. Run ``change_version.sh`` in ``jvm-packages/dev``
3. Commit the change, create a PR on github on release branch. Port the bumped version to default branch, optionally with the postfix ``SNAPSHOT``.
4. Create a tag on release branch, either on github or locally.
5. Make a release on github tag page, which might be done with previous step if the tag is created on github.
6. Submit pip, cran and maven packages.
- pip package is maintained by [Hyunsu Cho](http://hyunsu-cho.io/) and [Jiaming Yuan](https://github.com/trivialfis). There's a helper script for downloading pre-built wheels on ``xgboost/dev/release-pypi.py`` along with simple instructions for using ``twine``.
- cran package is maintained by [Tong He](https://github.com/hetong007).
- maven packageis maintained by [Nan Zhu](https://github.com/CodingCat).

View File

@ -305,6 +305,7 @@ if __name__ == '__main__':
description="XGBoost Python Package",
long_description=open(os.path.join(CURRENT_DIR, 'README.rst'),
encoding='utf-8').read(),
long_description_content_type="text/x-rst",
install_requires=[
'numpy',
'scipy',