Simplify ref checkout in validate cmd

When the current code needs the repo checked out to a specific commit it
calls clone_repo. The clone_repo call makes sure the repo has been
cloned locally, performs a fetch to get all tags and prunes any
references no longer on the remote, then finally checks out the
requested ref.

The validation logic starts with cloning all necessary repos and
performing these actions, so after that point, we should be able to just
checkout the ref that we need for the given check. This will greatly
improve the execution time of the validate job for repos that have had a
large number of releases.

Change-Id: Ie444c8ef8e91832c38ee69307382ddb5fb8e1b08
Signed-off-by: Sean McGinnis <sean.mcginnis@gmail.com>
This commit is contained in:
Sean McGinnis 2018-09-22 21:19:01 -05:00
parent c6797b72d4
commit bb81a80fd0
3 changed files with 42 additions and 23 deletions

View File

@ -598,7 +598,7 @@ def validate_gitreview(deliv, context):
if not version_exists:
LOG.debug('checking {} at {} for {}'.format(
project.repo.name, project.hash, release.version))
gitutils.safe_clone_repo(
gitutils.checkout_ref(
context.workdir, project.repo.name, project.hash, context)
_require_gitreview(project.repo.name, context)
else:
@ -658,7 +658,7 @@ def validate_release_type(deliv, context):
if not version_exists:
LOG.debug('new version {}, checking release jobs'.format(
release.version))
gitutils.safe_clone_repo(
gitutils.checkout_ref(
context.workdir, project.repo.name, project.hash, context)
project_config.require_release_jobs_for_repo(
deliv,
@ -731,7 +731,7 @@ def validate_build_sdist(deliv, context):
release.version))
continue
gitutils.safe_clone_repo(
gitutils.checkout_ref(
context.workdir, project.repo.name, project.hash, context)
try:
@ -755,7 +755,7 @@ def validate_pypi_readme(deliv, context):
# the branch, in case the sdist name changes over time.
latest_release = deliv.releases[-1]
for project in latest_release.projects:
gitutils.safe_clone_repo(
gitutils.checkout_ref(
context.workdir, project.repo.name, project.hash, context)
if latest_release.is_eol:
@ -808,7 +808,7 @@ def validate_pypi_permissions(deliv, context):
# in case the sdist name changes over time.
latest_release = deliv.releases[-1]
for project in latest_release.projects:
gitutils.safe_clone_repo(
gitutils.checkout_ref(
context.workdir, project.repo.name, project.hash, context)
for repo in deliv.repos:
@ -894,8 +894,8 @@ def validate_release_sha_exists(deliv, context):
)
continue
if not gitutils.safe_clone_repo(context.workdir, project.repo.name,
project.hash, context):
if not gitutils.checkout_ref(context.workdir, project.repo.name,
project.hash, context):
continue
print('successfully cloned {}'.format(project.hash))
@ -923,8 +923,8 @@ def validate_existing_tags(deliv, context):
LOG.debug('{} SHA {}'.format(project.repo.name, project.hash))
if not gitutils.safe_clone_repo(context.workdir, project.repo.name,
project.hash, context):
if not gitutils.checkout_ref(context.workdir, project.repo.name,
project.hash, context):
continue
# Report if the version has already been
@ -992,8 +992,8 @@ def validate_version_numbers(deliv, context):
for project in release.projects:
if not gitutils.safe_clone_repo(context.workdir, project.repo.name,
project.hash, context):
if not gitutils.checkout_ref(context.workdir, project.repo.name,
project.hash, context):
continue
version_exists = gitutils.commit_exists(
@ -1126,8 +1126,8 @@ def validate_new_releases_at_end(deliv, context):
for project in release.projects:
if not gitutils.safe_clone_repo(context.workdir, project.repo.name,
project.hash, context):
if not gitutils.checkout_ref(context.workdir, project.repo.name,
project.hash, context):
continue
version_exists = gitutils.commit_exists(
@ -1142,7 +1142,7 @@ def validate_new_releases_at_end(deliv, context):
new_releases[release.version] = release
# Make sure that new entries have been appended to the file.
for v, nr in new_releases.items():
for _, nr in new_releases.items():
LOG.debug('comparing {!r} to {!r}'.format(nr, deliv.releases[-1]))
if nr != deliv.releases[-1]:
msg = ('new release %s must be listed last, '
@ -1173,8 +1173,8 @@ def validate_new_releases_in_open_series(deliv, context):
for project in release.projects:
if not gitutils.safe_clone_repo(context.workdir, project.repo.name,
project.hash, context):
if not gitutils.checkout_ref(context.workdir, project.repo.name,
project.hash, context):
continue
version_exists = gitutils.commit_exists(
@ -1225,8 +1225,8 @@ def validate_release_branch_membership(deliv, context):
for project in release.projects:
if not gitutils.safe_clone_repo(context.workdir, project.repo.name,
project.hash, context):
if not gitutils.checkout_ref(context.workdir, project.repo.name,
project.hash, context):
continue
version_exists = gitutils.commit_exists(
@ -1444,8 +1444,8 @@ def validate_stable_branches(deliv, context):
)
# We can't clone the location if it isn't a SHA.
continue
if not gitutils.safe_clone_repo(context.workdir, repo, loc,
context):
if not gitutils.checkout_ref(context.workdir, repo, loc,
context):
continue
if not gitutils.commit_exists(context.workdir, repo, loc):
context.error(
@ -1499,7 +1499,7 @@ def validate_feature_branches(deliv, context):
for branch in deliv.branches:
try:
prefix, series = branch.name.split('/')
prefix, _ = branch.name.split('/')
except ValueError:
context.error(
('feature branch name expected to be feature/name '

View File

@ -128,6 +128,22 @@ def safe_clone_repo(workdir, repo, ref, messages):
return True
def checkout_ref(workdir, repo, ref, messages):
"""Checkout a specific ref in the repo."""
LOG.debug('Checking out repository %s to %s', repo, ref)
try:
processutils.check_call(
['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))
return False
return True
def sha_for_tag(workdir, repo, version):
"""Return the SHA for a given tag
"""

View File

@ -593,7 +593,7 @@ class TestValidateReleaseSHAExists(base.BaseTestCase):
validate.validate_release_sha_exists(deliv, self.ctx)
self.ctx.show_summary()
self.assertEqual(0, len(self.ctx.warnings))
self.assertEqual(1, len(self.ctx.errors))
self.assertEqual(0, len(self.ctx.errors))
def test_no_such_hash(self):
deliv = deliverable.Deliverable(
@ -653,7 +653,7 @@ class TestValidateExistingTags(base.BaseTestCase):
self.repo.tag('0.8.0')
self.commit_2 = self.repo.add_file('testfile2.txt')
@mock.patch('openstack_releases.gitutils.safe_clone_repo')
@mock.patch('openstack_releases.gitutils.checkout_ref')
def test_valid(self, clone):
deliv = deliverable.Deliverable(
team='team',
@ -798,6 +798,7 @@ class TestValidateReleaseBranchMembership(base.BaseTestCase):
self.assertEqual(1, len(self.ctx.errors))
def test_hash_from_master_used_after_default_branch_should_exist_but_does_not(self):
gitutils.clone_repo(self.ctx.workdir, 'openstack/releases')
deliv = deliverable.Deliverable(
team='team',
series='austin',
@ -1479,6 +1480,7 @@ class TestPuppetUtils(base.BaseTestCase):
llam.return_value = True
get_version.return_value = '99.1.0'
cbs.return_value = True
gitutils.clone_repo(self.ctx.workdir, 'openstack/puppet-watcher')
deliv = deliverable.Deliverable(
team='team',
series='ocata',
@ -1506,6 +1508,7 @@ class TestPuppetUtils(base.BaseTestCase):
llam.return_value = True
get_version.return_value = '99.1.0'
cbs.return_value = True
gitutils.clone_repo(self.ctx.workdir, 'openstack/puppet-watcher')
deliv = deliverable.Deliverable(
team='team',
series=defaults.RELEASE,