mirror of https://github.com/docker/compose.git
Add images build step and finalize placeholder
Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
599456378b
commit
e9f6abf8f4
|
@ -4,9 +4,11 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import docker
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
from release.bintray import BintrayAPI
|
from release.bintray import BintrayAPI
|
||||||
from release.const import BINTRAY_ORG
|
from release.const import BINTRAY_ORG
|
||||||
|
@ -77,6 +79,15 @@ def monitor_pr_status(pr_data):
|
||||||
raise ScriptError('CI failure detected')
|
raise ScriptError('CI failure detected')
|
||||||
|
|
||||||
|
|
||||||
|
def check_pr_mergeable(pr_data):
|
||||||
|
if not pr_data.mergeable:
|
||||||
|
print(
|
||||||
|
'WARNING!! PR #{} can not currently be merged. You will need to '
|
||||||
|
'resolve the conflicts manually before finalizing the release.'.format(pr_data.number)
|
||||||
|
)
|
||||||
|
return pr_data.mergeable
|
||||||
|
|
||||||
|
|
||||||
def create_release_draft(repository, version, pr_data, files):
|
def create_release_draft(repository, version, pr_data, files):
|
||||||
print('Creating Github release draft')
|
print('Creating Github release draft')
|
||||||
with open(os.path.join(os.path.dirname(__file__), 'release.md.tmpl'), 'r') as f:
|
with open(os.path.join(os.path.dirname(__file__), 'release.md.tmpl'), 'r') as f:
|
||||||
|
@ -97,13 +108,51 @@ def create_release_draft(repository, version, pr_data, files):
|
||||||
return gh_release
|
return gh_release
|
||||||
|
|
||||||
|
|
||||||
def print_final_instructions(gh_release):
|
def build_images(repository, files, version):
|
||||||
print("""
|
print("Building release images...")
|
||||||
You're almost done! The following steps should be executed after you've
|
repository.write_git_sha()
|
||||||
verified that everything is in order and are ready to make the release public:
|
docker_client = docker.APIClient(**docker.utils.kwargs_from_env())
|
||||||
1.
|
distdir = os.path.join(REPO_ROOT, 'dist')
|
||||||
2.
|
os.makedirs(distdir, exist_ok=True)
|
||||||
3.""")
|
shutil.copy(files['docker-compose-Linux-x86_64'][0], distdir)
|
||||||
|
print('Building docker/compose image')
|
||||||
|
logstream = docker_client.build(
|
||||||
|
REPO_ROOT, tag='docker/compose:{}'.format(version), dockerfile='Dockerfile.run',
|
||||||
|
decode=True
|
||||||
|
)
|
||||||
|
for chunk in logstream:
|
||||||
|
if 'error' in chunk:
|
||||||
|
raise ScriptError('Build error: {}'.format(chunk['error']))
|
||||||
|
if 'stream' in chunk:
|
||||||
|
print(chunk['stream'], end='')
|
||||||
|
|
||||||
|
print('Building test image (for UCP e2e)')
|
||||||
|
logstream = docker_client.build(
|
||||||
|
REPO_ROOT, tag='docker-compose-tests:tmp', decode=True
|
||||||
|
)
|
||||||
|
for chunk in logstream:
|
||||||
|
if 'error' in chunk:
|
||||||
|
raise ScriptError('Build error: {}'.format(chunk['error']))
|
||||||
|
if 'stream' in chunk:
|
||||||
|
print(chunk['stream'], end='')
|
||||||
|
|
||||||
|
container = docker_client.create_container(
|
||||||
|
'docker-compose-tests:tmp', entrypoint='tox'
|
||||||
|
)
|
||||||
|
docker_client.commit(container, 'docker/compose-tests:latest')
|
||||||
|
docker_client.tag('docker/compose-tests:latest', 'docker/compose-tests:{}'.format(version))
|
||||||
|
docker_client.remove_container(container, force=True)
|
||||||
|
docker_client.remove_image('docker-compose-tests:tmp', force=True)
|
||||||
|
|
||||||
|
|
||||||
|
def print_final_instructions(args):
|
||||||
|
print(
|
||||||
|
"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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def resume(args):
|
def resume(args):
|
||||||
|
@ -117,6 +166,7 @@ def resume(args):
|
||||||
pr_data = repository.find_release_pr(args.release)
|
pr_data = repository.find_release_pr(args.release)
|
||||||
if not pr_data:
|
if not pr_data:
|
||||||
pr_data = repository.create_release_pull_request(args.release)
|
pr_data = repository.create_release_pull_request(args.release)
|
||||||
|
check_pr_mergeable(pr_data)
|
||||||
monitor_pr_status(pr_data)
|
monitor_pr_status(pr_data)
|
||||||
downloader = BinaryDownloader(args.destination)
|
downloader = BinaryDownloader(args.destination)
|
||||||
files = downloader.download_all(args.release)
|
files = downloader.download_all(args.release)
|
||||||
|
@ -133,11 +183,12 @@ def resume(args):
|
||||||
raise ScriptError('Aborting release')
|
raise ScriptError('Aborting release')
|
||||||
delete_assets(gh_release)
|
delete_assets(gh_release)
|
||||||
upload_assets(gh_release, files)
|
upload_assets(gh_release, files)
|
||||||
|
build_images(repository, files, args.release)
|
||||||
except ScriptError as e:
|
except ScriptError as e:
|
||||||
print(e)
|
print(e)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
print_final_instructions(gh_release)
|
print_final_instructions(args)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,19 +214,50 @@ def start(args):
|
||||||
repository = Repository(REPO_ROOT, args.repo or NAME)
|
repository = Repository(REPO_ROOT, args.repo or NAME)
|
||||||
create_initial_branch(repository, args.release, args.base, args.bintray_user)
|
create_initial_branch(repository, args.release, args.base, args.bintray_user)
|
||||||
pr_data = repository.create_release_pull_request(args.release)
|
pr_data = repository.create_release_pull_request(args.release)
|
||||||
|
check_pr_mergeable(pr_data)
|
||||||
monitor_pr_status(pr_data)
|
monitor_pr_status(pr_data)
|
||||||
downloader = BinaryDownloader(args.destination)
|
downloader = BinaryDownloader(args.destination)
|
||||||
files = downloader.download_all(args.release)
|
files = downloader.download_all(args.release)
|
||||||
gh_release = create_release_draft(repository, args.release, pr_data, files)
|
gh_release = create_release_draft(repository, args.release, pr_data, files)
|
||||||
upload_assets(gh_release, files)
|
upload_assets(gh_release, files)
|
||||||
|
build_images(repository, files, args.release)
|
||||||
except ScriptError as e:
|
except ScriptError as e:
|
||||||
print(e)
|
print(e)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
print_final_instructions(gh_release)
|
print_final_instructions(args)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def finalize(args):
|
||||||
|
try:
|
||||||
|
raise NotImplementedError()
|
||||||
|
except ScriptError as e:
|
||||||
|
print(e)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
ACTIONS = [
|
||||||
|
'start',
|
||||||
|
'cancel',
|
||||||
|
'resume',
|
||||||
|
'finalize',
|
||||||
|
]
|
||||||
|
|
||||||
|
EPILOG = '''Example uses:
|
||||||
|
* Start a new feature release (includes all changes currently in master)
|
||||||
|
release.py -b user start 1.23.0
|
||||||
|
* Start a new patch release
|
||||||
|
release.py -b user --patch 1.21.0 start 1.21.1
|
||||||
|
* Cancel / rollback an existing release draft
|
||||||
|
release.py -b user cancel 1.23.0
|
||||||
|
* Restart a previously aborted patch release
|
||||||
|
release.py -b user -p 1.21.0 resume 1.21.1
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if 'GITHUB_TOKEN' not in os.environ:
|
if 'GITHUB_TOKEN' not in os.environ:
|
||||||
print('GITHUB_TOKEN environment variable must be set')
|
print('GITHUB_TOKEN environment variable must be set')
|
||||||
|
@ -189,18 +271,9 @@ def main():
|
||||||
description='Orchestrate a new release of docker/compose. This tool assumes that you have '
|
description='Orchestrate a new release of docker/compose. This tool assumes that you have '
|
||||||
'obtained a Github API token and Bintray API key and set the GITHUB_TOKEN and '
|
'obtained a Github API token and Bintray API key and set the GITHUB_TOKEN and '
|
||||||
'BINTRAY_TOKEN environment variables accordingly.',
|
'BINTRAY_TOKEN environment variables accordingly.',
|
||||||
epilog='''Example uses:
|
epilog=EPILOG, formatter_class=argparse.RawTextHelpFormatter)
|
||||||
* Start a new feature release (includes all changes currently in master)
|
|
||||||
release.py -b user start 1.23.0
|
|
||||||
* Start a new patch release
|
|
||||||
release.py -b user --patch 1.21.0 start 1.21.1
|
|
||||||
* Cancel / rollback an existing release draft
|
|
||||||
release.py -b user cancel 1.23.0
|
|
||||||
* Restart a previously aborted patch release
|
|
||||||
release.py -b user -p 1.21.0 resume 1.21.1''', formatter_class=argparse.RawTextHelpFormatter)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'action', choices=['start', 'resume', 'cancel'],
|
'action', choices=ACTIONS, help='The action to be performed for this release'
|
||||||
help='The action to be performed for this release'
|
|
||||||
)
|
)
|
||||||
parser.add_argument('release', help='Release number, e.g. 1.9.0-rc1, 2.1.1')
|
parser.add_argument('release', help='Release number, e.g. 1.9.0-rc1, 2.1.1')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
@ -227,6 +300,9 @@ def main():
|
||||||
return resume(args)
|
return resume(args)
|
||||||
elif args.action == 'cancel':
|
elif args.action == 'cancel':
|
||||||
return cancel(args)
|
return cancel(args)
|
||||||
|
elif args.action == 'finalize':
|
||||||
|
return finalize(args)
|
||||||
|
|
||||||
print('Unexpected action "{}"'.format(args.action), file=sys.stderr)
|
print('Unexpected action "{}"'.format(args.action), file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,10 @@ class Repository(object):
|
||||||
print('No open PR for this release branch.')
|
print('No open PR for this release branch.')
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
def write_git_sha(self):
|
||||||
|
with open(os.path.join(REPO_ROOT, 'compose', 'GITSHA'), 'w') as f:
|
||||||
|
f.write(self.git_repo.head.commit.hexsha[:7])
|
||||||
|
|
||||||
|
|
||||||
def get_contributors(pr_data):
|
def get_contributors(pr_data):
|
||||||
commits = pr_data.get_commits()
|
commits = pr_data.get_commits()
|
||||||
|
@ -175,6 +179,7 @@ def upload_assets(gh_release, files):
|
||||||
print('Uploading {}...'.format(filename))
|
print('Uploading {}...'.format(filename))
|
||||||
gh_release.upload_asset(filedata[0], content_type='application/octet-stream')
|
gh_release.upload_asset(filedata[0], content_type='application/octet-stream')
|
||||||
gh_release.upload_asset('{}.sha256'.format(filedata[0]), content_type='text/plain')
|
gh_release.upload_asset('{}.sha256'.format(filedata[0]), content_type='text/plain')
|
||||||
|
print('Uploading run.sh...')
|
||||||
gh_release.upload_asset(
|
gh_release.upload_asset(
|
||||||
os.path.join(REPO_ROOT, 'script', 'run', 'run.sh'), content_type='text/plain'
|
os.path.join(REPO_ROOT, 'script', 'run', 'run.sh'), content_type='text/plain'
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue