Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cli] Export list of develop PRs to be merged into master #13944

Merged
merged 7 commits into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/python/qmk/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import_names = {
# A mapping of package name to importable name
'pep8-naming': 'pep8ext_naming',
'python-sqlite-cache': 'sqlite_cache',
'pyusb': 'usb.core',
'qmk-dotty-dict': 'dotty_dict'
}
Expand Down Expand Up @@ -46,6 +47,7 @@
'qmk.cli.format.text',
'qmk.cli.generate.api',
'qmk.cli.generate.config_h',
'qmk.cli.generate.develop_pr_list',
'qmk.cli.generate.dfu_header',
'qmk.cli.generate.docs',
'qmk.cli.generate.info_json',
Expand Down
99 changes: 99 additions & 0 deletions lib/python/qmk/cli/generate/develop_pr_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""Export the initial list of PRs associated with a `develop` merge to `master`.
"""
import os
import re
from pathlib import Path
from subprocess import DEVNULL

from milc import cli

cache_timeout = 7 * 86400
fix_expr = re.compile(r'fix', flags=re.IGNORECASE)
clean1_expr = re.compile(r'\[(develop|keyboard|keymap|core|cli|bug|docs|feature)\]', flags=re.IGNORECASE)
clean2_expr = re.compile(r'^(develop|keyboard|keymap|core|cli|bug|docs|feature):', flags=re.IGNORECASE)


def _get_pr_info(cache, gh, pr_num):
pull = cache.get(f'pull:{pr_num}')
if pull is None:
print(f'Retrieving info for PR #{pr_num}')
pull = gh.pulls.get(owner='qmk', repo='qmk_firmware', pull_number=pr_num)
cache.set(f'pull:{pr_num}', pull, cache_timeout)
return pull


@cli.argument('-f', '--from-ref', default='0.11.0', help='Git revision/tag/reference/branch to begin search')
@cli.argument('-b', '--branch', default='upstream/develop', help='Git branch to iterate (default: "upstream/develop")')
@cli.subcommand('Creates the develop PR list.', hidden=False if cli.config.user.developer else True)
def generate_develop_pr_list(cli):
"""Retrieves information from GitHub regarding the list of PRs associated
with a merge of `develop` branch into `master`.

Requires environment variable GITHUB_TOKEN to be set.
"""

if 'GITHUB_TOKEN' not in os.environ or os.environ['GITHUB_TOKEN'] == '':
cli.log.error('Environment variable "GITHUB_TOKEN" is not set.')
return 1

git_args = ['git', 'rev-list', '--oneline', '--no-merges', '--reverse', f'{cli.args.from_ref}...{cli.args.branch}', '^upstream/master']
commit_list = cli.run(git_args, capture_output=True, stdin=DEVNULL)

from sqlite_cache.sqlite_cache import SqliteCache
cache_loc = Path(cli.config_file).parent
cache = SqliteCache(cache_loc)

from ghapi.all import GhApi
gh = GhApi()

pr_list_bugs = []
pr_list_dependencies = []
pr_list_core = []
pr_list_keyboards = []
pr_list_keyboard_fixes = []
pr_list_cli = []
pr_list_others = []

def _categorise_commit(commit_info):
def fix_or_normal(info, fixes_collection, normal_collection):
if "bug" in info['pr_labels'] or fix_expr.search(info['title']):
fixes_collection.append(info)
else:
normal_collection.append(info)

if "dependencies" in commit_info['pr_labels']:
fix_or_normal(commit_info, pr_list_bugs, pr_list_dependencies)
elif "core" in commit_info['pr_labels']:
fix_or_normal(commit_info, pr_list_bugs, pr_list_core)
elif "keyboard" in commit_info['pr_labels'] or "keymap" in commit_info['pr_labels'] or "via" in commit_info['pr_labels']:
fix_or_normal(commit_info, pr_list_keyboard_fixes, pr_list_keyboards)
elif "cli" in commit_info['pr_labels']:
fix_or_normal(commit_info, pr_list_bugs, pr_list_cli)
else:
fix_or_normal(commit_info, pr_list_bugs, pr_list_others)

git_expr = re.compile(r'^(?P<hash>[a-f0-9]+) (?P<title>.*) \(#(?P<pr>[0-9]+)\)$')
for line in commit_list.stdout.split('\n'):
match = git_expr.search(line)
if match:
pr_info = _get_pr_info(cache, gh, match.group("pr"))
commit_info = {'hash': match.group("hash"), 'title': match.group("title"), 'pr_num': int(match.group("pr")), 'pr_labels': [label.name for label in pr_info.labels.items]}
_categorise_commit(commit_info)

def _dump_commit_list(name, collection):
if len(collection) == 0:
return
print("")
print(f"{name}:")
for commit in sorted(collection, key=lambda x: x['pr_num']):
title = clean1_expr.sub('', clean2_expr.sub('', commit['title'])).strip()
pr_num = commit['pr_num']
print(f'* {title} ([#{pr_num}](https://github.com/qmk/qmk_firmware/pull/{pr_num}))')

_dump_commit_list("Bugs", pr_list_bugs)
_dump_commit_list("Core", pr_list_core)
_dump_commit_list("CLI", pr_list_cli)
_dump_commit_list("Submodule updates", pr_list_dependencies)
_dump_commit_list("Keyboards", pr_list_keyboards)
_dump_commit_list("Keyboard fixes", pr_list_keyboard_fixes)
_dump_commit_list("Others", pr_list_others)
2 changes: 2 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ nose2
flake8
pep8-naming
yapf
ghapi
python-sqlite-cache