Compare commits

...

9 commits

Author SHA1 Message Date
Zach White
295cb5c60a fix stacktrace 2021-09-21 14:33:59 -07:00
Zach White
610111583b add the pr comment ourselves and request reviews 2021-09-21 14:28:28 -07:00
Zach White
1db04e4622 delay importing of codeowners 2021-09-18 23:15:53 -07:00
Zach White
40e8ab382c tweak the maintainers job 2021-09-18 23:11:30 -07:00
Zach White
eee765d454 add missing newline 2021-09-18 23:10:37 -07:00
Zach White
771c47ab99 refine how we ping 2021-09-18 23:04:10 -07:00
Zach White
405e200ca2 install deps 2021-09-18 22:57:07 -07:00
Zach White
65fd33ec0e Add CODEOWNERS support 2021-09-18 22:51:44 -07:00
Zach White
c4a891d425 add mechanisms for finding and pinging maintainers 2021-09-18 21:49:40 -07:00
7 changed files with 129 additions and 1 deletions

28
.github/workflows/maintainers.yaml vendored Normal file
View file

@ -0,0 +1,28 @@
name: Ping maintainers
on:
pull_request:
jobs:
maintainer_ping:
runs-on: ubuntu-latest
container: qmkfm/qmk_cli
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: trilom/file-changes-action@v1.2.4
id: file_changes
with:
output: " "
fileOutput: " "
- name: Install dependencies
run: pip3 install -r requirements-dev.txt
- name: Ping maintainers and request reviews
shell: "bash {0}"
run: qmk ping-maintainers --pr ${{ github.event.number }} ${{ steps.file_changes.outputs.files }}

2
CODEOWNERS Normal file
View file

@ -0,0 +1,2 @@
* @qmk/collaborators
/lib/python/* @qmk/python

View file

@ -60,10 +60,12 @@ subcommands = [
'qmk.cli.lint', 'qmk.cli.lint',
'qmk.cli.list.keyboards', 'qmk.cli.list.keyboards',
'qmk.cli.list.keymaps', 'qmk.cli.list.keymaps',
'qmk.cli.list.maintainers',
'qmk.cli.kle2json', 'qmk.cli.kle2json',
'qmk.cli.multibuild', 'qmk.cli.multibuild',
'qmk.cli.new.keyboard', 'qmk.cli.new.keyboard',
'qmk.cli.new.keymap', 'qmk.cli.new.keymap',
'qmk.cli.ping.maintainers',
'qmk.cli.pyformat', 'qmk.cli.pyformat',
'qmk.cli.pytest', 'qmk.cli.pytest',
] ]

View file

@ -0,0 +1,16 @@
"""List the keymaps for a specific keyboard
"""
from pathlib import Path
from milc import cli
from qmk.maintainers import maintainers
@cli.argument("files", type=Path, arg_only=True, nargs='*', help="File to check")
@cli.subcommand("List the maintainers for a file.")
def list_maintainers(cli):
"""List the maintainers for a file.
"""
for file in cli.args.files:
cli.echo('%s: %s', file, ', '.join(maintainers(file)))

View file

@ -0,0 +1,51 @@
"""Generate a message to ping people responsible for one or more files.
"""
from pathlib import Path
from milc import cli
from qmk.maintainers import maintainers
@cli.argument('--pr', type=int, arg_only=True, help="PR to send ping to (optional)")
@cli.argument('--owner', default='qmk', arg_only=True, help="Owner for the repo (Default: qmk)")
@cli.argument('--repo', default='qmk_firmware', arg_only=True, help="Repo to send pings to (Default: qmk_firmware)")
@cli.argument("files", type=Path, arg_only=True, nargs='*', help="File to ping maintainers for.")
@cli.subcommand("Ping the maintainers and request reviews for one or more files.")
def ping_maintainers(cli):
"""Ping the maintainers for one or more files.
"""
github_maintainers = set()
github_teams = set()
for file in cli.args.files:
for maintainer in maintainers(file):
if '/' in maintainer:
github_teams.add(maintainer)
else:
github_maintainers.add(maintainer)
if cli.args.pr:
from ghapi.all import GhApi
ghapi = GhApi(owner=cli.args.owner, repo=cli.args.repo)
pr = ghapi.pulls.get(cli.args.pr)
if not pr.draft:
for team in pr.requested_teams:
team_name = f'@{cli.args.owner}/{team.slug}'
if team_name in github_teams:
cli.log.info('Found %s in reviews already, skipping', team_name)
github_teams.remove(team_name)
for team in github_teams:
cli.log.info('Requesting review from team %s', team.split('/', 1)[1])
ghapi.pulls.request_reviewers(pull_number=cli.args.pr, team_reviewers=team.split('/', 1)[1])
if github_maintainers:
ghapi.issues.create_comment(cli.args.pr, f'If you were pinged by this comment you have one or more files being changed by this PR: {" ".join(sorted(github_maintainers))}')
else:
print(f'Team Reviews: {" ".join(sorted(github_teams))}')
print(f'Individual Reviews: {" ".join(sorted(github_maintainers))}')

View file

@ -0,0 +1,27 @@
from pathlib import Path
from qmk.json_schema import json_load
def maintainers(file):
"""Yields maintainers for a file.
"""
from codeowners import CodeOwners
codeowners_file = Path('CODEOWNERS')
codeowners = CodeOwners(codeowners_file.read_text())
maintainers = [owner[1] for owner in codeowners.of(str(file))]
file_dir = file if file.is_dir() else file.parent
cur_path = Path('.')
for path_part in file_dir.parts:
cur_path = cur_path / path_part
info_file = cur_path / 'info.json'
if info_file.exists():
new_info_data = json_load(info_file)
maintainers = new_info_data.get('maintainer').replace(',', ' ').split()
maintainers = ['@' + maintainer for maintainer in maintainers]
for maintainer in maintainers:
yield '@qmk/collaborators' if maintainer == 'qmk' else maintainer

View file

@ -2,7 +2,9 @@
-r requirements.txt -r requirements.txt
# Python development requirements # Python development requirements
nose2 codeowners
flake8 flake8
ghapi
nose2
pep8-naming pep8-naming
yapf yapf