def main(): load_config() print "Calculating F11 0day update metrics..." updates = { 'bugfix': [], 'security': [], 'enhancement': [], 'newpackage': [] } date = datetime(*time.strptime('06-09-2009', '%m-%d-%Y')[:-2]) f11 = Release.byName('F11') for update in PackageUpdate.select(PackageUpdate.q.releaseID == f11.id): for comment in update.comments: if comment.author == 'bodhi' and comment.timestamp < date and \ comment.text.startswith('This update has been pushed to stable'): updates[update.type].append(update.title) break pprint(updates) print '=' * 80 print 'F11 0day stats' print ' * %d security' % len(updates['security']) print ' * %d bugfixes' % len(updates['bugfix']) print ' * %d enhancements' % len(updates['enhancement']) print ' * %d newpackage' % len(updates['newpackage'])
def main(): load_config() __connection__ = hub = PackageHub("bodhi") if len(sys.argv) != 2: print "Usage: %s <release>" % sys.argv[0] sys.exit(1) try: release = Release.byName(sys.argv[1].upper()) except SQLObjectNotFound: print "Cannot find Release '%s'" % sys.argv[1] sys.exit(1) updates = PackageUpdate.select(PackageUpdate.q.releaseID == release.id) progress = ProgressBar(maxValue=updates.count()) print "Destroying all updates, comments, and bugs associated with %s" % release.name for update in updates: for comment in update.comments: comment.destroySelf() for build in update.builds: build.destroySelf() for bug in update.bugs: if len(bug.updates) == 1: bug.destroySelf() update.destroySelf() progress() release.destroySelf() hub.commit() print
def main(): """ Initialize the package/release/multilib tables """ print "Initializing Bodhi\n" load_config() hub.begin() clean_tables() if releases: import_releases() import_rebootpkgs() hub.commit()
def main(): load_config() hub.begin() try: print "\nCreating guest user and giving it administrator priviliges" guest = User(user_name="guest", display_name="Bodhi Hacker", password="******") admin = Group(group_name="releng", display_name="Bodhi administrators") guest.addGroup(admin) hub.commit() except DuplicateEntryError: print "guest account already created"
def main(): load_config() hub.begin() try: print "\nCreating guest user and giving it administrator priviliges" guest = User(user_name='guest', display_name='Bodhi Hacker', password='******') admin = Group(group_name='releng', display_name='Bodhi administrators') guest.addGroup(admin) hub.commit() except DuplicateEntryError: print "guest account already created"
def main(): load_config() if len(sys.argv) < 2: usage() elif sys.argv[1] == "save": print "Pickling database..." save_db() elif sys.argv[1] == "load" and len(sys.argv) == 3: try: hub.begin() load_db() finally: hub.commit() else: usage()
def main(): load_config() if len(sys.argv) < 2: usage() elif sys.argv[1] == 'save': print "Pickling database..." save_db() elif sys.argv[1] == 'load' and len(sys.argv) == 3: try: hub.begin() load_db() finally: hub.commit() else: usage()
def start(): '''Start the CherryPy application server.''' if len(sys.argv) > 1: load_config(sys.argv[1]) else: load_config() from fedora.tg.util import enable_csrf if turbogears.config.get('identity.provider') in ('sqlobjectcsrf', 'jsonfas2'): turbogears.startup.call_on_startup.append(enable_csrf) ## Schedule our periodic tasks from bodhi import jobs turbogears.startup.call_on_startup.append(jobs.schedule) from bodhi.controllers import Root turbogears.start_server(Root())
def main(): load_config() print "Calculating F11 0day update metrics..." updates = {'bugfix': [], 'security': [], 'enhancement': [], 'newpackage': []} date = datetime(*time.strptime('06-09-2009', '%m-%d-%Y')[:-2]) f11 = Release.byName('F11') for update in PackageUpdate.select(PackageUpdate.q.releaseID==f11.id): for comment in update.comments: if comment.author == 'bodhi' and comment.timestamp < date and \ comment.text.startswith('This update has been pushed to stable'): updates[update.type].append(update.title) break pprint(updates) print '=' * 80 print 'F11 0day stats' print ' * %d security' % len(updates['security']) print ' * %d bugfixes' % len(updates['bugfix']) print ' * %d enhancements' % len(updates['enhancement']) print ' * %d newpackage' % len(updates['newpackage'])
def main(): load_config() __connection__ = hub = PackageHub("bodhi") koji = get_session() tasks = [] broke = set() # Clean up any stray pending tags for release in Release.select(): print "Finding all pending-testing builds..." if release.name.startswith('EL'): continue tag = release.pending_testing_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable', 'obsolete'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) tag = release.pending_stable_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('pending', 'obsolete', 'stable'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) # Check for testing updates that aren't tagged properly for update in PackageUpdate.select(PackageUpdate.q.status == 'testing'): dest_tag = update.release.testing_tag for build in update.builds: tags = [tag['name'] for tag in koji.listTags(build=build.nvr)] if dest_tag not in tags: print "%s marked as testing, but tagged with %s" % (build.nvr, tags) if '--fix' in sys.argv: broke.add((tags[0], dest_tag, build.nvr)) # Check all candidate updates to see if they are in a different bodhi state for release in Release.select(): tag = release.candidate_tag tagged = [build['nvr'] for build in koji.listTagged(tag, latest=True)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable'): print "%s %s but tagged as %s" % (nvr, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag broke.add((tag, dest, nvr)) except SQLObjectNotFound: pass # Make sure that all builds in koji tagged as an update exist # in bodhi, and are in the expect state. for release in Release.select(): for tag in (release.testing_tag, release.stable_tag): tagged = [ build['nvr'] for build in koji.listTagged(tag, latest=True) ] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: print "PackageUpdate(%s) not found!" % nvr continue if not len(build.updates): print "PackageBuild(%s) has no updates" % (build.nvr) status = 'testing' in tag and 'testing' or 'stable' for update in build.updates: if update.status != status: print "%s is %s in bodhi but tagged as %s in koji" % ( update.title, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag for b in update.builds: broke.add((tag, dest, b.nvr)) if broke: print " ** Fixing broken tags! **" koji.multicall = True for tag, dest, build in broke: print "Moving %s from %s to %s" % (build, tag, dest) koji.moveBuild(tag, dest, build, force=True) print "Running koji.multiCall()" results = koji.multiCall() success = False print "Waiting for tasks" bad_tasks = wait_for_tasks([task[0] for task in results]) if bad_tasks == 0: success = True if success: print "Tags successfully moved!" else: print "Error moving tags!" print "bad_tasks = %r" % bad_tasks
def main(): load_config() stats = {} # {release: {'stat': ...}} feedback = 0 # total number of updates that received feedback karma = defaultdict(int) # {username: # of karma submissions} num_updates = PackageUpdate.select().count() proventesters = set() for release in Release.select(): print header(release.long_name) updates = PackageUpdate.select(PackageUpdate.q.releaseID==release.id) stats[release.name] = { 'num_updates': updates.count(), 'num_tested': 0, 'num_tested_without_karma': 0, 'num_feedback': 0, 'num_anon_feedback': 0, 'num_critpath': 0, 'num_critpath_approved': 0, 'num_critpath_unapproved': 0, 'num_stablekarma': 0, 'num_testingtime': 0, 'critpath_without_karma': set(), 'conflicted_proventesters': [], 'critpath_positive_karma_including_proventesters': [], 'critpath_positive_karma_negative_proventesters': [], 'stable_with_negative_karma': PackageUpdate.select( AND(PackageUpdate.q.releaseID==release.id, PackageUpdate.q.status=='stable', PackageUpdate.q.karma < 0)).count(), 'bugs': set(), 'karma': defaultdict(int), 'deltas': [], 'occurrences': {}, 'accumulative': timedelta(), 'packages': defaultdict(int), 'proventesters': set(), 'proventesters_1': 0, 'proventesters_0': 0, 'proventesters_-1': 0, # for tracking number of types of karma '1': 0, '0': 0, '-1': 0, } data = stats[release.name] for status in statuses: data['num_%s' % status] = PackageUpdate.select(AND( PackageUpdate.q.releaseID==release.id, PackageUpdate.q.status==status)).count() for type in types: data['num_%s' % type] = PackageUpdate.select(AND( PackageUpdate.q.releaseID==release.id, PackageUpdate.q.type==type)).count() for update in release.updates: for build in update.builds: data['packages'][build.package] += 1 for bug in update.bugs: data['bugs'].add(bug.bz_id) feedback_done = False testingtime_done = False for comment in update.comments: if comment.author_name in ('autoqa', 'taskotron'): continue # Track the # of +1's, -1's, and +0's. if comment.author_name != 'bodhi': data[str(comment.karma)] += 1 if comment.author_group == 'proventesters': data['proventesters'].add(comment.author_name) data['proventesters_%d' % comment.karma] += 1 if comment.text == 'This update has reached the stable karma threshold and will be pushed to the stable updates repository': data['num_stablekarma'] += 1 elif comment.text and comment.text.endswith('days in testing and can be pushed to stable now if the maintainer wishes'): data['num_testingtime'] += 1 # For figuring out if an update has received feedback or not if not feedback_done: if (not comment.author.startswith('bodhi') and comment.karma != 0 and not comment.anonymous): data['num_feedback'] += 1 # per-release tracking of feedback feedback += 1 # total number of updates that have received feedback feedback_done = True # so we don't run this for each comment # Tracking per-author karma & anonymous feedback if not comment.author.startswith('bodhi'): if comment.anonymous: # @@: should we track anon +0 comments as "feedback"? if comment.karma != 0: data['num_anon_feedback'] += 1 else: author = comment.author_name data['karma'][author] += 1 karma[author] += 1 if (not testingtime_done and comment.text == 'This update has been pushed to testing'): for othercomment in update.comments: if othercomment.text == 'This update has been pushed to stable': delta = othercomment.timestamp - comment.timestamp data['deltas'].append(delta) data['occurrences'][delta.days] = \ data['occurrences'].setdefault( delta.days, 0) + 1 data['accumulative'] += delta testingtime_done = True break if update.critpath: if update.critpath_approved or update.status == 'stable': data['num_critpath_approved'] += 1 else: if status in ('testing', 'pending'): data['num_critpath_unapproved'] += 1 data['num_critpath'] += 1 #if not feedback_done: if update.status == 'stable' and update.karma == 0: data['critpath_without_karma'].add(update) # Proventester metrics proventester_karma = defaultdict(int) # {username: karma} positive_proventesters = 0 negative_proventesters = 0 for comment in update.comments: if comment.author_group == 'proventesters': proventester_karma[comment.author_name] += comment.karma for _karma in proventester_karma.values(): if _karma > 0: positive_proventesters += 1 elif _karma < 0: negative_proventesters += 1 # Conflicting proventesters if positive_proventesters and negative_proventesters: data['conflicted_proventesters'] += [short_url(update)] # Track updates with overall positive karma, including positive # karma from a proventester if update.karma > 0 and positive_proventesters: data['critpath_positive_karma_including_proventesters'] += [short_url(update)] # Track updates with overall positive karma, including negative # karma from a proventester if update.karma > 0 and negative_proventesters: data['critpath_positive_karma_negative_proventesters'] += [short_url(update)] if testingtime_done: data['num_tested'] += 1 if not feedback_done: data['num_tested_without_karma'] += 1 data['deltas'].sort() print " * %d updates" % data['num_updates'] print " * %d packages updated" % (len(data['packages'])) for status in statuses: print " * %d %s updates" % (data['num_%s' % status], status) for type in types: print " * %d %s updates (%0.2f%%)" % (data['num_%s' % type], type, float(data['num_%s' % type]) / data['num_updates'] * 100) print " * %d bugs resolved" % len(data['bugs']) print " * %d critical path updates (%0.2f%%)" % (data['num_critpath'], float(data['num_critpath']) / data['num_updates'] * 100) print " * %d approved critical path updates" % ( data['num_critpath_approved']) print " * %d unapproved critical path updates" % ( data['num_critpath_unapproved']) print " * %d updates received feedback (%0.2f%%)" % ( data['num_feedback'], (float(data['num_feedback']) / data['num_updates'] * 100)) print " * %d +0 comments" % data['0'] print " * %d +1 comments" % data['1'] print " * %d -1 comments" % data['-1'] print " * %d unique authenticated karma submitters" % ( len(data['karma'])) print " * %d proventesters" % len(data['proventesters']) print " * %d +1's from proventesters" % data['proventesters_1'] print " * %d -1's from proventesters" % data['proventesters_-1'] if data['num_critpath']: print " * %d critpath updates with conflicting proventesters (%0.2f%% of critpath)" % (len(data['conflicted_proventesters']), float(len(data['conflicted_proventesters'])) / data['num_critpath'] * 100) for u in data['conflicted_proventesters']: print " * " + u print " * %d critpath updates with positive karma and negative proventester feedback (%0.2f%% of critpath)" % (len(data['critpath_positive_karma_negative_proventesters']), float(len(data['critpath_positive_karma_negative_proventesters'])) / data['num_critpath'] * 100) for u in data['critpath_positive_karma_negative_proventesters']: print " * " + u print " * %d critpath updates with positive karma and positive proventester feedback (%0.2f%% of critpath)" % (len(data['critpath_positive_karma_including_proventesters']), float(len(data['critpath_positive_karma_including_proventesters'])) / data['num_critpath'] * 100) print " * %d anonymous users gave feedback (%0.2f%%)" % ( data['num_anon_feedback'], float(data['num_anon_feedback']) / (data['num_anon_feedback'] + sum(data['karma'].values())) * 100) # This does not take into account updates that reach stablekarma before being pushed to testing! # print " * %d out of %d stable updates went through testing (%0.2f%%)" %( # data['num_tested'], data['num_stable'], # float(data['num_tested']) / data['num_stable'] * 100) print " * %d updates reached the stable karma threshold (%0.2f%%)" % ( data['num_stablekarma'], float(data['num_stablekarma']) / data['num_stable'] * 100) print " * %d updates reached the minimum time in testing threshold (%0.2f%%)" % ( data['num_testingtime'], float(data['num_testingtime']) / data['num_stable'] * 100) print " * %d went from testing to stable *without* karma (%0.2f%%)" % ( data['num_tested_without_karma'], float(data['num_tested_without_karma']) / data['num_tested'] * 100) print " * %d updates were pushed to stable with negative karma (%0.2f%%)" % ( data['stable_with_negative_karma'], float(data['stable_with_negative_karma']) / data['num_stable'] * 100) print " * %d critical path updates pushed to stable *without* karma" % ( len(data['critpath_without_karma'])) #for update in data['critpath_without_karma']: # print " * %s submitted by %s" % (update.title, update.submitter) print " * Time spent in testing:" print " * mean = %d days" % (data['accumulative'].days / len(data['deltas'])) print " * median = %d days" % ( data['deltas'][len(data['deltas']) / 2].days) print " * mode = %d days" % ( sorted(data['occurrences'].items(), key=itemgetter(1))[-1][0]) #for package in sorted(data['packages'].items(), key=itemgetter(1), reverse=True): # print " * %s: %d" % (package[0].name, package[1]) print print print "Out of %d total updates, %d received feedback (%0.2f%%)" % ( num_updates, feedback, (float(feedback) / num_updates * 100)) print "Out of %d total unique commenters, the top 50 are:" % ( len(karma)) for submitter in sorted(karma.iteritems(), key=itemgetter(1), reverse=True)[:50]: print " * %s (%d)" % (submitter[0], submitter[1])
num_updates = PackageUpdate.select( PackageUpdate.q.releaseID==release.id).count() num_stable = len(stable_updates[release.name]) num_unstable = len(unstable_updates[release.name]) num_testing = len(unstable_deltas) + len(stable_deltas) print " * %d updates automatically unpushed due to karma (%0.2f%%)" % ( num_unstable, float(num_unstable) / num_updates * 100) print " * %d of which were critical path updates" % ( unstable_critpath[release.name]) print " * %d updates automatically pushed due to karma (%0.2f%%)" % ( num_stable, float(num_stable) / num_updates * 100) print " * %d of which were critical path updates" % ( stable_critpath[release.name]) print " * Time spent in testing of updates that were pushed by karma:" print " * mean = %d days" % (stable_accum.days / len(stable_deltas)) print " * median = %d days" % stable_deltas[len(stable_deltas)/2].days print " * mode = %d days" % sorted(stable_occur.items(), key=itemgetter(1))[-1][0] print " * Time spent in testing of updates that were unpushed by karma:" print " * mean = %d days" % (unstable_accum.days / len(unstable_deltas)) print " * median = %d days" % unstable_deltas[len(unstable_deltas)/2].days print " * mode = %d days" % sorted(unstable_occur.items(), key=itemgetter(1))[-1][0] if __name__ == '__main__': load_config() main()
PackageUpdate.q.status == 'testing', PackageUpdate.q.request == None)): for build in update.builds: if build.nvr not in testing_nvrs: latest_testing = None latest_stable = None for testing in testing_nvrs: if testing.startswith(build.package.name + '-'): latest_testing = testing break for stable in stable_nvrs: if stable.startswith(build.package.name + '-'): latest_stable = stable break if latest_testing: koji_build = koji.getBuild(build.nvr) latest_build = koji.getBuild(latest_testing) if rpm.labelCompare(build_evr(koji_build), build_evr(latest_build)) < 0: print "%s in testing, latest_testing = %s, latest_stable = %s" % ( update.title, latest_testing, latest_stable) if untag: print "Obsoleting %s" % update.title update.obsolete(newer=latest_testing) if __name__ == '__main__': load_config() turbomail.start_extension() clean_testing_builds('--untag' in sys.argv)
def main(): load_config() stats = {} # {release: {'stat': ...}} feedback = 0 # total number of updates that received feedback karma = defaultdict(int) # {username: # of karma submissions} num_updates = PackageUpdate.select().count() proventesters = set() for release in Release.select(): print header(release.long_name) updates = PackageUpdate.select(PackageUpdate.q.releaseID == release.id) stats[release.name] = { 'num_updates': updates.count(), 'num_tested': 0, 'num_tested_without_karma': 0, 'num_feedback': 0, 'num_anon_feedback': 0, 'num_critpath': 0, 'num_critpath_approved': 0, 'num_critpath_unapproved': 0, 'num_stablekarma': 0, 'num_testingtime': 0, 'critpath_without_karma': set(), 'conflicted_proventesters': [], 'critpath_positive_karma_including_proventesters': [], 'critpath_positive_karma_negative_proventesters': [], 'stable_with_negative_karma': PackageUpdate.select( AND(PackageUpdate.q.releaseID == release.id, PackageUpdate.q.status == 'stable', PackageUpdate.q.karma < 0)).count(), 'bugs': set(), 'karma': defaultdict(int), 'deltas': [], 'occurrences': {}, 'accumulative': timedelta(), 'packages': defaultdict(int), 'proventesters': set(), 'proventesters_1': 0, 'proventesters_0': 0, 'proventesters_-1': 0, # for tracking number of types of karma '1': 0, '0': 0, '-1': 0, } data = stats[release.name] for status in statuses: data['num_%s' % status] = PackageUpdate.select( AND(PackageUpdate.q.releaseID == release.id, PackageUpdate.q.status == status)).count() for type in types: data['num_%s' % type] = PackageUpdate.select( AND(PackageUpdate.q.releaseID == release.id, PackageUpdate.q.type == type)).count() for update in release.updates: for build in update.builds: data['packages'][build.package] += 1 for bug in update.bugs: data['bugs'].add(bug.bz_id) feedback_done = False testingtime_done = False for comment in update.comments: if comment.author_name in ('autoqa', 'taskotron'): continue # Track the # of +1's, -1's, and +0's. if comment.author_name != 'bodhi': data[str(comment.karma)] += 1 if comment.author_group == 'proventesters': data['proventesters'].add(comment.author_name) data['proventesters_%d' % comment.karma] += 1 if comment.text == 'This update has reached the stable karma threshold and will be pushed to the stable updates repository': data['num_stablekarma'] += 1 elif comment.text and comment.text.endswith( 'days in testing and can be pushed to stable now if the maintainer wishes' ): data['num_testingtime'] += 1 # For figuring out if an update has received feedback or not if not feedback_done: if (not comment.author.startswith('bodhi') and comment.karma != 0 and not comment.anonymous): data[ 'num_feedback'] += 1 # per-release tracking of feedback feedback += 1 # total number of updates that have received feedback feedback_done = True # so we don't run this for each comment # Tracking per-author karma & anonymous feedback if not comment.author.startswith('bodhi'): if comment.anonymous: # @@: should we track anon +0 comments as "feedback"? if comment.karma != 0: data['num_anon_feedback'] += 1 else: author = comment.author_name data['karma'][author] += 1 karma[author] += 1 if (not testingtime_done and comment.text == 'This update has been pushed to testing'): for othercomment in update.comments: if othercomment.text == 'This update has been pushed to stable': delta = othercomment.timestamp - comment.timestamp data['deltas'].append(delta) data['occurrences'][delta.days] = \ data['occurrences'].setdefault( delta.days, 0) + 1 data['accumulative'] += delta testingtime_done = True break if update.critpath: if update.critpath_approved or update.status == 'stable': data['num_critpath_approved'] += 1 else: if status in ('testing', 'pending'): data['num_critpath_unapproved'] += 1 data['num_critpath'] += 1 #if not feedback_done: if update.status == 'stable' and update.karma == 0: data['critpath_without_karma'].add(update) # Proventester metrics proventester_karma = defaultdict(int) # {username: karma} positive_proventesters = 0 negative_proventesters = 0 for comment in update.comments: if comment.author_group == 'proventesters': proventester_karma[ comment.author_name] += comment.karma for _karma in proventester_karma.values(): if _karma > 0: positive_proventesters += 1 elif _karma < 0: negative_proventesters += 1 # Conflicting proventesters if positive_proventesters and negative_proventesters: data['conflicted_proventesters'] += [short_url(update)] # Track updates with overall positive karma, including positive # karma from a proventester if update.karma > 0 and positive_proventesters: data[ 'critpath_positive_karma_including_proventesters'] += [ short_url(update) ] # Track updates with overall positive karma, including negative # karma from a proventester if update.karma > 0 and negative_proventesters: data['critpath_positive_karma_negative_proventesters'] += [ short_url(update) ] if testingtime_done: data['num_tested'] += 1 if not feedback_done: data['num_tested_without_karma'] += 1 data['deltas'].sort() print " * %d updates" % data['num_updates'] print " * %d packages updated" % (len(data['packages'])) for status in statuses: print " * %d %s updates" % (data['num_%s' % status], status) for type in types: print " * %d %s updates (%0.2f%%)" % ( data['num_%s' % type], type, float(data['num_%s' % type]) / data['num_updates'] * 100) print " * %d bugs resolved" % len(data['bugs']) print " * %d critical path updates (%0.2f%%)" % ( data['num_critpath'], float(data['num_critpath']) / data['num_updates'] * 100) print " * %d approved critical path updates" % ( data['num_critpath_approved']) print " * %d unapproved critical path updates" % ( data['num_critpath_unapproved']) print " * %d updates received feedback (%0.2f%%)" % ( data['num_feedback'], (float(data['num_feedback']) / data['num_updates'] * 100)) print " * %d +0 comments" % data['0'] print " * %d +1 comments" % data['1'] print " * %d -1 comments" % data['-1'] print " * %d unique authenticated karma submitters" % (len( data['karma'])) print " * %d proventesters" % len(data['proventesters']) print " * %d +1's from proventesters" % data['proventesters_1'] print " * %d -1's from proventesters" % data['proventesters_-1'] if data['num_critpath']: print " * %d critpath updates with conflicting proventesters (%0.2f%% of critpath)" % ( len(data['conflicted_proventesters']), float(len(data['conflicted_proventesters'])) / data['num_critpath'] * 100) for u in data['conflicted_proventesters']: print " * " + u print " * %d critpath updates with positive karma and negative proventester feedback (%0.2f%% of critpath)" % ( len(data['critpath_positive_karma_negative_proventesters']), float( len(data['critpath_positive_karma_negative_proventesters']) ) / data['num_critpath'] * 100) for u in data['critpath_positive_karma_negative_proventesters']: print " * " + u print " * %d critpath updates with positive karma and positive proventester feedback (%0.2f%% of critpath)" % ( len(data['critpath_positive_karma_including_proventesters']), float( len(data['critpath_positive_karma_including_proventesters'] )) / data['num_critpath'] * 100) print " * %d anonymous users gave feedback (%0.2f%%)" % ( data['num_anon_feedback'], float(data['num_anon_feedback']) / (data['num_anon_feedback'] + sum(data['karma'].values())) * 100) # This does not take into account updates that reach stablekarma before being pushed to testing! # print " * %d out of %d stable updates went through testing (%0.2f%%)" %( # data['num_tested'], data['num_stable'], # float(data['num_tested']) / data['num_stable'] * 100) print " * %d updates reached the stable karma threshold (%0.2f%%)" % ( data['num_stablekarma'], float(data['num_stablekarma']) / data['num_stable'] * 100) print " * %d updates reached the minimum time in testing threshold (%0.2f%%)" % ( data['num_testingtime'], float(data['num_testingtime']) / data['num_stable'] * 100) print " * %d went from testing to stable *without* karma (%0.2f%%)" % ( data['num_tested_without_karma'], float(data['num_tested_without_karma']) / data['num_tested'] * 100) print " * %d updates were pushed to stable with negative karma (%0.2f%%)" % ( data['stable_with_negative_karma'], float(data['stable_with_negative_karma']) / data['num_stable'] * 100) print " * %d critical path updates pushed to stable *without* karma" % ( len(data['critpath_without_karma'])) #for update in data['critpath_without_karma']: # print " * %s submitted by %s" % (update.title, update.submitter) print " * Time spent in testing:" print " * mean = %d days" % (data['accumulative'].days / len(data['deltas'])) print " * median = %d days" % (data['deltas'][len(data['deltas']) / 2].days) print " * mode = %d days" % (sorted(data['occurrences'].items(), key=itemgetter(1))[-1][0]) #for package in sorted(data['packages'].items(), key=itemgetter(1), reverse=True): # print " * %s: %d" % (package[0].name, package[1]) print print print "Out of %d total updates, %d received feedback (%0.2f%%)" % ( num_updates, feedback, (float(feedback) / num_updates * 100)) print "Out of %d total unique commenters, the top 50 are:" % (len(karma)) for submitter in sorted(karma.iteritems(), key=itemgetter(1), reverse=True)[:50]: print " * %s (%d)" % (submitter[0], submitter[1])
def main(): load_config() __connection__ = hub = PackageHub("bodhi") koji = get_session() tasks = [] broke = set() # Clean up any stray pending tags for release in Release.select(): print "Finding all pending-testing builds..." if release.name.startswith('EL'): continue tag = release.pending_testing_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable', 'obsolete'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) tag = release.pending_stable_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('pending', 'obsolete'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) # Check for testing updates that aren't tagged properly for update in PackageUpdate.select(PackageUpdate.q.status=='testing'): dest_tag = update.release.testing_tag for build in update.builds: tags = [tag['name'] for tag in koji.listTags(build=build.nvr)] if dest_tag not in tags: print "%s marked as testing, but tagged with %s" % (build.nvr, tags) if '--fix' in sys.argv: broke.add((tags[0], dest_tag, build.nvr)) # Check all candidate updates to see if they are in a different bodhi state for release in Release.select(): tag = release.candidate_tag tagged = [build['nvr'] for build in koji.listTagged(tag, latest=True)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable'): print "%s %s but tagged as %s" % (nvr, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag broke.add((tag, dest, nvr)) except SQLObjectNotFound: pass # Make sure that all builds in koji tagged as an update exist # in bodhi, and are in the expect state. for release in Release.select(): for tag in (release.testing_tag, release.stable_tag): tagged = [build['nvr'] for build in koji.listTagged(tag, latest=True)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: print "PackageUpdate(%s) not found!" % nvr continue if not len(build.updates): print "PackageBuild(%s) has no updates" % (build.nvr) status = 'testing' in tag and 'testing' or 'stable' for update in build.updates: if update.status != status: print "%s is %s in bodhi but tagged as %s in koji" % ( update.title, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag for b in update.builds: broke.add((tag, dest, b.nvr)) if broke: print " ** Fixing broken tags! **" koji.multicall = True for tag, dest, build in broke: print "Moving %s from %s to %s" % (build, tag, dest) koji.moveBuild(tag, dest, build, force=True) print "Running koji.multiCall()" results = koji.multiCall() success = False print "Waiting for tasks" bad_tasks = wait_for_tasks([task[0] for task in results]) if bad_tasks == 0: success = True if success: print "Tags successfully moved!" else: print "Error moving tags!" print "bad_tasks = %r" % bad_tasks
def main(): load_config() hub.begin() print "Finding updates with duplicate IDs..." if os.path.exists('dupes.pickle'): out = file('dupes.pickle') dupes = cPickle.load(out) out.close() highest_fedora = int(file('highest_fedora').read()) highest_epel = int(file('highest_epel').read()) else: dupes = set() highest_fedora = 0 highest_epel = 0 for update in PackageUpdate.select(PackageUpdate.q.updateid != None): if '-2010-' in update.updateid: if update.release.id_prefix == 'FEDORA': if update.updateid_int > highest_fedora: highest_fedora = update.updateid_int else: if update.updateid_int > highest_epel: highest_epel = update.updateid_int updates = PackageUpdate.select( AND(PackageUpdate.q.updateid == update.updateid, PackageUpdate.q.title != update.title)) if updates.count(): # Maybe TODO?: ensure these dupes have a date_pushed less tahn update?! # this way, the new ID is based on the oldest update for u in updates: dupes.add(u.title) out = file('dupes.pickle', 'w') cPickle.dump(dupes, out) out.close() print "Wrote dupes.pickle" file('highest_fedora', 'w').write(str(highest_fedora)) file('highest_epel', 'w').write(str(highest_epel)) # verify what we really found the highest IDs assert PackageUpdate.select(PackageUpdate.q.updateid == 'FEDORA-2010-%d' % (highest_fedora + 1)).count() == 0 assert PackageUpdate.select( PackageUpdate.q.updateid == 'FEDORA-EPEL-2010-%d' % (highest_epel + 1)).count() == 0 # Should be 740? print "%d dupes" % len(dupes) print "Highest FEDORA ID:", highest_fedora print "Highest FEDORA-EPEL ID:", highest_epel # Reassign the update IDs on all of our dupes for dupe in dupes: up = PackageUpdate.byTitle(dupe) #print "%s *was* %s" % (up.title, up.updateid) up.updateid = None # TODO: save & restore this value after new id assignment?! #up.date_pushed = None # Tweak the date_pushed to on the updates with the highest IDs PackageUpdate.select(PackageUpdate.q.updateid == 'FEDORA-2010-%d' % highest_fedora).date_pushed = datetime.now() PackageUpdate.select(PackageUpdate.q.updateid == 'FEDORA-EPEL-2010-%d' % highest_epel).date_pushed = datetime.now() #hub.commit() for dupe in dupes: up = PackageUpdate.byTitle(dupe) up.assign_id() ups = PackageUpdate.select(PackageUpdate.q.updateid == up.updateid) if ups.count() == 1: print "Still a dupe!!" for update in ups: if update.title == up.title: continue else: if update.title in dupes: print "%s in dupes, yet shares an updateid %s" % ( update.title, update.updateid) else: print "%s is not in dupes, but dupes %s" % ( update.title, updateid) print "Checking to ensure we have no more dupes..." dupes = set() for update in PackageUpdate.select(PackageUpdate.q.updateid != None): updates = PackageUpdate.select( AND(PackageUpdate.q.updateid == update.updateid, PackageUpdate.q.title != update.title)) if updates.count(): dupes.add(update.title) print "%d dupes (should be 0)" % len(dupes)
def main(): load_config() hub.begin() print "Finding updates with duplicate IDs..." if os.path.exists('dupes.pickle'): out = file('dupes.pickle') dupes = cPickle.load(out) out.close() highest_fedora = int(file('highest_fedora').read()) highest_epel = int(file('highest_epel').read()) else: dupes = set() highest_fedora = 0 highest_epel = 0 for update in PackageUpdate.select(PackageUpdate.q.updateid!=None): if '-2010-' in update.updateid: if update.release.id_prefix == 'FEDORA': if update.updateid_int > highest_fedora: highest_fedora = update.updateid_int else: if update.updateid_int > highest_epel: highest_epel = update.updateid_int updates = PackageUpdate.select( AND(PackageUpdate.q.updateid == update.updateid, PackageUpdate.q.title != update.title)) if updates.count(): # Maybe TODO?: ensure these dupes have a date_pushed less tahn update?! # this way, the new ID is based on the oldest update for u in updates: dupes.add(u.title) out = file('dupes.pickle', 'w') cPickle.dump(dupes, out) out.close() print "Wrote dupes.pickle" file('highest_fedora', 'w').write(str(highest_fedora)) file('highest_epel', 'w').write(str(highest_epel)) # verify what we really found the highest IDs assert PackageUpdate.select(PackageUpdate.q.updateid=='FEDORA-2010-%d' % (highest_fedora + 1)).count() == 0 assert PackageUpdate.select(PackageUpdate.q.updateid=='FEDORA-EPEL-2010-%d' % (highest_epel + 1)).count() == 0 # Should be 740? print "%d dupes" % len(dupes) print "Highest FEDORA ID:", highest_fedora print "Highest FEDORA-EPEL ID:", highest_epel # Reassign the update IDs on all of our dupes for dupe in dupes: up = PackageUpdate.byTitle(dupe) #print "%s *was* %s" % (up.title, up.updateid) up.updateid = None # TODO: save & restore this value after new id assignment?! #up.date_pushed = None # Tweak the date_pushed to on the updates with the highest IDs PackageUpdate.select(PackageUpdate.q.updateid=='FEDORA-2010-%d' % highest_fedora).date_pushed = datetime.now() PackageUpdate.select(PackageUpdate.q.updateid=='FEDORA-EPEL-2010-%d' % highest_epel).date_pushed = datetime.now() #hub.commit() for dupe in dupes: up = PackageUpdate.byTitle(dupe) up.assign_id() ups = PackageUpdate.select(PackageUpdate.q.updateid == up.updateid) if ups.count() == 1: print "Still a dupe!!" for update in ups: if update.title == up.title: continue else: if update.title in dupes: print "%s in dupes, yet shares an updateid %s" % ( update.title, update.updateid) else: print "%s is not in dupes, but dupes %s" % ( update.title, updateid) print "Checking to ensure we have no more dupes..." dupes = set() for update in PackageUpdate.select(PackageUpdate.q.updateid != None): updates = PackageUpdate.select( AND(PackageUpdate.q.updateid == update.updateid, PackageUpdate.q.title != update.title)) if updates.count(): dupes.add(update.title) print "%d dupes (should be 0)" % len(dupes)