From 60e786d7248044fad3db33ed401f69c7d0607e61 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Thu, 6 Jun 2019 22:06:48 +1000 Subject: [PATCH] Add tools/bulk_review.sh and get-contacts get-contacts: To extract the PTL/Liaison contact information from the governance data / release team data tools/bulk_review.sh: To manipulate a dirty working-tree and post as a single gerrit topic, one change per team. Changes are unordered so any change can be merged when it's ready/ approved by the appropriate team Also enhance get-deliverable-owner: to detect file paths Story: 2005704 Task: 31028 Change-Id: Ia319e8a7b4da195cb4bc861c51025a41adc43bb3 --- doc/source/reference/using.rst | 21 ++++ openstack_releases/cmds/get_contacts.py | 80 ++++++++++++ .../cmds/get_deliverable_owner.py | 25 ++-- setup.cfg | 1 + tools/bulk_review.sh | 117 ++++++++++++++++++ 5 files changed, 237 insertions(+), 7 deletions(-) create mode 100644 openstack_releases/cmds/get_contacts.py create mode 100755 tools/bulk_review.sh diff --git a/doc/source/reference/using.rst b/doc/source/reference/using.rst index 5f43dfa893..ef1e337753 100644 --- a/doc/source/reference/using.rst +++ b/doc/source/reference/using.rst @@ -576,6 +576,8 @@ easy as ``pip install .`` in this repository directory. of the releases that should have been tagged by hand have been * ``init-series`` initializes a new deliverable directory with stub files based on the previous release. +* ``get-contacts`` Loads the governance and liaison data to print contact + deatils for a given team tools/aclmanager.py ------------------- @@ -620,6 +622,25 @@ Example: tox -e check_approval -- 695375 +tools/bulk_review.sh +-------------------- + +A script for taking a working directory and dividing up the modified files into +a collection on independent per-team reviews. Each per-team change should be +able to be processed in any order. These reviews will request review from the +the PTL and all release liaisons. + +This is designed to be used by the release team at key points in the cycle to +ease bulk releases. + + .. note:: + + This tool will commit ultimately commit all modified deliverables and + modifies git state. Therefore it is essential that befoer running it + the working tree contains only the logical changes appropriate for the + stage of the release *and* all changes are saved elsewhere, in case the + script encounters a problem. + tools/membership_freeze_test.py -------------------------------- diff --git a/openstack_releases/cmds/get_contacts.py b/openstack_releases/cmds/get_contacts.py new file mode 100644 index 0000000000..4462b45963 --- /dev/null +++ b/openstack_releases/cmds/get_contacts.py @@ -0,0 +1,80 @@ +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Get the PTL and release liaison information. + +Grab the PTL's contact details from the governance repo; and Liaisons +data from release_liaisons.yaml +""" + +import argparse +import sys + +from openstack_governance import governance + +from openstack_releases import liaisons + + +class Contact(object): + def __init__(self, contact_data): + self.name = contact_data['name'] + self.irc = contact_data['irc'] + self.email = contact_data['email'] + + +def print_contact(contact): + print('Name : %s' % contact.name) + print('IRC Nick : %s' % contact.irc) + print('Email : %s' % contact.email) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('team', nargs='+', help='The team(s) to lookup') + who_group = parser.add_mutually_exclusive_group() + who_group.add_argument('--ptl', action='store_true', default=False, + help='Find PTL details') + who_group.add_argument('--liaisons', action='store_true', default=False, + help='Find Liaisons details') + who_group.add_argument('--all', action='store_true', default=True, + help='Find Liaisons details') + args = parser.parse_args() + + gov_data = governance.Governance.from_remote_repo() + liaison_data = liaisons.get_liaisons() + + for team_name in args.team: + contacts = set() + if args.ptl or args.all: + team_data = gov_data.get_team(team_name) + if not team_data: + print('Unable to find team [%s] in governance data' % + (args.team), + file=sys.stderr) + return 1 + + contacts.add(Contact(team_data.ptl)) + + if args.liaisons or args.all: + for liaison in liaison_data.get(team_name.lower(), []): + contacts.add(Contact(liaison)) + + team_header = '%s Contacts:' % team_name.title() + print() + print(team_header) + print('%s' % ('-' * len(team_header))) + for contact in contacts: + print_contact(contact) + + return 0 diff --git a/openstack_releases/cmds/get_deliverable_owner.py b/openstack_releases/cmds/get_deliverable_owner.py index e96f467e3d..1b558954fd 100644 --- a/openstack_releases/cmds/get_deliverable_owner.py +++ b/openstack_releases/cmds/get_deliverable_owner.py @@ -27,12 +27,23 @@ def main(): default=openstack_releases.deliverable_dir, help='location of deliverable files', ) + parser.add_argument( + '--file', + default=False, + action='store_true', + help='deliverable arg is a file path rather than a std. deliverable' + ) args = parser.parse_args() - all_deliv = deliverable.Deliverables( - root_dir=args.deliverables_dir, - collapse_history=False, - ) - for deliv in all_deliv.get_deliverable_history(args.deliverable): - print(deliv.team) - break + # If we've been told the 'deliverable' is infact a yaml file *or* the + # deliverable contains a '/' just load that file directly + if args.file or '/' in args.deliverable: + deliv = deliverable.Deliverable.read_file(args.deliverable) + else: + all_deliv = deliverable.Deliverables( + root_dir=args.deliverables_dir, + collapse_history=False, + ) + deliv = next(all_deliv.get_deliverable_history(args.deliverable)) + + print(deliv.team) diff --git a/setup.cfg b/setup.cfg index 25beccbe51..f209d3eb19 100644 --- a/setup.cfg +++ b/setup.cfg @@ -41,6 +41,7 @@ console_scripts = release-notes = openstack_releases.cmds.release_notes:main check-schema = openstack_releases.cmds.check_schema:main find-gerrit-acl-issues = openstack_releases.cmds.find_gerrit_acl_issues:main + get-contacts = openstack_releases.cmds.get_contacts:main [build_sphinx] source-dir = doc/source diff --git a/tools/bulk_review.sh b/tools/bulk_review.sh new file mode 100755 index 0000000000..88f757f488 --- /dev/null +++ b/tools/bulk_review.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +# +# Tool to take a dirty working tree and create a 'flat' gerrit topic (per team) +# for all the changes +# +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +function usage { + echo "Usage: bulk_review.sh -t topic -s subject -b message_body" + echo + echo " topic: local branch names will be of the form $team-$topic" + echo " and gerrit topic will be set to $topic" + echo " subject: This will be the subject in the git commit" + echo " body: This will be the message body for the git commit" + echo + echo "This script operates on a dirty repo (such as one created by" + echo "running tools/make_missing_releases.sh. It will then create a" + echo "local branch per-team of the modified deliverable files and then" + echo "submit that branch for review" + echo + echo "PTLs and liaisons will be CC'd on the review" +} + +# NOTE: It might be worth switching getopt but I don't knwo if that is +# available and the same on MacOS +while getopts "t:s:b:" arg ; do + case "$arg" in + t) + topic=$OPTARG + ;; + s) + subject=$OPTARG + ;; + b) + body=$OPTARG + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ -z "$topic" -o -z "$subject" -o -z "$body" ] ; then + usage + exit 1 +fi + +echo 'This script will modifiy git branches and and submit reviews.' +echo 'It relies on master being a safe/clean branch.' +echo +echo 'If master contains private changes, abort now' +echo 'If you have any unrelated work, abort now' +echo 'If you have not saved the modified deliverables somewhere, abort now' +echo +echo 'Press return to continue or -C to abort' + +read _continue + +declare -A files_by_team_release=() + +# Find the team associated with each modified deliverable file +declare -a deliverables=($(git ls-files -m deliverables)) +for file in "${deliverables[@]}" ; do + team="$(get-deliverable-owner --file $file)" + files_by_team_release["$team"]+=" $file" +done + +#for x in "${!files_by_team_release[@]}"; do printf "[%q]=%q\n" "$x" "${files_by_team_release[$x]}" ; done + +for team in "${!files_by_team_release[@]}" ; do + branch_name=${team/ /_}-${topic} + echo "[$team] :: [$branch_name] ${files_by_team_release[$team]}" + + git checkout -b $branch_name -t origin/master + + git add ${files_by_team_release[$team]} + git commit \ + -m "[$team] $subject" \ + -m "$body" + + git stash + git checkout master + git stash pop +done + +git checkout master +git stash list +git branch -va | grep -E "$topic" + +for team in "${!files_by_team_release[@]}" ; do + declare -a emails=( + $(get-contacts --all "$team"| awk -F': ' '/Email/ {print $2}') + ) + review_args='' + for email in ${emails[@]} ; do + review_args+=" --reviewers $email" + done + + branch_name=${team/ /_}-${topic} + git checkout $branch_name + git review -y -t $topic $review_args +done +git checkout master