def test_project_overrides(self): deliv = deliverable.Deliverable( team='team', series='newton', name='name', data={ 'releases': [{ 'version': '1.5.0', 'projects': [ { 'repo': 'openstack/release-test', 'hash': 'a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5', 'tarball-base': 'foo' }, ] }], 'repository-settings': { 'openstack/release-test': { 'tarball-base': 'bar', }, }, }, ) project = deliv.releases[-1].projects[0] self.assertEqual('foo', project.tarball_base)
def main(): parser = argparse.ArgumentParser() parser.add_argument( 'deliverable', help='the name of the deliverable, such as "nova" or "oslo.config"', ) parser.add_argument( '--series', default=defaults.RELEASE, help='the release series, such as "newton" or "ocata"', ) parser.add_argument( '--deliverables-dir', default=openstack_releases.deliverable_dir, help='location of deliverable files', ) args = parser.parse_args() # Deal with the inconsistency of the name for the independent # directory. series = args.series if series == 'independent': series = '_independent' all_deliv = deliverable.Deliverables( root_dir=args.deliverables_dir, collapse_history=False, ) for entry in all_deliv.get_deliverable_history(args.deliverable): deliv = deliverable.Deliverable(*entry) print(deliv.team) break
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_default_to_series(self): d = deliverable.Deliverable( team='team', series='ocata', name='name', data={}, ) self.assertEqual('extended maintenance', d.stable_status)
def test_override_series(self): d = deliverable.Deliverable( team='team', series='newton', name='name', data={ 'stable-status': 'extended maintenance', }, ) self.assertEqual('extended maintenance', d.stable_status)
def repositories_list(deliverables_dir, series): """Yields (team, repo) tuples for cycle-with-milestones deliverables""" deliverables = deliverable.Deliverables(deliverables_dir) for team, series, dname, dinfo in deliverables.get_deliverables(None, series): d = deliverable.Deliverable(team, series, dname, dinfo) if d.model != 'cycle-with-milestones': continue if not d.repos: print('WARNING: no releases for {} in {}'.format(dname, series)) for repo in sorted(d.repos): yield (d.team, repo)
def main(): parser = argparse.ArgumentParser() parser.add_argument( '--deliverables-dir', default=openstack_releases.deliverable_dir, help='location of deliverable files', ) parser.add_argument( '--series', default=defaults.RELEASE, help='the release series, such as "newton" or "ocata"', ) args = parser.parse_args() all_deliv = deliverable.Deliverables( root_dir=args.deliverables_dir, collapse_history=False, ) interesting_deliverables = [ d for d in ( deliverable.Deliverable(t, s, dn, da) for t, s, dn, da in all_deliv.get_deliverables(None, args.series)) if d.model == MILESTONE ] team_data = governance.get_team_data() teams = {n.lower(): governance.Team(n, i) for n, i in team_data.items()} # Dump the dashboard data writer = csv.writer(sys.stdout) writer.writerow( ('Team', 'Deliverable Type', 'Deliverable Name', 'Pre-RC1', 'RC1', 'Branched at', 'Latest RC', 'Release Notes', 'Comments', 'PTL Nick', 'PTL Email', 'Liaison Nick', 'IRC Channel')) for deliv in sorted(interesting_deliverables, key=lambda x: (x.team, x.name)): team = teams[deliv.team.lower()] writer.writerow(( deliv.team.lower(), deliv.type, deliv.name, deliv.latest_release, '', # RC1 deliv.get_branch_location('stable/' + args.series), # branched at '', # latest RC deliv.release_notes, '', # Comments team.data['ptl']['irc'], team.data['ptl']['email'], team.liaison[1] or '', team.data.get('irc-channel')))
def test_is_eol_tag_true(self): deliverable_data = textwrap.dedent(''' releases: - version: newton-eol projects: - repo: openstack/release-test hash: a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5 ''') deliv = deliverable.Deliverable( team='team', series='newton', name='name', data=yamlutils.loads(deliverable_data), ) self.assertTrue(deliv.releases[-1].is_eol)
def test_eol_series_for_version_tag(self): deliverable_data = textwrap.dedent(''' releases: - version: 0.3.0 projects: - repo: openstack/release-test hash: a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5 ''') deliv = deliverable.Deliverable( team='team', series='newton', name='name', data=yamlutils.loads(deliverable_data), ) self.assertEqual( '', deliv.releases[-1].eol_series, )
def test_not_set(self): deliv = deliverable.Deliverable( team='team', series='newton', name='name', data={ 'releases': [{ 'version': '1.5.0', 'projects': [ { 'repo': 'openstack/release-test', 'hash': 'a26e6a2e8a5e321b2e3517dbb01a7b9a56a8bfd5' }, ] }], }, ) project = deliv.releases[-1].projects[0] self.assertIsNone(project.tarball_base)
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 main(): parser = argparse.ArgumentParser() output_mode = parser.add_mutually_exclusive_group() output_mode.add_argument( '-v', '--verbose', action='store_true', default=False, help='show more than the deliverable name', ) output_mode.add_argument( '-r', '--repos', action='store_true', default=False, help='show the repository names not deliverable names', ) parser.add_argument( '--team', help='the name of the project team, such as "Nova" or "Oslo"', ) parser.add_argument( '--deliverable', help='the name of the deliverable, such as "nova" or "oslo.config"', ) parser.add_argument( '--series', default=defaults.RELEASE, help='the release series, such as "newton" or "ocata"', ) parser.add_argument( '--csvfile', help='Save results (same as when --verbose) to CSV file', ) model = parser.add_mutually_exclusive_group() model.add_argument( '--model', help=('the release model, such as "cycle-with-milestones"' ' or "independent"'), ) model.add_argument( '--cycle-based', action='store_true', default=False, help='include all cycle-based code repositories', ) parser.add_argument( '--type', help='deliverable type, such as "library" or "service"', ) parser.add_argument( '--tag', default=[], action='append', help='look for one more more tags on the deliverable or team', ) parser.add_argument( '--deliverables-dir', default=openstack_releases.deliverable_dir, help='location of deliverable files', ) parser.add_argument( '--no-stable-branch', default=False, action='store_true', help='limit the list to deliverables without a stable branch', ) grp = parser.add_mutually_exclusive_group() grp.add_argument( '--unreleased', default=False, action='store_true', help='limit the list to deliverables not released in the cycle', ) grp.add_argument( '--missing-milestone', help=('deliverables that do not have the specified milestone as ' 'the most current release; for example 2 would look for .0b2 ' 'in the version number (implies --model cycle-with-milestones)'), ) grp.add_argument( '--missing-rc', action='store_true', help=('deliverables that do not have a release candidate, yet ' '(implies --model cycle-with-milestones)'), ) grp.add_argument( '--missing-final', action='store_true', help='deliverables that have pre-releases but no final releases, yet', ) args = parser.parse_args() # Deal with the inconsistency of the name for the independent # directory. series = args.series if series == 'independent': series = '_independent' if args.missing_milestone: model = 'cycle-with-milestones' version_ending = '.0b{}'.format(args.missing_milestone) elif args.missing_rc: model = 'cycle-with-milestones' version_ending = None elif args.missing_final: model = args.model version_ending = None else: model = args.model version_ending = None verbose_template = '{name:30} {team:20}' if not args.unreleased: verbose_template += ' {latest_release:15}' if not args.type: verbose_template += ' {type:15}' if not args.model: verbose_template += ' {model:15}' csvfile = None if args.csvfile: csvfile = open(args.csvfile, 'w') fieldnames = [ 'name', 'latest_release', 'repo', 'hash', 'team', 'type', 'model' ] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() all_deliv = deliverable.Deliverables( root_dir=args.deliverables_dir, collapse_history=False, ) for entry in all_deliv.get_deliverables(args.team, series): deliv = deliverable.Deliverable(*entry) if args.deliverable and deliv.name != args.deliverable: continue if model and deliv.model != model: continue if args.cycle_based and not deliv.is_cycle_based: continue if args.type and deliv.type != args.type: continue if args.no_stable_branch: if deliv.get_branch_location('stable/' + series) is not None: continue if args.unreleased and deliv.versions: continue if version_ending and deliv.latest_release and deliv.latest_release.endswith( version_ending): continue if args.missing_rc and deliv.latest_release and 'rc' in deliv.latest_release: continue if args.tag: tags = deliv.tags for t in args.tag: if t not in tags: continue if args.missing_final and deliv.latest_release: if not ('rc' in deliv.latest_release or 'a' in deliv.latest_release or 'b' in deliv.latest_release): continue if csvfile: rel = (deliv.releases or [{}])[-1] for prj in rel.get('projects', [{}]): writer.writerow({ 'name': deliv.name, 'latest_release': rel.get('version', None), 'repo': prj.get('repo', None), 'hash': prj.get('hash', None), 'team': deliv.team, 'type': deliv.type, 'model': deliv.model, }) elif args.verbose: print( verbose_template.format( name=deliv.name, latest_release=deliv.latest_release, team=deliv.team, type=deliv.type, model=deliv.model, )) elif args.repos: for r in sorted(deliv.repos): print(r) else: print(deliv.name) if csvfile: csvfile.close()
def main(): parser = argparse.ArgumentParser() parser.add_argument( '-v', '--verbose', action='store_true', default=False, help='show more than the deliverable name', ) parser.add_argument( '--team', help='the name of the project team, such as "Nova" or "Oslo"', ) parser.add_argument( '--deliverable', help='the name of the deliverable, such as "nova" or "oslo.config"', ) parser.add_argument( '--series', default=defaults.RELEASE, help='the release series, such as "newton" or "ocata"', ) model = parser.add_mutually_exclusive_group() model.add_argument( '--model', help=('the release model, such as "cycle-with-milestones"' ' or "independent"'), ) model.add_argument( '--cycle-based', action='store_true', default=False, help='include all cycle-based code repositories', ) parser.add_argument( '--type', help='deliverable type, such as "library" or "service"', ) parser.add_argument( '--deliverables-dir', default=openstack_releases.deliverable_dir, help='location of deliverable files', ) parser.add_argument( '--branch', default=None, help='branch name, defaults to stable/$series', ) parser.add_argument( '--no-cleanup', dest='cleanup', default=True, action='store_false', help='do not remove temporary files', ) args = parser.parse_args() if args.verbose: def verbose(msg): print(msg) else: def verbose(msg): pass # Deal with the inconsistency of the name for the independent # directory. series = args.series if series == 'independent': series = '_independent' branch = args.branch if not branch: branch = 'stable/{}'.format(series) workdir = tempfile.mkdtemp(prefix='releases-') verbose('creating temporary files in {}'.format(workdir)) def cleanup_workdir(): if args.cleanup: try: verbose('cleaning up temporary files in {}'.format(workdir)) shutil.rmtree(workdir) except: pass else: print('not cleaning up {}'.format(workdir)) atexit.register(cleanup_workdir) # Count any errors for our exit code. errors = 0 all_deliv = deliverable.Deliverables( root_dir=args.deliverables_dir, collapse_history=False, ) for entry in all_deliv.get_deliverables(args.team, series): deliv = deliverable.Deliverable(*entry) branch_loc = deliv.get_branch_location(branch) if branch_loc is None: verbose('No stable branch for {}'.format(deliv.name)) continue all_versions = deliv.versions if all_versions[-1] == branch_loc: verbose('Most recent release for {} ({}) is at {}'.format( deliv.name, branch_loc, branch)) continue idx = all_versions.index(branch_loc) late_releases = all_versions[idx + 1:] print('{} releases {} come after {}'.format(deliv.name, late_releases, branch)) for repo in sorted(deliv.repos): verbose('cloning {}'.format(repo)) gitutils.clone_repo( workdir, repo, ) for version in late_releases: containing_br = gitutils.branches_containing( workdir, repo, version, ) for cb in containing_br: if branch in cb: # allow for remote prefix verbose('{} version {} is on branch {}'.format( repo, version, branch)) break else: print('{} version {} is not on branch {} ({})'.format( repo, version, branch, containing_br)) errors += 1 return (1 if errors else 0)
def main(): parser = argparse.ArgumentParser() parser.add_argument( '--deliverables-dir', default=openstack_releases.deliverable_dir, help='location of deliverable files', ) parser.add_argument( '--no-cleanup', dest='cleanup', default=True, action='store_false', help='do not remove temporary files', ) parser.add_argument( 'repository_cache', help='location of existing copies of repositories', ) parser.add_argument( 'series', help='the release series, such as "newton" or "ocata"', ) args = parser.parse_args() workdir = tempfile.mkdtemp(prefix='releases-') def cleanup_workdir(): if args.cleanup: try: shutil.rmtree(workdir) except: pass atexit.register(cleanup_workdir) branch_name = 'origin/stable/' + args.series all_deliv = deliverable.Deliverables( root_dir=args.deliverables_dir, collapse_history=False, ) for entry in all_deliv.get_deliverables(None, args.series): deliv = deliverable.Deliverable(*entry) if deliv.get_branch_location(branch_name) is not None: # the branch is already defined for this project sys.stderr.write('{} already has a branch {}\n'.format( deliv.name, branch_name)) continue # We're only importing stable branches, and those are # specified by the version number. We therefore only need one # repository, and it shouldn't matter which one. That said, we # might not actually find the branch in the first repo so loop # until we do. for r in deliv.repos: reporoot = os.path.join(args.repository_cache, r) version = _get_branch_base(reporoot, branch_name) if version: print(deliv.name, args.series, version) break else: sys.stderr.write('could not find {} in any repos for {}\n'.format( branch_name, deliv.name))