Пример #1
0
    def test_select_multibuild_package(self):
        self.wf.setup_rings()
        staging = self.wf.create_staging('A', freeze=True)

        project = self.wf.create_project('devel:gcc')
        package = OBSLocal.Package(name='gcc9', project=project)
        package.create_commit(filename='gcc9.spec', text='Name: gcc9')
        package.create_commit(filename='gcc9-tests.spec')
        package.create_commit(
            '<multibuild><flavor>gcc9-tests.spec</flavor></multibuild>',
            filename='_multibuild')
        self.wf.submit_package(package)

        ret = SelectCommand(self.wf.api, staging.name).perform(['gcc9'])
        self.assertEqual(True, ret)

        self.assertEqual(package_list(self.wf.apiurl, staging.name), ['gcc9'])
        file = source_file_load(self.wf.apiurl, staging.name, 'gcc9',
                                'gcc9.spec')
        self.assertEqual(file, 'Name: gcc9')

        uc = UnselectCommand(self.wf.api)
        self.assertIsNone(uc.perform(['gcc9'], False, None))

        # no stale links
        self.assertEqual([], package_list(self.wf.apiurl, staging.name))
Пример #2
0
    def test_accept_switch_to_multibuild_package(self):
        wf = self.setup_wf()

        staging = wf.create_staging('A', freeze=True)

        tpackage = wf.create_package('target', 'gcc9')
        tpackage.create_commit(filename='gcc9.spec')
        tpackage.create_commit(filename='gcc9-tests.spec')
        lpackage = wf.create_package('target', 'gcc9-tests')
        lpackage.create_commit('<link package="gcc9" cicount="copy" />', filename='_link')

        project = wf.create_project('devel:gcc')
        package = OBSLocal.Package(name='gcc9', project=project)
        package.create_commit(filename='gcc9.spec')
        package.create_commit(filename='gcc9-tests.spec')
        package.create_commit('<multibuild><flavor>gcc9-tests.spec</flavor></multibuild>', filename='_multibuild')

        wf.submit_package(package)

        ret = SelectCommand(wf.api, staging.name).perform(['gcc9'])
        ac = AcceptCommand(wf.api)
        self.assertEqual(True, ac.accept_all(['A'], True))

        # no stale links
        self.assertEqual([], package_list(wf.apiurl, staging.name))
        self.assertEqual(['gcc9', 'wine'], package_list(wf.apiurl, wf.project))
Пример #3
0
    def test_select_multiple_spec(self):
        self.wf.setup_rings()
        staging = self.wf.create_staging('A', freeze=True)

        project = self.wf.create_project('devel:gcc')
        package = OBSLocal.Package(name='gcc8', project=project)
        package.create_commit(filename='gcc8.spec', text='Name: gcc8')
        package.create_commit(filename='gcc8-tests.spec')
        self.wf.submit_package(package)

        ret = SelectCommand(self.wf.api, staging.name).perform(['gcc8'])
        self.assertEqual(True, ret)

        self.assertEqual(package_list(self.wf.apiurl, staging.name),
                         ['gcc8', 'gcc8-tests'])
        file = source_file_load(self.wf.apiurl, staging.name, 'gcc8',
                                'gcc8.spec')
        self.assertEqual(file, 'Name: gcc8')
        # we should see the spec file also in the 2nd package
        file = source_file_load(self.wf.apiurl, staging.name, 'gcc8-tests',
                                'gcc8.spec')
        self.assertEqual(file, 'Name: gcc8')

        uc = UnselectCommand(self.wf.api)
        self.assertIsNone(uc.perform(['gcc8'], False, None))

        # no stale links
        self.assertEqual([], package_list(self.wf.apiurl, staging.name))
Пример #4
0
    def test_accept_new_multispec_package(self):
        wf = self.setup_wf()

        staging = wf.create_staging('A', freeze=True)

        project = wf.create_project('devel:gcc')
        package = OBSLocal.Package(name='gcc9', project=project)
        package.create_commit(filename='gcc9.spec')
        package.create_commit(filename='gcc9-tests.spec')
        wf.submit_package(package)

        ret = SelectCommand(wf.api, staging.name).perform(['gcc9'])
        ac = AcceptCommand(wf.api)
        self.assertEqual(True, ac.accept_all(['A'], True))

        # no stale links
        self.assertEqual([], package_list(wf.apiurl, staging.name))
        self.assertEqual(['gcc9', 'gcc9-tests', 'wine'], package_list(wf.apiurl, wf.project))
Пример #5
0
    def test_select_multiple_spec(self):
        self.wf.setup_rings()
        staging = self.wf.create_staging('A', freeze=True)

        project = self.wf.create_project('devel:gcc')
        package = OBSLocal.Package(name='gcc8', project=project)
        package.create_commit(filename='gcc8.spec')
        package.create_commit(filename='gcc8-tests.spec')
        self.wf.submit_package(package)

        ret = SelectCommand(self.wf.api, staging.name).perform(['gcc8'])
        self.assertEqual(True, ret)

        self.assertEqual(package_list(self.wf.apiurl, staging.name), ['gcc8', 'gcc8-tests'])
        uc = UnselectCommand(self.wf.api)
        self.assertIsNone(uc.perform(['gcc8']))

        # no stale links
        self.assertEqual([], package_list(self.wf.apiurl, staging.name))
Пример #6
0
def osrt_origin_update_packages(apiurl, project):
    packages = set(package_list_kind_filtered(apiurl, project))

    # Include packages from origins with initial update enabled to allow for
    # potential new package submissions.
    for origin in origin_updatable_initial(apiurl, project):
        for package in package_list(apiurl, origin):
            # Only add missing package if it does not exist in target
            # project. If it exists in target then it is not a source
            # package (since origin list is filtered to source) and should
            # not be updated. This also properly avoids submitting a package
            # that is a subpackage in target, but is a source package in an
            # origin project.
            if package in packages or entity_exists(apiurl, project, package):
                continue

            # No sense submitting a non-source package (most expensive).
            if package_kind(apiurl, origin, package) == 'source':
                packages.add(package)

    return packages
Пример #7
0
def main(args):
    # Store the default apiurl in addition to the overriden url if the
    # option was set and thus overrides the default config value.
    # Using the OBS link does not work for ?view=issues.
    if args.apiurl is not None:
        osc.conf.get_config()
        apiurl_default = osc.conf.config['apiurl']
    else:
        apiurl_default = None

    osc.conf.get_config(override_apiurl=args.apiurl)
    osc.conf.config['debug'] = args.debug
    apiurl = osc.conf.config['apiurl']

    Cache.init()

    git_repo_url = '[email protected]:jberry-suse/openSUSE-release-tools-issue-db.git'
    git_message = 'Sync issue-diff.py changes.'
    db_dir = sync(args.cache_dir, git_repo_url, git_message)
    db_file = os.path.join(db_dir, '{}.yml'.format(args.project))

    if os.path.exists(db_file):
        db = yaml.safe_load(open(db_file).read())
        if db is None:
            db = {}
        else:
            print('Loaded db file: {}'.format(db_file))
    else:
        db = {}

    if args.print_stats:
        print_stats(db)
        return

    print('Comparing {} against {}'.format(args.project, args.factory))

    bugzilla_api = bugzilla_init(args.bugzilla_apiurl)
    bugzilla_defaults = (args.bugzilla_product, args.bugzilla_component, args.bugzilla_version)

    trackers = issue_trackers(apiurl)
    packages_project = package_list(apiurl, args.project)
    packages_factory = package_list(apiurl_default, args.factory)
    packages = set(packages_project).intersection(set(packages_factory))
    new = 0
    shuffle(list(packages))
    for index, package in enumerate(packages, start=1):
        if index % 50 == 0:
            print('Checked {} of {}'.format(index, len(packages)))
        if package in db and db[package] == 'whitelist':
            print('Skipping package {}'.format(package))
            continue

        issues_project = issues_get(apiurl, args.project, package, trackers, db)
        issues_factory = issues_get(apiurl_default, args.factory, package, trackers, db)

        missing_from_factory = set(issues_project.keys()) - set(issues_factory.keys())

        # Filtering by age must be done after set diff in order to allow for
        # matches with issues newer than --newest.
        for label in set(missing_from_factory):
            if issues_project[label]['age'] < args.newest:
                missing_from_factory.remove(label)

        if len(missing_from_factory) == 0:
            continue

        print('{}: {} missing'.format(package, len(missing_from_factory)))

        # Generate summaries for issues missing from factory.
        changes = {}
        for issue in missing_from_factory:
            info = issues_project[issue]
            summary = ISSUE_SUMMARY if info['owner'] else ISSUE_SUMMARY_PLAIN
            changes[issue] = summary.format(
                label=issue, url=info['url'], owner=info['owner'], summary=info['summary'])

        # Prompt user to decide which issues to whitelist.
        changes_after = prompt_interactive(changes, args.project, package)

        # Determine if any real changes (vs typos) and create text issue list.
        issues = []
        cc = []
        if len(changes_after) > 0:
            for issue, summary in changes.items():
                if issue in changes_after:
                    info = issues_project[issue]
                    if issue.startswith('bsc'):
                        # Reformat for bugzilla markdown.
                        summary = ISSUE_SUMMARY_BUGZILLA if info['owner'] else ISSUE_SUMMARY_PLAIN_BUGZILLA
                        issue = issue.replace('bsc', 'bug')
                        summary = summary.format(
                            label=issue, url=info['url'], owner=info['owner'], summary=info['summary'])
                    issues.append('- ' + summary)
                    if info['owner'] is not None:
                        cc.append(info['owner'])

        # Prompt user about how to continue.
        response = prompt_continue(len(issues))
        if response == 'n':
            break
        if response == 's':
            continue

        # File a bug if not all issues whitelisted.
        if len(issues) > 0:
            summary = BUG_SUMMARY.format(project=args.project, factory=args.factory, package=package)
            message = BUG_TEMPLATE.format(
                message_start=MESSAGE_START.format(
                    project=args.project, factory=args.factory, package=package, newest=args.newest),
                issues='\n'.join(issues))
            if len(message) > 65535:
                # Truncate messages longer than bugzilla limit.
                message = message[:65535 - 3] + '...'

            # Determine bugzilla meta information to use when creating bug.
            meta = bug_meta(bugzilla_api, bugzilla_defaults, trackers, changes.keys())
            owner = bug_owner(apiurl, package)
            if args.bugzilla_cc:
                cc.append(args.bugzilla_cc)

            # Try to create bug, but allow for handling faults.
            tries = 0
            while tries < 10:
                try:
                    bug_id = bug_create(bugzilla_api, meta, owner, cc, summary, message)
                    break
                except Fault as e:
                    if 'There is no component named' in e.faultString:
                        print('Invalid component {}, fallback to default'.format(meta[1]))
                        meta = (meta[0], bugzilla_defaults[1], meta[2])
                    elif 'is not a valid username' in e.faultString:
                        username = e.faultString.split(' ', 3)[2]
                        cc.remove(username)
                        print('Removed invalid username {}'.format(username))
                    else:
                        raise e
                tries += 1

        # Mark changes in db.
        notified, whitelisted = 0, 0
        for issue in changes:
            if package not in db:
                db[package] = {}

            if issue in changes_after:
                db[package][issue] = str(bug_id)
                notified += 1
            else:
                db[package][issue] = 'whitelist'
                whitelisted += 1

        # Write out changes after each package to avoid loss.
        with open(db_file, 'w') as outfile:
            yaml.safe_dump(db, outfile, default_flow_style=False, default_style="'")

        if notified > 0:
            print('{}: {} notified in bug {}, {} whitelisted'.format(package, notified, bug_id, whitelisted))
        else:
            print('{}: {} whitelisted'.format(package, whitelisted))

        if response == 'b':
            break

        new += 1
        if new == args.limit:
            print('stopped at limit')
            break

    sync(args.cache_dir, git_repo_url, git_message)
Пример #8
0
def main(args):
    # Store the default apiurl in addition to the overriden url if the
    # option was set and thus overrides the default config value.
    # Using the OBS link does not work for ?view=issues.
    if args.apiurl is not None:
        osc.conf.get_config()
        apiurl_default = osc.conf.config['apiurl']
    else:
        apiurl_default = None

    osc.conf.get_config(override_apiurl=args.apiurl)
    osc.conf.config['debug'] = args.debug
    apiurl = osc.conf.config['apiurl']

    Cache.init()

    git_repo_url = '[email protected]:jberry-suse/openSUSE-release-tools-issue-db.git'
    git_message = 'Sync issue-diff.py changes.'
    db_dir = sync(args.cache_dir, git_repo_url, git_message)
    db_file = os.path.join(db_dir, '{}.yml'.format(args.project))

    if os.path.exists(db_file):
        db = yaml.safe_load(open(db_file).read())
        if db is None:
            db = {}
        else:
            print('Loaded db file: {}'.format(db_file))
    else:
        db = {}

    if args.print_stats:
        print_stats(db)
        return

    print('Comparing {} against {}'.format(args.project, args.factory))

    bugzilla_api = bugzilla_init(args.bugzilla_apiurl)
    bugzilla_defaults = (args.bugzilla_product, args.bugzilla_component,
                         args.bugzilla_version)

    trackers = issue_trackers(apiurl)
    packages_project = package_list(apiurl, args.project)
    packages_factory = package_list(apiurl_default, args.factory)
    packages = set(packages_project).intersection(set(packages_factory))
    new = 0
    shuffle(list(packages))
    for index, package in enumerate(packages, start=1):
        if index % 50 == 0:
            print('Checked {} of {}'.format(index, len(packages)))
        if package in db and db[package] == 'whitelist':
            print('Skipping package {}'.format(package))
            continue

        issues_project = issues_get(apiurl, args.project, package, trackers,
                                    db)
        issues_factory = issues_get(apiurl_default, args.factory, package,
                                    trackers, db)

        missing_from_factory = set(issues_project.keys()) - set(
            issues_factory.keys())

        # Filtering by age must be done after set diff in order to allow for
        # matches with issues newer than --newest.
        for label in set(missing_from_factory):
            if issues_project[label]['age'] < args.newest:
                missing_from_factory.remove(label)

        if len(missing_from_factory) == 0:
            continue

        print('{}: {} missing'.format(package, len(missing_from_factory)))

        # Generate summaries for issues missing from factory.
        changes = {}
        for issue in missing_from_factory:
            info = issues_project[issue]
            summary = ISSUE_SUMMARY if info['owner'] else ISSUE_SUMMARY_PLAIN
            changes[issue] = summary.format(label=issue,
                                            url=info['url'],
                                            owner=info['owner'],
                                            summary=info['summary'])

        # Prompt user to decide which issues to whitelist.
        changes_after = prompt_interactive(changes, args.project, package)

        # Determine if any real changes (vs typos) and create text issue list.
        issues = []
        cc = []
        if len(changes_after) > 0:
            for issue, summary in changes.items():
                if issue in changes_after:
                    info = issues_project[issue]
                    if issue.startswith('bsc'):
                        # Reformat for bugzilla markdown.
                        summary = ISSUE_SUMMARY_BUGZILLA if info[
                            'owner'] else ISSUE_SUMMARY_PLAIN_BUGZILLA
                        issue = issue.replace('bsc', 'bug')
                        summary = summary.format(label=issue,
                                                 url=info['url'],
                                                 owner=info['owner'],
                                                 summary=info['summary'])
                    issues.append('- ' + summary)
                    if info['owner'] is not None:
                        cc.append(info['owner'])

        # Prompt user about how to continue.
        response = prompt_continue(len(issues))
        if response == 'n':
            break
        if response == 's':
            continue

        # File a bug if not all issues whitelisted.
        if len(issues) > 0:
            summary = BUG_SUMMARY.format(project=args.project,
                                         factory=args.factory,
                                         package=package)
            message = BUG_TEMPLATE.format(message_start=MESSAGE_START.format(
                project=args.project,
                factory=args.factory,
                package=package,
                newest=args.newest),
                                          issues='\n'.join(issues))
            if len(message) > 65535:
                # Truncate messages longer than bugzilla limit.
                message = message[:65535 - 3] + '...'

            # Determine bugzilla meta information to use when creating bug.
            meta = bug_meta(bugzilla_api, bugzilla_defaults, trackers,
                            changes.keys())
            owner = bug_owner(apiurl, package)
            if args.bugzilla_cc:
                cc.append(args.bugzilla_cc)

            # Try to create bug, but allow for handling faults.
            tries = 0
            while tries < 10:
                try:
                    bug_id = bug_create(bugzilla_api, meta, owner, cc, summary,
                                        message)
                    break
                except Fault as e:
                    if 'There is no component named' in e.faultString:
                        print(
                            'Invalid component {}, fallback to default'.format(
                                meta[1]))
                        meta = (meta[0], bugzilla_defaults[1], meta[2])
                    elif 'is not a valid username' in e.faultString:
                        username = e.faultString.split(' ', 3)[2]
                        cc.remove(username)
                        print('Removed invalid username {}'.format(username))
                    else:
                        raise e
                tries += 1

        # Mark changes in db.
        notified, whitelisted = 0, 0
        for issue in changes:
            if package not in db:
                db[package] = {}

            if issue in changes_after:
                db[package][issue] = str(bug_id)
                notified += 1
            else:
                db[package][issue] = 'whitelist'
                whitelisted += 1

        # Write out changes after each package to avoid loss.
        with open(db_file, 'w') as outfile:
            yaml.safe_dump(db,
                           outfile,
                           default_flow_style=False,
                           default_style="'")

        if notified > 0:
            print('{}: {} notified in bug {}, {} whitelisted'.format(
                package, notified, bug_id, whitelisted))
        else:
            print('{}: {} whitelisted'.format(package, whitelisted))

        if response == 'b':
            break

        new += 1
        if new == args.limit:
            print('stopped at limit')
            break

    sync(args.cache_dir, git_repo_url, git_message)