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
This commit is contained in:
Tony Breeds 2019-06-06 22:06:48 +10:00 committed by Thierry Carrez
parent 802661cdb3
commit 60e786d724
5 changed files with 237 additions and 7 deletions

View File

@ -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
--------------------------------

View File

@ -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

View File

@ -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()
# 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,
)
for deliv in all_deliv.get_deliverable_history(args.deliverable):
deliv = next(all_deliv.get_deliverable_history(args.deliverable))
print(deliv.team)
break

View File

@ -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

117
tools/bulk_review.sh Executable file
View File

@ -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 <ctrl>-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