Support custom local projects and legacy projects

Add --legacy and --projects options to the owners CLI, which make it
possible to specify local alternatives for the legacy.yaml and
projects.yaml files. This enables easily running the tool for
unofficial/non-OpenStack elections which use the same Gerrit and
similar rules for determining their electorates other than the
actual repository lists.

Change-Id: I45d6c4d4fd454ae426883006db1e58dbd373bbdf
This commit is contained in:
Jeremy Stanley 2019-01-19 14:33:04 +00:00
parent 549cc39319
commit bb84857d15
3 changed files with 38 additions and 12 deletions

View File

@ -110,9 +110,11 @@ def usage(argv=sys.argv):
parser.add_argument("-c", "--config", help="Path to script configuration") parser.add_argument("-c", "--config", help="Path to script configuration")
parser.add_argument("-i", "--ignore", help="Account Id numbers to skip", parser.add_argument("-i", "--ignore", help="Account Id numbers to skip",
action='append') action='append')
parser.add_argument("-l", "--legacy", help="Path to legacy projects file")
parser.add_argument("-n", "--no-extra-atcs", help='Omit "extra ATCs"', parser.add_argument("-n", "--no-extra-atcs", help='Omit "extra ATCs"',
dest='no_extra_atcs', action='store_true') dest='no_extra_atcs', action='store_true')
parser.add_argument("-o", "--outdir", help="Create an output directory") parser.add_argument("-o", "--outdir", help="Create an output directory")
parser.add_argument("-p", "--projects", help="Path to local projects file")
parser.add_argument("-r", "--ref", help="Specify a Governance refname") parser.add_argument("-r", "--ref", help="Specify a Governance refname")
parser.add_argument("-s", "--sieve", help="Add Gerrit query parameters") parser.add_argument("-s", "--sieve", help="Add Gerrit query parameters")

View File

@ -122,6 +122,14 @@ def main(options):
else: else:
ignore = [] ignore = []
# Legacy projects file path
if options.legacy:
legacy_file = options.legacy
elif 'legacy' in config:
legacy_file = config['legacy']
else:
legacy_file = None
# Whether to omit "extra ATCs" # Whether to omit "extra ATCs"
if options.no_extra_atcs: if options.no_extra_atcs:
no_extra_atcs = options.no_extra_atcs no_extra_atcs = options.no_extra_atcs
@ -140,6 +148,14 @@ def main(options):
if not os.path.isdir(outdir): if not os.path.isdir(outdir):
os.makedirs(outdir) os.makedirs(outdir)
# Projects file path
if options.projects:
projects_file = options.projects
elif 'projects' in config:
projects_file = config['projects']
else:
projects_file = None
# Governance Git repository ref object for reference lists # Governance Git repository ref object for reference lists
if options.ref: if options.ref:
ref = options.ref ref = options.ref
@ -165,9 +181,9 @@ def main(options):
# Retrieve the governance projects list, needs a Git refname as a # Retrieve the governance projects list, needs a Git refname as a
# parameter # parameter
# TODO(fungi): make this a configurable option so that you can if projects_file:
# for example supply a custom project list for running elections gov_projects = utils.load_yaml(open(projects_file).read())
# in unofficial teams else:
gov_projects = utils.get_from_cgit('openstack/governance', gov_projects = utils.get_from_cgit('openstack/governance',
'reference/projects.yaml', 'reference/projects.yaml',
{'h': ref}) {'h': ref})
@ -175,7 +191,9 @@ def main(options):
# The set of retired or removed "legacy" projects from governance # The set of retired or removed "legacy" projects from governance
# are merged into the main dict if their retired-on date falls # are merged into the main dict if their retired-on date falls
# later than the after parameter for the qualifying time period # later than the after parameter for the qualifying time period
# TODO(fungi): make this a configurable option if legacy_file:
old_projects = utils.load_yaml(open(legacy_file).read())
else:
old_projects = utils.get_from_cgit('openstack/governance', old_projects = utils.get_from_cgit('openstack/governance',
'reference/legacy.yaml', 'reference/legacy.yaml',
{'h': ref}) {'h': ref})

View File

@ -85,13 +85,19 @@ def query_gerrit(method, params={}):
return decode_json(raw) return decode_json(raw)
def load_yaml(yaml_stream):
"""Retrieve a file from the cgit interface"""
return yaml.safe_load(yaml_stream)
def get_from_cgit(project, obj, params={}): def get_from_cgit(project, obj, params={}):
"""Retrieve a file from the cgit interface""" """Retrieve a file from the cgit interface"""
url = 'http://git.openstack.org/cgit/' + project + '/plain/' + obj url = 'http://git.openstack.org/cgit/' + project + '/plain/' + obj
raw = requester(url, params=params, raw = requester(url, params=params,
headers={'Accept': 'application/json'}) headers={'Accept': 'application/json'})
return yaml.safe_load(raw.text) return load_yaml(raw.text)
def get_series_data(): def get_series_data():
@ -228,7 +234,7 @@ def _get_projects(tag=None):
os.stat(cache_file).st_size < 100 or os.stat(cache_file).st_size < 100 or
os.stat(cache_file).st_mtime + (7*24*3600) < time.time()): os.stat(cache_file).st_mtime + (7*24*3600) < time.time()):
print("[+] Updating %s" % (cache_file)) print("[+] Updating %s" % (cache_file))
data = yaml.safe_load(urlopen(url).read()) data = load_yaml(urlopen(url).read())
pickle.dump(data, open(cache_file, "wb"), protocol=2) pickle.dump(data, open(cache_file, "wb"), protocol=2)
return pickle.load(open(cache_file, "rb")) return pickle.load(open(cache_file, "rb"))