Add --interactive to new-releases
Shamelessly steal^Wcopy some of the code from interactive-release so that after validating the release we list the changes that will be released. This gives us the ability to decide that the release contains no functional changes and elect to not create that release. NOTE: I chose not to use interactive-release as it seems not to correctly handle first releases in a series (because it doesn't load all release history. It also doesn't use some of the new features (like series_status). Adding --interactive to new-release gets us a long way to deprecating interactive-release but we aren't quire there yet. Change-Id: I25bbb4d7df9ae618500dd37f4b0cbc32c0bbd153
This commit is contained in:
parent
2c0feab157
commit
4cf2670c1f
@ -12,8 +12,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import atexit
|
||||
import logging
|
||||
@ -22,6 +20,8 @@ import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from openstack_releases.cmds.interactive_release import clean_changes
|
||||
from openstack_releases.cmds.interactive_release import yes_no_prompt
|
||||
from openstack_releases import gitutils
|
||||
from openstack_releases import series_status
|
||||
from openstack_releases import yamlutils
|
||||
@ -178,6 +178,12 @@ def main():
|
||||
action='store_true',
|
||||
help='be more chatty',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-i', '--interactive',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help='Be interactive and only make releases when instructed'
|
||||
)
|
||||
parser.add_argument(
|
||||
'release_type',
|
||||
choices=('bugfix', 'feature', 'major', 'milestone', 'rc',
|
||||
@ -239,7 +245,7 @@ def main():
|
||||
if args.cleanup:
|
||||
shutil.rmtree(workdir, True)
|
||||
else:
|
||||
print('not cleaning up %s' % workdir)
|
||||
LOG.warning('not cleaning up %s', workdir)
|
||||
atexit.register(cleanup_workdir)
|
||||
|
||||
# Allow for independent projects.
|
||||
@ -441,6 +447,9 @@ def main():
|
||||
|
||||
sha = gitutils.sha_for_tag(workdir, repo, version)
|
||||
|
||||
# Check out the working repo to the sha
|
||||
gitutils.checkout_ref(workdir, repo, sha)
|
||||
|
||||
if is_retagging:
|
||||
changes += 1
|
||||
LOG.info('re-tagging %s at %s (%s)', repo, sha, previous_tag)
|
||||
@ -468,6 +477,29 @@ def main():
|
||||
projects.append(new_project)
|
||||
|
||||
elif previous_sha != sha or force_tag:
|
||||
# TODO(tonyb): Do this early and also prompt for release type.
|
||||
# Once we do that we can probably deprecate interactive-release
|
||||
if args.interactive:
|
||||
# NOTE(tonyb): This is pretty much just copied from
|
||||
# interactive-release
|
||||
last_tag = '.'.join(last_version)
|
||||
change_lines = list(clean_changes(gitutils.changes_since(
|
||||
workdir, repo, last_tag).splitlines()))
|
||||
max_changes_show = 100
|
||||
LOG.info('')
|
||||
if last_tag:
|
||||
LOG.info("%s changes to %s since %s are:",
|
||||
len(change_lines), repo, last_tag)
|
||||
else:
|
||||
LOG.info("%s changes to %s are:", len(change_lines), repo)
|
||||
for sha, descr in change_lines[0:max_changes_show]:
|
||||
LOG.info("* %s %s", sha[:7], descr)
|
||||
leftover_change_lines = change_lines[max_changes_show:]
|
||||
if leftover_change_lines:
|
||||
LOG.info(" and %s more changes...",
|
||||
len(leftover_change_lines))
|
||||
LOG.info('')
|
||||
|
||||
changes += 1
|
||||
LOG.info('advancing %s from %s (%s) to %s',
|
||||
repo, previous_sha, previous_tag, sha)
|
||||
@ -507,7 +539,12 @@ def main():
|
||||
'location': new_version,
|
||||
})
|
||||
|
||||
if changes > 0:
|
||||
create_release = changes > 0
|
||||
if create_release and args.interactive:
|
||||
create_release = yes_no_prompt(
|
||||
'Create a release in %s containing those changes? ' % series)
|
||||
|
||||
if create_release:
|
||||
deliverable_filename = 'deliverables/%s/%s.yaml' % (
|
||||
series, args.deliverable)
|
||||
with open(deliverable_filename, 'w', encoding='utf-8') as f:
|
||||
|
@ -42,6 +42,26 @@ def find_modified_deliverable_files():
|
||||
return filenames
|
||||
|
||||
|
||||
def changes_since(workdir, repo, ref):
|
||||
"""Get all changes between the last ref and the current point.
|
||||
|
||||
:param workdir: The git repo working directory.
|
||||
:param repo: The name of the repo.
|
||||
:param ref: The starting ref.
|
||||
:returns: Merged commits between the two points.
|
||||
"""
|
||||
try:
|
||||
changes = processutils.check_output(
|
||||
['git', 'log', '--decorate', '--no-merges', '--pretty=oneline',
|
||||
"%s..HEAD" % ref],
|
||||
cwd=os.path.join(workdir, repo),
|
||||
).decode('utf-8').strip()
|
||||
except processutils.CalledProcessError as err:
|
||||
LOG.error('Could not find {}: {}'.format(ref, err))
|
||||
changes = ''
|
||||
return changes
|
||||
|
||||
|
||||
def commit_exists(workdir, repo, ref):
|
||||
"""Return boolean specifying whether the reference exists in the repository.
|
||||
|
||||
@ -126,7 +146,7 @@ def safe_clone_repo(workdir, repo, ref, messages):
|
||||
return True
|
||||
|
||||
|
||||
def checkout_ref(workdir, repo, ref, messages):
|
||||
def checkout_ref(workdir, repo, ref, messages=None):
|
||||
"""Checkout a specific ref in the repo."""
|
||||
|
||||
LOG.debug('Resetting the repository %s to HEAD', repo)
|
||||
@ -138,9 +158,10 @@ def checkout_ref(workdir, repo, ref, messages):
|
||||
['git', 'reset', '--hard'],
|
||||
cwd=os.path.join(workdir, repo))
|
||||
except processutils.CalledProcessError as err:
|
||||
messages.warning(
|
||||
'Could not reset repository {} to HEAD: {}'.format(
|
||||
repo, err))
|
||||
if messages:
|
||||
messages.warning(
|
||||
'Could not reset repository {} to HEAD: {}'.format(
|
||||
repo, err))
|
||||
|
||||
LOG.debug('Checking out repository %s to %s', repo, ref)
|
||||
try:
|
||||
@ -148,9 +169,10 @@ def checkout_ref(workdir, repo, ref, messages):
|
||||
['git', 'checkout', ref],
|
||||
cwd=os.path.join(workdir, repo))
|
||||
except processutils.CalledProcessError as err:
|
||||
messages.error(
|
||||
'Could not checkout repository {} at {}: {}'.format(
|
||||
repo, ref, err))
|
||||
if messages:
|
||||
messages.error(
|
||||
'Could not checkout repository {} at {}: {}'.format(
|
||||
repo, ref, err))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user