Merge "Add ptl_nominations_last_day email template"
This commit is contained in:
commit
303b7d9f39
@ -69,6 +69,53 @@ def collect_project_stats(basedir, verbose, projects):
|
|||||||
', '.join(candidates)))
|
', '.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():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='Investigate PTL Nominations')
|
parser = argparse.ArgumentParser(description='Investigate PTL Nominations')
|
||||||
parser.add_argument('-v', '--verbose', action="count", default=0,
|
parser.add_argument('-v', '--verbose', action="count", default=0,
|
||||||
@ -94,45 +141,9 @@ def main():
|
|||||||
args.basedir = os.path.expanduser(args.basedir)
|
args.basedir = os.path.expanduser(args.basedir)
|
||||||
collect_project_stats(args.basedir, args.verbose, args.projects)
|
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:
|
if args.verbose:
|
||||||
print("-" * 51)
|
print("-" * 51)
|
||||||
print("%-25s @ %s" % ("Nominations started", as_utctime(start)))
|
print(election_summary())
|
||||||
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("")
|
print("")
|
||||||
print("[1] These numbers include the following projects that have a "
|
print("[1] These numbers include the following projects that have a "
|
||||||
"candidate that is approved my only a single election official:"
|
"candidate that is approved my only a single election official:"
|
||||||
|
@ -2,8 +2,10 @@ from __future__ import print_function
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from openstack_election.cmds import render_statistics as stats
|
||||||
from openstack_election import config
|
from openstack_election import config
|
||||||
from openstack_election import utils
|
from openstack_election import utils
|
||||||
|
|
||||||
@ -35,6 +37,11 @@ if conf['election_type'] == 'tc':
|
|||||||
release=conf['release'],
|
release=conf['release'],
|
||||||
)
|
)
|
||||||
elif conf['election_type'] == 'ptl':
|
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(
|
ptl_fmt_args = dict(
|
||||||
nom_end_date=utils.get_event('PTL Nominations')['end_str'],
|
nom_end_date=utils.get_event('PTL Nominations')['end_str'],
|
||||||
time_frame=time_frame,
|
time_frame=time_frame,
|
||||||
@ -42,6 +49,9 @@ elif conf['election_type'] == 'ptl':
|
|||||||
ending_release=end_release,
|
ending_release=end_release,
|
||||||
future_release=end_release.lower(),
|
future_release=end_release.lower(),
|
||||||
email_deadline=conf['timeframe']['email_deadline'],
|
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))
|
print(email_text % (ptl_fmt_args))
|
||||||
|
|
||||||
|
|
||||||
def ptl_nominations_last_days(num_projects_without_candidates):
|
def ptl_nominations_last_days():
|
||||||
email_text = """
|
email_text = """
|
||||||
A quick reminder that we are in the last hours for PTL candidate
|
A quick reminder that we are in the last hours for PTL candidate
|
||||||
nominations.
|
nominations.
|
||||||
@ -126,19 +136,21 @@ Make sure your nomination has been submitted to the openstack/election
|
|||||||
repository and approved by election officials.
|
repository and approved by election officials.
|
||||||
|
|
||||||
Election statistics[2]:
|
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
|
be deemed leaderless. In this case the TC will oversee PTL selection as
|
||||||
described by [3].
|
described by [3].
|
||||||
|
|
||||||
Thank you,
|
Thank you,
|
||||||
|
|
||||||
[1] http://governance.openstack.org/election/#how-to-submit-a-candidacy
|
[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
|
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,
|
def ptl_end_nominations(projects_no_candidates,
|
||||||
@ -465,6 +477,7 @@ def main():
|
|||||||
parser_ptl = cmd_parsers.add_parser('ptl')
|
parser_ptl = cmd_parsers.add_parser('ptl')
|
||||||
parser_ptl.add_argument('template',
|
parser_ptl.add_argument('template',
|
||||||
choices=['election_season', 'nominations_kickoff',
|
choices=['election_season', 'nominations_kickoff',
|
||||||
|
'nominations_last_days',
|
||||||
])
|
])
|
||||||
parser_tc = cmd_parsers.add_parser('tc')
|
parser_tc = cmd_parsers.add_parser('tc')
|
||||||
parser_tc.add_argument('template',
|
parser_tc.add_argument('template',
|
||||||
|
Loading…
Reference in New Issue
Block a user