def test_one_expected_job(self): deliv = deliverable.Deliverable( team='team', series='series', name='name', data={ 'repository-settings': { 'openstack/releases': {}, }, }, ) self.ctx._zuul_projects = { 'openstack/releases': { 'templates': [ 'publish-to-pypi', ], }, } project_config.require_release_jobs_for_repo( deliv, deliv.repos[0], 'python-pypi', self.ctx, ) self.ctx.show_summary() self.assertEqual(0, len(self.ctx.warnings)) self.assertEqual(0, len(self.ctx.errors))
def test_no_zuul_layout(self): deliverable_info = { } zuul_layout = { } warnings = [] errors = [] project_config.require_release_jobs_for_repo( deliverable_info, {'validate-projects-by-name': zuul_layout}, 'openstack/releases', 'std', warnings.append, errors.append, ) self.assertEqual(0, len(warnings)) self.assertEqual(1, len(errors))
def test_no_zuul_projects(self): deliv = deliverable.Deliverable( team='team', series='series', name='name', data={ 'repository-settings': { 'openstack/releases': {}, }, }, ) self.ctx._zuul_projects = {'validate-projects-by-name': {}} project_config.require_release_jobs_for_repo( deliv, deliv.repos[0], 'std', self.ctx, ) self.assertEqual(0, len(self.ctx.warnings)) self.assertEqual(1, len(self.ctx.errors))
def test_one_expected_job(self): deliverable_info = { } zuul_layout = { 'openstack/releases': { 'template': [ {'name': 'publish-to-pypi'}, ], } } warnings = [] errors = [] project_config.require_release_jobs_for_repo( deliverable_info, {'validate-projects-by-name': zuul_layout}, 'openstack/releases', 'std', warnings.append, errors.append, ) print(warnings, errors) self.assertEqual(0, len(warnings)) self.assertEqual(0, len(errors))
def test_retired_flag(self): deliverable_info = { 'repository-settings': { 'openstack/releases': { 'flags': [ 'retired', ] } } } zuul_layout = { } warnings = [] errors = [] project_config.require_release_jobs_for_repo( deliverable_info, {'validate-projects-by-name': zuul_layout}, 'openstack/releases', 'std', warnings.append, errors.append, ) self.assertEqual(0, len(warnings)) self.assertEqual(0, len(errors))
def validate_releases(deliverable_info, zuul_layout, series_name, workdir, mk_warning, mk_error): """Apply validation rules to the 'releases' list for the deliverable. """ release_model = get_model(deliverable_info, series_name) is_independent = (release_model == 'independent') # Remember which entries are new so we can verify that they # appear at the end of the file. new_releases = {} release_type = deliverable_info.get('release-type', 'std') link_mode = deliverable_info.get('artifact-link-mode', 'tarball') prev_version = None prev_projects = set() for release in deliverable_info.get('releases', []): for project in release['projects']: # Check for release jobs (if we ship a tarball) if link_mode != 'none': project_config.require_release_jobs_for_repo( deliverable_info, zuul_layout, project['repo'], release_type, mk_warning, mk_error, ) # Check the SHA specified for the tag. print('%s SHA %s ' % (project['repo'], project['hash'])) if not is_a_hash(project['hash']): mk_error( ('%(repo)s version %(version)s release from ' '%(hash)r, which is not a hash') % { 'repo': project['repo'], 'hash': project['hash'], 'version': release['version'], } ) else: # Report if the SHA exists or not (an error if it # does not). sha_exists = gitutils.commit_exists( project['repo'], project['hash'], ) if not sha_exists: mk_error('No commit %(hash)r in %(repo)r' % project) # No point in running extra checks if the SHA just # doesn't exist. continue # Report if the version has already been # tagged. We expect it to not exist, but neither # case is an error because sometimes we want to # import history and sometimes we want to make new # releases. version_exists = gitutils.tag_exists( project['repo'], release['version'], ) gitutils.clone_repo(workdir, project['repo']) if version_exists: actual_sha = gitutils.sha_for_tag( workdir, project['repo'], release['version'], ) if actual_sha != project['hash']: mk_error( ('Version %s in %s is on ' 'commit %s instead of %s') % (release['version'], project['repo'], actual_sha, project['hash'])) else: print('Found new version {}'.format(release['version'])) new_releases[release['version']] = release if prev_projects and project['repo'] not in prev_projects: print('not included in previous release for %s: %s' % (prev_version, ', '.join(sorted(prev_projects)))) else: for e in versionutils.validate_version( release['version'], release_type=release_type, pre_ok=(release_model in _USES_PREVER)): msg = ('could not validate version %r: %s' % (release['version'], e)) mk_error(msg) if is_independent: mk_warning('skipping descendant test for ' 'independent project, verify ' 'branch manually') elif not prev_version: # If this is the first version in the series, # check that the commit is actually on the # targeted branch. if not gitutils.check_branch_sha(workdir, project['repo'], series_name, defaults.RELEASE, project['hash']): msg = '%s %s not present in %s branch' % ( project['repo'], project['hash'], series_name, ) mk_error(msg) else: # Check to see if we are re-tagging the same # commit with a new version. old_sha = gitutils.sha_for_tag( workdir, project['repo'], prev_version, ) if old_sha == project['hash']: # FIXME(dhellmann): This needs a test. print('Retagging the SHA with a new version') else: # Check to see if the commit for the new # version is in the ancestors of the # previous release, meaning it is actually # merged into the branch. is_ancestor = gitutils.check_ancestry( workdir, project['repo'], prev_version, project['hash'], ) if not is_ancestor: mk_error( '%s %s receiving %s ' 'is not a descendant of %s' % ( project['repo'], project['hash'], release['version'], prev_version, ) ) prev_version = release['version'] prev_projects = set(p['repo'] for p in release['projects']) # Make sure that new entries have been appended to the file. for v, nr in new_releases.items(): if nr != deliverable_info['releases'][-1]: msg = ('new release %s must be listed last, ' 'with one new release per patch' % nr['version']) mk_error(msg)
def validate_releases(deliverable_info, zuul_layout, series_name, workdir, mk_warning, mk_error): """Apply validation rules to the 'releases' list for the deliverable. """ release_model = get_model(deliverable_info, series_name) is_independent = (release_model == 'independent') # Remember which entries are new so we can verify that they # appear at the end of the file. new_releases = {} release_type = deliverable_info.get('release-type', 'std') link_mode = deliverable_info.get('artifact-link-mode', 'tarball') prev_version = None prev_projects = set() for release in deliverable_info.get('releases', []): print('checking %s' % release['version']) for project in release['projects']: # Check for release jobs (if we ship a tarball) if link_mode != 'none': project_config.require_release_jobs_for_repo( deliverable_info, zuul_layout, project['repo'], release_type, mk_warning, mk_error, ) # Check the SHA specified for the tag. print('%s SHA %s ' % (project['repo'], project['hash'])) if not is_a_hash(project['hash']): mk_error( ('%(repo)s version %(version)s release from ' '%(hash)r, which is not a hash') % { 'repo': project['repo'], 'hash': project['hash'], 'version': release['version'], }) else: # Report if the SHA exists or not (an error if it # does not). sha_exists = gitutils.commit_exists( project['repo'], project['hash'], ) if not sha_exists: mk_error('No commit %(hash)r in %(repo)r' % project) # No point in running extra checks if the SHA just # doesn't exist. continue # Ensure we have a local copy of the repository so we # can scan for values that are more difficult to get # remotely. gitutils.clone_repo(workdir, project['repo'], project['hash']) # Check that the sdist name and tarball-base name match. if link_mode == 'tarball': sdist = pythonutils.get_sdist_name(workdir, project['repo']) if sdist is not None: expected = project.get( 'tarball-base', os.path.basename(project['repo']), ) if sdist != expected: if 'tarball-base' in project: action = 'is set to' else: action = 'defaults to' mk_error(('tarball-base for %s %s %s %r ' 'but the sdist name is actually %r. ' + _PLEASE) % (project['repo'], release['version'], action, expected, sdist)) # Report if the version has already been # tagged. We expect it to not exist, but neither # case is an error because sometimes we want to # import history and sometimes we want to make new # releases. version_exists = gitutils.tag_exists( project['repo'], release['version'], ) if version_exists: actual_sha = gitutils.sha_for_tag( workdir, project['repo'], release['version'], ) if actual_sha != project['hash']: mk_error(('Version %s in %s is on ' 'commit %s instead of %s') % (release['version'], project['repo'], actual_sha, project['hash'])) else: print('Found new version {}'.format(release['version'])) new_releases[release['version']] = release if prev_projects and project['repo'] not in prev_projects: print('not included in previous release for %s: %s' % (prev_version, ', '.join(sorted(prev_projects)))) else: for e in versionutils.validate_version( release['version'], release_type=release_type, pre_ok=(release_model in _USES_PREVER)): msg = ('could not validate version %r: %s' % (release['version'], e)) mk_error(msg) # If this is a puppet module, ensure # that the tag and metadata file # match. if puppetutils.looks_like_a_module( workdir, project['repo']): puppet_ver = puppetutils.get_version( workdir, project['repo']) if puppet_ver != release['version']: mk_error('%s metadata contains "%s" ' 'but is being tagged "%s"' % ( project['repo'], puppet_ver, release['version'], )) if is_independent: mk_warning('skipping descendant test for ' 'independent project, verify ' 'branch manually') else: # If this is the first version in the series, # check that the commit is actually on the # targeted branch. if not gitutils.check_branch_sha( workdir, project['repo'], series_name, defaults.RELEASE, project['hash']): msg = '%s %s not present in %s branch' % ( project['repo'], project['hash'], series_name, ) mk_error(msg) if prev_version: # Check to see if we are re-tagging the same # commit with a new version. old_sha = gitutils.sha_for_tag( workdir, project['repo'], prev_version, ) if old_sha == project['hash']: # FIXME(dhellmann): This needs a test. print('Retagging the SHA with ' 'a new version') else: # Check to see if the commit for the new # version is in the ancestors of the # previous release, meaning it is actually # merged into the branch. is_ancestor = gitutils.check_ancestry( workdir, project['repo'], prev_version, project['hash'], ) if not is_ancestor: mk_error('%s %s receiving %s ' 'is not a descendant of %s' % ( project['repo'], project['hash'], release['version'], prev_version, )) prev_version = release['version'] prev_projects = set(p['repo'] for p in release['projects']) # Make sure that new entries have been appended to the file. for v, nr in new_releases.items(): if nr != deliverable_info['releases'][-1]: msg = ('new release %s must be listed last, ' 'with one new release per patch' % nr['version']) mk_error(msg)