summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorAlexandru Fazakas <alexandru.fazakas@codethink.co.uk>2019-07-26 16:28:08 +0100
committerTristan Maat <tristan.maat@codethink.co.uk>2019-07-31 17:51:09 +0100
commit1388d72ac76c2de326d064290b383314db1454e8 (patch)
tree72b7a08f25c9074d1dec5e1108bb6bc6c80c7e77 /contrib
parentdcc1ffcec4991fe18b83a5bdf4d08dcc161bcbd6 (diff)
downloadbuildstream-1388d72ac76c2de326d064290b383314db1454e8.tar.gz
contrib: Update COMMITTERS automatically
Since we want the COMMITTERS list to be sync'd with the GitLab permissions, use a script for fetching all the information and building a table with it automatically. The script uses a template located in the contrib/ directory. Closes https://gitlab.com/BuildStream/buildstream/issues/1071
Diffstat (limited to 'contrib')
-rw-r--r--contrib/COMMITTERS.rst.j218
-rwxr-xr-xcontrib/update_committers.py111
2 files changed, 129 insertions, 0 deletions
diff --git a/contrib/COMMITTERS.rst.j2 b/contrib/COMMITTERS.rst.j2
new file mode 100644
index 000000000..6f602d6c3
--- /dev/null
+++ b/contrib/COMMITTERS.rst.j2
@@ -0,0 +1,18 @@
+.. _committers:
+
+Committers
+==========
+
+Full commit access
+-------------------
+List of people with full commit access, i.e. blanket commit access to
+the BuildStream codebase. Note that this is not a full list of all
+contributors.
+
++-----------------------------------+-----------------------------------+
+| Full Name | GitLab User |
++===================================+===================================+
+{% for name, username in committers.items() -%}
+| {{ get_table_entry(name) }}| {{ get_table_entry(username)}}|
++-----------------------------------+-----------------------------------+
+{% endfor %}
diff --git a/contrib/update_committers.py b/contrib/update_committers.py
new file mode 100755
index 000000000..f0faac327
--- /dev/null
+++ b/contrib/update_committers.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+"""A script to set up COMMITTERS.rst according to gitlab committers."""
+
+import os
+import subprocess
+import argparse
+import json
+import urllib.request
+import urllib.parse
+from jinja2 import Environment, FileSystemLoader
+from collections import OrderedDict
+
+GIT_ERROR = 1
+MERGE_REQUEST = 'https://gitlab.com/api/v4/projects/1975139/merge_requests'
+ALL_MEMBERS = 'https://gitlab.com/api/v4/projects/1975139/members/all'
+PROTECTED = 'https://gitlab.com/api/v4/projects/1975139/protected_branches/master'
+USERS = 'https://gitlab.com/api/v4/users/{}'
+MAX_LEN = len('Full Name ')
+
+
+def get_committers(token: str) -> OrderedDict:
+ request = urllib.request.Request(PROTECTED)
+ request.add_header('PRIVATE-TOKEN', token)
+ response = urllib.request.urlopen(request).read().decode('utf-8')
+ named_developers = [x['user_id'] for x in json.loads(response)['merge_access_levels']]
+ request = urllib.request.Request(ALL_MEMBERS)
+ request.add_header('PRIVATE-TOKEN', token)
+ all_members = json.loads(urllib.request.urlopen(request).read().decode('utf-8'))
+ names_usernames_dictionary = OrderedDict()
+ for contributor in all_members:
+ if contributor['access_level'] >= 40:
+ names_usernames_dictionary[contributor['name']] = contributor['username']
+ for contributor in named_developers:
+ if contributor:
+ request = urllib.request.Request(USERS.format(contributor))
+ response = json.loads(urllib.request.urlopen(request).read().decode('utf-8'))
+ if response['name'] != 'bst-marge-bot':
+ names_usernames_dictionary[response['name']] = response['username']
+ return names_usernames_dictionary
+
+
+def get_table_entry(entry: str) -> str:
+ res = entry
+ for _ in range(MAX_LEN - len(entry)):
+ res = res + ' '
+ return res
+
+
+def find_repository_root() -> str:
+ root = os.getcwd()
+ try:
+ root = subprocess.check_output('git rev-parse --show-toplevel', shell=True)
+ except CalledProcessError as e:
+ print('The current working directory is not a git repository. \
+ \"git rev-parse --show-toplevel\" exited with code {}.'.format(e.returncode))
+ sys.exit(GIT_ERROR)
+ return root.rstrip().decode('utf-8')
+
+
+def create_committers_file(committers: OrderedDict):
+ contrib_directory = os.path.join(find_repository_root(), 'contrib')
+ file_loader = FileSystemLoader(contrib_directory)
+ env = Environment(loader=file_loader)
+ template = env.get_template('COMITTERS.rst.j2')
+ render_output = template.render(committers=committers, get_table_entry=get_table_entry)
+ committers_file = os.path.join(contrib_directory, 'COMMITTERS.rst')
+
+ with open(committers_file, 'w') as f:
+ f.write(render_output)
+
+
+def commit_changes_if_needed(token: str):
+ committers_file = os.path.join(find_repository_root(), 'contrib/COMMITTERS.rst')
+ git_diff = subprocess.call('git diff --quiet {}'.format(committers_file), shell=True)
+ if git_diff:
+ commit_message = '\'contrib: Update COMMITTERS.rst\''
+ branch_name = 'update_committers'
+ subprocess.call('git add {}'.format(committers_file), shell=True)
+ subprocess.call('git commit -m {}'.format(commit_message), shell=True)
+ try:
+ subprocess.call('git push -u origin {} 2>&1'.format(branch_name),
+ shell=True)
+ except CalledProcessError as e:
+ print('Could not push to remote branch. \"git push -u origin {}\" \
+ exited with code {}.'.format(branch_name, e.returncode))
+ sys.exit(GIT_ERROR)
+ data = urllib.parse.urlencode({'source_branch': 'update_committers',
+ 'target_branch': 'master',
+ 'title': 'Update COMMITTERS.rst file'})
+ request = urllib.request.Request(MERGE_REQUEST, data=bytearray(data, 'ASCII'))
+ request.add_header('PRIVATE-TOKEN', token)
+ response = urllib.request.urlopen(request).read().decode('utf-8')
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Update gitlab committers according to COMMITTERS.rst"
+ )
+ parser.add_argument(
+ "token", type=str,
+ help="Your private access token. See https://gitlab.com/profile/personal_access_tokens."
+ )
+ args = parser.parse_args()
+
+ committers = get_committers(args.token)
+ create_committers_file(committers)
+ commit_changes_if_needed(args.token)
+
+
+if __name__ == '__main__':
+ main()