def resume(args): try: distclean() repository = Repository(REPO_ROOT, args.repo) br_name = branch_name(args.release) if not repository.branch_exists(br_name): raise ScriptError('No local branch exists for this release.') gh_release = repository.find_release(args.release) if gh_release and not gh_release.draft: print( 'WARNING!! Found non-draft (public) release for this version!') proceed = yesno( 'Are you sure you wish to proceed? Modifying an already ' 'released version is dangerous! y/N ', default=False) if proceed.lower() is not True: raise ScriptError('Aborting release') release_branch = repository.checkout_branch(br_name) if args.cherries: cherries = input( 'Indicate (space-separated) PR numbers to cherry-pick then press Enter:\n' ) repository.cherry_pick_prs(release_branch, cherries.split()) create_bump_commit(repository, release_branch, args.bintray_user, args.bintray_org) pr_data = repository.find_release_pr(args.release) if not pr_data: pr_data = repository.create_release_pull_request(args.release) check_pr_mergeable(pr_data) if not args.skip_ci: monitor_pr_status(pr_data) downloader = BinaryDownloader(args.destination) files = downloader.download_all(args.release) if not gh_release: gh_release = create_release_draft(repository, args.release, pr_data, files) delete_assets(gh_release) upload_assets(gh_release, files) tag_as_latest = is_tag_latest(args.release) img_manager = ImageManager(args.release, tag_as_latest) img_manager.build_images(repository) except ScriptError as e: print(e) return 1 print_final_instructions(args) return 0
def monitor_pr_status(pr_data): print('Waiting for CI to complete...') last_commit = pr_data.get_commits().reversed[0] while True: status = last_commit.get_combined_status() if status.state == 'pending' or status.state == 'failure': summary = { 'pending': 0, 'success': 0, 'failure': 0, 'error': 0, } for detail in status.statuses: if detail.context == 'dco-signed': # dco-signed check breaks on merge remote-tracking ; ignore it continue if detail.state in summary: summary[detail.state] += 1 print( '{pending} pending, {success} successes, {failure} failures, ' '{error} errors'.format(**summary)) if summary['failure'] > 0 or summary['error'] > 0: raise ScriptError('CI failures detected!') elif summary['pending'] == 0 and summary['success'] > 0: # This check assumes at least 1 non-DCO CI check to avoid race conditions. # If testing on a repo without CI, use --skip-ci-check to avoid looping eternally return True time.sleep(30) elif status.state == 'success': print('{} successes: all clear!'.format(status.total_count)) return True
def monitor_pr_status(pr_data): print('Waiting for CI to complete...') last_commit = pr_data.get_commits().reversed[0] while True: status = last_commit.get_combined_status() if status.state == 'pending' or status.state == 'failure': summary = { 'pending': 0, 'success': 0, 'failure': 0, } for detail in status.statuses: if detail.context == 'dco-signed': # dco-signed check breaks on merge remote-tracking ; ignore it continue summary[detail.state] += 1 print('{pending} pending, {success} successes, {failure} failures'. format(**summary)) if status.total_count == 0: # Mostly for testing purposes against repos with no CI setup return True elif summary['pending'] == 0 and summary['failure'] == 0: return True elif summary['failure'] > 0: raise ScriptError('CI failures detected!') time.sleep(30) elif status.state == 'success': print('{} successes: all clear!'.format(status.total_count)) return 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 finalize(args): distclean() try: check_pypirc() repository = Repository(REPO_ROOT, args.repo) img_manager = ImageManager(args.release) pr_data = repository.find_release_pr(args.release) if not pr_data: raise ScriptError('No PR found for {}'.format(args.release)) if not check_pr_mergeable(pr_data): raise ScriptError( 'Can not finalize release with an unmergeable PR') if not img_manager.check_images(): raise ScriptError('Missing release image') br_name = branch_name(args.release) if not repository.branch_exists(br_name): raise ScriptError('No local branch exists for this release.') gh_release = repository.find_release(args.release) if not gh_release: raise ScriptError('No Github release draft for this version') repository.checkout_branch(br_name) pypandoc.convert_file(os.path.join(REPO_ROOT, 'README.md'), 'rst', outputfile=os.path.join(REPO_ROOT, 'README.rst')) run_setup(os.path.join(REPO_ROOT, 'setup.py'), script_args=['sdist', 'bdist_wheel']) merge_status = pr_data.merge() 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: print(e) return 1 return 0
def finalize(args): distclean() try: check_pypirc() repository = Repository(REPO_ROOT, args.repo) tag_as_latest = _check_if_tag_latest(args.release) img_manager = ImageManager(args.release, tag_as_latest) pr_data = repository.find_release_pr(args.release) if not pr_data: raise ScriptError('No PR found for {}'.format(args.release)) if not check_pr_mergeable(pr_data): raise ScriptError('Can not finalize release with an unmergeable PR') if not img_manager.check_images(): raise ScriptError('Missing release image') br_name = branch_name(args.release) if not repository.branch_exists(br_name): raise ScriptError('No local branch exists for this release.') gh_release = repository.find_release(args.release) if not gh_release: raise ScriptError('No Github release draft for this version') repository.checkout_branch(br_name) os.system('python {setup_script} sdist bdist_wheel'.format( setup_script=os.path.join(REPO_ROOT, 'setup.py'))) merge_status = pr_data.merge() 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: print(e) return 1 return 0