mirror of https://github.com/docker/compose.git
Merge pull request #6073 from docker/release-tool-improve
Misc improvements to release script
This commit is contained in:
commit
8c4fc4bc2e
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
|||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
from distutils.core import run_setup
|
||||
|
@ -27,6 +28,7 @@ from release.utils import ScriptError
|
|||
from release.utils import update_init_py_version
|
||||
from release.utils import update_run_sh_version
|
||||
from release.utils import yesno
|
||||
from requests.exceptions import HTTPError
|
||||
from twine.commands.upload import main as twine_upload
|
||||
|
||||
|
||||
|
@ -128,13 +130,60 @@ def print_final_instructions(args):
|
|||
"You're almost done! Please verify that everything is in order and "
|
||||
"you are ready to make the release public, then run the following "
|
||||
"command:\n{exe} -b {user} finalize {version}".format(
|
||||
exe=sys.argv[0], user=args.bintray_user, version=args.release
|
||||
exe='./script/release/release.sh', user=args.bintray_user, version=args.release
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def distclean():
|
||||
print('Running distclean...')
|
||||
dirs = [
|
||||
os.path.join(REPO_ROOT, 'build'), os.path.join(REPO_ROOT, 'dist'),
|
||||
os.path.join(REPO_ROOT, 'docker-compose.egg-info')
|
||||
]
|
||||
files = []
|
||||
for base, dirnames, fnames in os.walk(REPO_ROOT):
|
||||
for fname in fnames:
|
||||
path = os.path.normpath(os.path.join(base, fname))
|
||||
if fname.endswith('.pyc'):
|
||||
files.append(path)
|
||||
elif fname.startswith('.coverage.'):
|
||||
files.append(path)
|
||||
for dirname in dirnames:
|
||||
path = os.path.normpath(os.path.join(base, dirname))
|
||||
if dirname == '__pycache__':
|
||||
dirs.append(path)
|
||||
elif dirname == '.coverage-binfiles':
|
||||
dirs.append(path)
|
||||
|
||||
for file in files:
|
||||
os.unlink(file)
|
||||
|
||||
for folder in dirs:
|
||||
shutil.rmtree(folder, ignore_errors=True)
|
||||
|
||||
|
||||
def pypi_upload(args):
|
||||
print('Uploading to PyPi')
|
||||
try:
|
||||
twine_upload([
|
||||
'dist/docker_compose-{}*.whl'.format(args.release),
|
||||
'dist/docker-compose-{}*.tar.gz'.format(args.release)
|
||||
])
|
||||
except HTTPError as e:
|
||||
if e.response.status_code == 400 and 'File already exists' in e.message:
|
||||
if not args.finalize_resume:
|
||||
raise ScriptError(
|
||||
'Package already uploaded on PyPi.'
|
||||
)
|
||||
print('Skipping PyPi upload - package already uploaded')
|
||||
else:
|
||||
raise ScriptError('Unexpected HTTP error uploading package to PyPi: {}'.format(e))
|
||||
|
||||
|
||||
def resume(args):
|
||||
try:
|
||||
distclean()
|
||||
repository = Repository(REPO_ROOT, args.repo)
|
||||
br_name = branch_name(args.release)
|
||||
if not repository.branch_exists(br_name):
|
||||
|
@ -186,6 +235,7 @@ def cancel(args):
|
|||
bintray_api = BintrayAPI(os.environ['BINTRAY_TOKEN'], args.bintray_user)
|
||||
print('Removing Bintray data repository for {}'.format(args.release))
|
||||
bintray_api.delete_repository(args.bintray_org, branch_name(args.release))
|
||||
distclean()
|
||||
except ScriptError as e:
|
||||
print(e)
|
||||
return 1
|
||||
|
@ -194,6 +244,7 @@ def cancel(args):
|
|||
|
||||
|
||||
def start(args):
|
||||
distclean()
|
||||
try:
|
||||
repository = Repository(REPO_ROOT, args.repo)
|
||||
create_initial_branch(repository, args)
|
||||
|
@ -216,6 +267,7 @@ def start(args):
|
|||
|
||||
|
||||
def finalize(args):
|
||||
distclean()
|
||||
try:
|
||||
repository = Repository(REPO_ROOT, args.repo)
|
||||
img_manager = ImageManager(args.release)
|
||||
|
@ -241,10 +293,13 @@ def finalize(args):
|
|||
run_setup(os.path.join(REPO_ROOT, 'setup.py'), script_args=['sdist', 'bdist_wheel'])
|
||||
|
||||
merge_status = pr_data.merge()
|
||||
if not merge_status.merged:
|
||||
raise ScriptError('Unable to merge PR #{}: {}'.format(pr_data.number, merge_status.message))
|
||||
print('Uploading to PyPi')
|
||||
twine_upload(['dist/*'])
|
||||
if not merge_status.merged and not args.finalize_resume:
|
||||
raise ScriptError(
|
||||
'Unable to merge PR #{}: {}'.format(pr_data.number, merge_status.message)
|
||||
)
|
||||
|
||||
pypi_upload(args)
|
||||
|
||||
img_manager.push_images()
|
||||
repository.publish_release(gh_release)
|
||||
except ScriptError as e:
|
||||
|
@ -263,13 +318,13 @@ ACTIONS = [
|
|||
|
||||
EPILOG = '''Example uses:
|
||||
* Start a new feature release (includes all changes currently in master)
|
||||
release.py -b user start 1.23.0
|
||||
release.sh -b user start 1.23.0
|
||||
* Start a new patch release
|
||||
release.py -b user --patch 1.21.0 start 1.21.1
|
||||
release.sh -b user --patch 1.21.0 start 1.21.1
|
||||
* Cancel / rollback an existing release draft
|
||||
release.py -b user cancel 1.23.0
|
||||
release.sh -b user cancel 1.23.0
|
||||
* Restart a previously aborted patch release
|
||||
release.py -b user -p 1.21.0 resume 1.21.1
|
||||
release.sh -b user -p 1.21.0 resume 1.21.1
|
||||
'''
|
||||
|
||||
|
||||
|
@ -319,6 +374,10 @@ def main():
|
|||
'--skip-ci-checks', dest='skip_ci', action='store_true',
|
||||
help='If set, the program will not wait for CI jobs to complete'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--finalize-resume', dest='finalize_resume', action='store_true',
|
||||
help='If set, finalize will continue through steps that have already been completed.'
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.action == 'start':
|
||||
|
|
|
@ -81,3 +81,7 @@ class ImageManager(object):
|
|||
for chunk in logstream:
|
||||
if 'status' in chunk:
|
||||
print(chunk['status'])
|
||||
if 'error' in chunk:
|
||||
raise ScriptError(
|
||||
'Error pushing {name}: {err}'.format(name=name, err=chunk['error'])
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue