Merge "Add ptl_nominations_last_day email template"

This commit is contained in:
Zuul 2019-02-20 02:40:33 +00:00 committed by Gerrit Code Review
commit 303b7d9f39
2 changed files with 66 additions and 42 deletions

View File

@ -69,6 +69,53 @@ def collect_project_stats(basedir, verbose, projects):
', '.join(candidates)))
def election_summary():
now = datetime.datetime.now(tz=pytz.utc)
now = now.replace(microsecond=0)
event = utils.get_event('PTL Nominations')
start, end = event['start'], event['end']
duration = (end - start)
remaining = (end - now)
progress = (duration - remaining)
p_progress = as_percentage(progress.total_seconds(),
duration.total_seconds())
p_candidate = as_percentage(counts['with_candidate'], counts['projects'])
p_nominations = as_percentage(counts['nominations'], counts['projects'])
need_election.sort()
without_candidate.sort()
output = ""
output += ("%-25s @ %s\n" % ("Nominations started", as_utctime(start)))
output += ("%-25s @ %s\n" % ("Nominations end", as_utctime(end)))
output += ("%-25s : %s\n" % ("Nominations duration", duration))
output += ("%-25s : %s\n" % ("Nominations remaining", remaining))
output += ("%-25s : %6.2f%%\n" % ("Nominations progress", p_progress))
output += ("-" * 51)
output += ("\n")
output += ("%-25s : %5d\n" % ("Projects[1]", counts['projects']))
output += ("%-25s : %5d (%6.2f%%)\n" % ("Projects with candidates",
counts['with_candidate'],
p_candidate))
output += ("%-25s : %5d (%6.2f%%)\n" % ("Projects with election",
counts['nominations'],
p_nominations))
output += ("-" * 51)
output += ("\n")
output += ("%-25s : %d (%s)\n" % ("Need election",
len(need_election),
" ".join(need_election)))
output += ("%-25s : %d (%s)\n" % ("Need appointment",
len(without_candidate),
" ".join(without_candidate)))
output += ("=" * 51)
output += ("\n")
output += ("%-25s @ %s\n" % ("Stats gathered", as_utctime(now)))
return output
def main():
parser = argparse.ArgumentParser(description='Investigate PTL Nominations')
parser.add_argument('-v', '--verbose', action="count", default=0,
@ -94,45 +141,9 @@ def main():
args.basedir = os.path.expanduser(args.basedir)
collect_project_stats(args.basedir, args.verbose, args.projects)
now = datetime.datetime.now(tz=pytz.utc)
now = now.replace(microsecond=0)
event = utils.get_event('PTL Nominations')
start, end = event['start'], event['end']
duration = (end - start)
remaining = (end - now)
progress = (duration - remaining)
p_progress = as_percentage(progress.total_seconds(),
duration.total_seconds())
p_candidate = as_percentage(counts['with_candidate'], counts['projects'])
p_nominations = as_percentage(counts['nominations'], counts['projects'])
need_election.sort()
without_candidate.sort()
if args.verbose:
print("-" * 51)
print("%-25s @ %s" % ("Nominations started", as_utctime(start)))
print("%-25s @ %s" % ("Nominations end", as_utctime(end)))
print("%-25s : %s" % ("Nominations duration", duration))
print("%-25s : %s" % ("Nominations remaining", remaining))
print("%-25s : %6.2f%%" % ("Nominations progress", p_progress))
print("-" * 51)
print("%-25s : %5d" % ("Projects[1]", counts['projects']))
print("%-25s : %5d (%6.2f%%)" % ("Projects with candidates",
counts['with_candidate'],
p_candidate))
print("%-25s : %5d (%6.2f%%)" % ("Projects with election",
counts['nominations'],
p_nominations))
print("-" * 51)
print("%-25s : %d (%s)" % ("Need election", len(need_election),
" ".join(need_election)))
print("%-25s : %d (%s)" % ("Need appointment", len(without_candidate),
" ".join(without_candidate)))
print("=" * 51)
print("%-25s @ %s" % ("Stats gathered", as_utctime(now)))
print(election_summary())
print("")
print("[1] These numbers include the following projects that have a "
"candidate that is approved my only a single election official:"

View File

@ -2,8 +2,10 @@ from __future__ import print_function
from __future__ import unicode_literals
import argparse
import os
import sys
from openstack_election.cmds import render_statistics as stats
from openstack_election import config
from openstack_election import utils
@ -35,6 +37,11 @@ if conf['election_type'] == 'tc':
release=conf['release'],
)
elif conf['election_type'] == 'ptl':
# NOTE(tonyb): We need an empty item last to ensure the path ends in a
# tailing '/'
stats.collect_project_stats(os.path.join(utils.CANDIDATE_PATH,
conf['release'], ''),
False, [])
ptl_fmt_args = dict(
nom_end_date=utils.get_event('PTL Nominations')['end_str'],
time_frame=time_frame,
@ -42,6 +49,9 @@ elif conf['election_type'] == 'ptl':
ending_release=end_release,
future_release=end_release.lower(),
email_deadline=conf['timeframe']['email_deadline'],
num_projects_without_candidates=len(stats.without_candidate),
election_summary_stats=stats.election_summary(),
leaderless_url=LEADERLESS_URL,
)
@ -114,7 +124,7 @@ Happy running,
print(email_text % (ptl_fmt_args))
def ptl_nominations_last_days(num_projects_without_candidates):
def ptl_nominations_last_days():
email_text = """
A quick reminder that we are in the last hours for PTL candidate
nominations.
@ -126,19 +136,21 @@ Make sure your nomination has been submitted to the openstack/election
repository and approved by election officials.
Election statistics[2]:
%(election_summary_stats)s
This means that with approximately 2 days left, %s projects will
This means that with approximately 2 days left, %(num_projects_without_candidates)s projects will
be deemed leaderless. In this case the TC will oversee PTL selection as
described by [3].
Thank you,
[1] http://governance.openstack.org/election/#how-to-submit-a-candidacy
[2] Assuming the open reviews below are validated
[2] Any open reviews at
https://review.openstack.org/#/q/is:open+project:openstack/election
[3] %s"""
have not been factored into these stats.
[3] %(leaderless_url)s""" # noqa
print(email_text % (num_projects_without_candidates, LEADERLESS_URL))
print(email_text % (ptl_fmt_args))
def ptl_end_nominations(projects_no_candidates,
@ -465,6 +477,7 @@ def main():
parser_ptl = cmd_parsers.add_parser('ptl')
parser_ptl.add_argument('template',
choices=['election_season', 'nominations_kickoff',
'nominations_last_days',
])
parser_tc = cmd_parsers.add_parser('tc')
parser_tc.add_argument('template',