Merge pull request #4531 from adbridge/update

Update branching option to branch from another branch.
pull/4636/head
Jimmy Brisson 2017-06-29 11:05:17 -05:00 committed by GitHub
commit 18b1cb6c11
3 changed files with 135 additions and 93 deletions

View File

@ -1,4 +1,17 @@
{ {
"update-config" : {
"help" : "Update each example repo with a version of mbed-os identified by the tag",
"via-fork" : {
"help" : "-f cmd line option. Update a fork",
"github-user" : "adbridge"
},
"via-branch" : {
"help" : "-b cmd line option. Update dst branch, created from src branch",
"src-branch" : "mbed-os-5.5.0-rc1-oob",
"dst-branch" : "mbed-os-5.5.0-rc2-oob"
},
"tag" : "mbed-os-5.5.0-rc2"
},
"examples": [ "examples": [
{ {
"name": "mbed-os-example-blinky", "name": "mbed-os-example-blinky",

View File

@ -0,0 +1,4 @@
Please test this PR
If successful then merge, otherwise provide a known issue.
Once you get notification of the release being made public then tag Master with {{ tag }} .

View File

@ -14,11 +14,29 @@
# 2) Update a different ARMmbed branch of the specified example # 2) Update a different ARMmbed branch of the specified example
# #
# A branch to update is specified. If it doesn't already exist then it is first created. # A branch to update is specified. If it doesn't already exist then it is first created.
# This branch will be updated and the change automatically pushed. # This branch will be updated and the change automatically pushed. The new branch will
# be created from the specified source branch.
#
# The modes are controlled via configuration data in the json file.
# E.g.
#
# "update-config" : {
# "help" : "Update each example repo with a version of mbed-os identified by the tag",
# "via-fork" : {
# "help" : "-f cmd line option. Update a fork",
# "github-user" : "adbridge"
# },
# "via-branch" : {
# "help" : "-b cmd line option. Update dst branch, created from src branch",
# "src-branch" : "mbed-os-5.5.0-rc1-oob",
# "dst-branch" : "mbed-os-5.5.0-rc2-oob"
# },
# "tag" : "mbed-os-5.5.0-rc2"
#
# #
# Command usage: # Command usage:
# #
# update.py -c <config file> - T <github_token> -l <logging level> -U <github user> -b <branch> <tag> # update.py -c <config file> - T <github_token> -l <logging level> -f -b
# #
# Where: # Where:
# -c <config file> - Optional path to an examples file. # -c <config file> - Optional path to an examples file.
@ -27,16 +45,18 @@
# -l <logging level> - Optional Level for providing logging output. Can be one of, # -l <logging level> - Optional Level for providing logging output. Can be one of,
# CRITICAL, ERROR, WARNING, INFO, DEBUG # CRITICAL, ERROR, WARNING, INFO, DEBUG
# If not provided the default is 'INFO' # If not provided the default is 'INFO'
# -U <github_user> - GitHub user for forked repos # -f - Update forked repos. This will use the 'github-user' parameter in
# -b <branch> - Branch to be updated # the 'via-fork' section.
# -b - Update branched repos. This will use the "src-branch" and
# "dst-branch" parameters in the 'via-branch' section. The destination
# branch is created from the source branch (if it doesn't already exist).
# #
# NOTE only one of -U or -b can be specified. # The options -f and -b are mutually exlusive. Only one can be specified.
# #
# <tag> mbed-os tag to which all examples will be updated
# #
import os import os
from os.path import dirname, abspath, basename from os.path import dirname, abspath, basename, join
import sys import sys
import logging import logging
import argparse import argparse
@ -46,6 +66,8 @@ import shutil
import stat import stat
import re import re
from github import Github, GithubException from github import Github, GithubException
from jinja2 import FileSystemLoader, StrictUndefined
from jinja2.environment import Environment
ROOT = abspath(dirname(dirname(dirname(dirname(__file__))))) ROOT = abspath(dirname(dirname(dirname(dirname(__file__)))))
sys.path.insert(0, ROOT) sys.path.insert(0, ROOT)
@ -216,7 +238,6 @@ def prepare_fork(arm_example):
Args: Args:
arm_example - Full GitHub repo path for original example arm_example - Full GitHub repo path for original example
ret - True if the fork was synchronised successfully, False otherwise
""" """
@ -227,111 +248,89 @@ def prepare_fork(arm_example):
['git', 'fetch', 'armmbed'], ['git', 'fetch', 'armmbed'],
['git', 'reset', '--hard', 'armmbed/master'], ['git', 'reset', '--hard', 'armmbed/master'],
['git', 'push', '-f', 'origin']]: ['git', 'push', '-f', 'origin']]:
if run_cmd(cmd): run_cmd(cmd, exit_on_failure=True)
update_log.error("Fork preparation failed")
return False
return True
def prepare_branch(branch): def prepare_branch(src, dst):
""" Set up at branch ready for use in updating examples """ Set up at branch ready for use in updating examples
Description: Description:
This function checks whether or not the supplied branch exists. This function checks whether or not the supplied dst branch exists.
If it does not, the branch is created and pushed to the origin. If it does not, the branch is created from the src and pushed to the origin.
The branch is then switched to. The branch is then switched to.
Args: Args:
arm_example - Full GitHub repo path for original example src - branch to create the dst branch from
ret - True if the fork was synchronised successfully, False otherwise dst - branch to update
""" """
update_log.debug("Preparing branch: %s", branch) update_log.debug("Preparing branch: %s", dst)
# Check if branch already exists or not. # Check if branch already exists or not.
cmd = ['git', 'branch'] cmd = ['git', 'branch']
return_code, output = run_cmd_with_output(cmd) _, output = run_cmd_with_output(cmd, exit_on_failure=True)
if not branch in output: if not dst in output:
# OOB branch does not exist thus create it and then check it out
cmd = ['git', 'checkout', '-b', branch] # OOB branch does not exist thus create it, first ensuring we are on
return_code = run_cmd(cmd) # the src branch and then check it out
if not return_code:
for cmd in [['git', 'checkout', src],
['git', 'checkout', '-b', dst],
['git', 'push', '-u', 'origin', dst]]:
run_cmd(cmd, exit_on_failure=True)
# Push new branch upstream
cmd = ['git', 'push', '-u', 'origin', branch]
return_code = run_cmd(cmd)
else: else:
cmd = ['git', 'checkout', branch] cmd = ['git', 'checkout', dst]
return_code = run_cmd(cmd) run_cmd(cmd, exit_on_failure=True)
if return_code: def upgrade_example(github, example, tag, ref, user, src, dst, template):
update_log.error("Failed to prepare branch: %s", branch)
return False
return True
def upgrade_example(github, example, tag, ref,
user='ARMmbed', branch='master'):
""" Upgrade all versions of mbed-os.lib found in the specified example repo """ Upgrade all versions of mbed-os.lib found in the specified example repo
Description: Description:
Clone a version of the example specified and upgrade all versions of Clone a version of the example specified and upgrade all versions of
mbed-os.lib found within its tree. The version cloned and how it mbed-os.lib found within its tree. The version cloned and how it
is upgraded depends on the user and branch specified. Only two options is upgraded depends on the user, src and dst settings.
are valid: 1) user == None
1) ARMmbed + non master branch The destination branch will be updated with the version of mbed-os
This option will update the branch directly in the ARMmbed repo. If the idenfied by the tag. If the destination branch does not exist then it
branch does not exist it will be first created. will be created from the source branch.
2) alternative user + master branch 2) user != None
The master branch of a fork of the example will be updated with the
This option assumes that a fork of the repo exists in the specified user's version of mbed-os identified by the tag.
account. The fork will first be updated so that it is up to date with the
upstream version , then the fork will be updated and a PR raised against
the upstream ie ARMmbed repo.
Args: Args:
github - GitHub instance to allow internal git commands to be run github - GitHub instance to allow internal git commands to be run
example - json example object containing the GitHub repo to update. example - json example object containing the GitHub repo to update.
tag - GitHub tag corresponding to a version of mbed-os to upgrade to. tag - GitHub tag corresponding to a version of mbed-os to upgrade to.
ref - SHA corresponding to the tag ref - SHA corresponding to the tag
user - GitHub user name (defaults to 'ARMmbed' if not supplied) user - GitHub user name
branch - branch to update (defaults to 'master' if not supplied) src - branch to create the dst branch from
dst - branch to update
returns True if the upgrade was successful, False otherwise returns True if the upgrade was successful, False otherwise
""" """
# If a user has not been specified then branch update will be used and thus
# the git user will be ARMmbed.
if not user:
user = 'ARMmbed'
ret = False ret = False
update_log.info("Updating example '%s'", example['name']) update_log.info("Updating example '%s'", example['name'])
update_log.debug("User: %s", user) update_log.debug("User: %s", user)
update_log.debug("Branch: %s", branch) update_log.debug("Src branch: %s", (src or "None"))
update_log.debug("Dst branch: %s", (dst or "None"))
# First check validity of user/branch combination
if ((user == 'ARMmbed' and branch == 'master') or
(user != 'ARMmbed' and branch != 'master')):
update_log.error("Invalid user/branch combination")
return False
cwd = os.getcwd() cwd = os.getcwd()
upstream_repo = 'ARMmbed/'+ example['name']
update_repo = "https://github.com/" + user + '/' + example['name'] update_repo = "https://github.com/" + user + '/' + example['name']
update_log.debug("Upstream repository: %s", upstream_repo)
update_log.debug("Update repository: %s", update_repo) update_log.debug("Update repository: %s", update_repo)
# Check access to mbed-os repo
try:
repo = github.get_repo(upstream_repo, False)
except:
update_log.error("Upstream repo: %s, does not exist - skipping", upstream_repo)
return False
# Clone the example repo # Clone the example repo
clone_cmd = ['git', 'clone', update_repo] clone_cmd = ['git', 'clone', update_repo]
return_code = run_cmd(clone_cmd) return_code = run_cmd(clone_cmd)
@ -343,14 +342,12 @@ def upgrade_example(github, example, tag, ref,
os.chdir(example['name']) os.chdir(example['name'])
# If the user is not the default, then a fork will be used. Thus # If the user is ARMmbed then a branch is used.
# synchronise the user fork with the upstream if user == 'ARMmbed':
if user != 'ARMmbed': prepare_branch(src, dst)
else:
prepare_fork(example['github']) prepare_fork(example['github'])
if branch != 'master':
prepare_branch(branch)
for example_directory in example_directories: for example_directory in example_directories:
if not upgrade_single_example(example, tag, os.path.relpath(example_directory, example['name']), ref): if not upgrade_single_example(example, tag, os.path.relpath(example_directory, example['name']), ref):
os.chdir(cwd) os.chdir(cwd)
@ -369,12 +366,28 @@ def upgrade_example(github, example, tag, ref,
return_code = run_cmd(push_cmd) return_code = run_cmd(push_cmd)
if not return_code: if not return_code:
# If the user is not ARMmbed then a fork is being used
if user != 'ARMmbed': if user != 'ARMmbed':
body = "Please test/merge this PR and then tag Master with " + tag
upstream_repo = 'ARMmbed/'+ example['name']
update_log.debug("Upstream repository: %s", upstream_repo)
# Check access to mbed-os repo
try:
repo = github.get_repo(upstream_repo, False)
except:
update_log.error("Upstream repo: %s, does not exist - skipping", upstream_repo)
return False
jinja_loader = FileSystemLoader(template)
jinja_environment = Environment(loader=jinja_loader,
undefined=StrictUndefined)
pr_body = jinja_environment.get_template("pr.tmpl").render(tag=tag)
# Raise a PR from release-candidate to master # Raise a PR from release-candidate to master
user_fork = user + ':master' user_fork = user + ':master'
try: try:
pr = repo.create_pull(title='Updating mbed-os to ' + tag, head=user_fork, base='master', body=body) pr = repo.create_pull(title='Updating mbed-os to ' + tag, head=user_fork, base='master', body=pr_body)
ret = True ret = True
except GithubException as e: except GithubException as e:
# Default to False # Default to False
@ -409,7 +422,6 @@ if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__, parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter) formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('tag', help="mbed-os tag to which all examples will be updated")
parser.add_argument('-c', '--config_file', help="Path to the configuration file (default is 'examples.json')", default='examples.json') parser.add_argument('-c', '--config_file', help="Path to the configuration file (default is 'examples.json')", default='examples.json')
parser.add_argument('-T', '--github_token', help="GitHub token for secure access") parser.add_argument('-T', '--github_token', help="GitHub token for secure access")
parser.add_argument('-l', '--log-level', parser.add_argument('-l', '--log-level',
@ -417,8 +429,8 @@ if __name__ == '__main__':
default='INFO') default='INFO')
exclusive = parser.add_mutually_exclusive_group(required=True) exclusive = parser.add_mutually_exclusive_group(required=True)
exclusive.add_argument('-U', '--github_user', help="GitHub user for forked repos, mutually exclusive to branch option") exclusive.add_argument('-f', '--fork', help="Update a fork", action='store_true')
exclusive.add_argument('-b', '--branch', help="Branch to be updated, mutually exclusive to user option") exclusive.add_argument('-b', '--branch', help="Update a branch", action='store_true')
args = parser.parse_args() args = parser.parse_args()
@ -441,30 +453,43 @@ if __name__ == '__main__':
create_work_directory('examples') create_work_directory('examples')
github = Github(args.github_token) github = Github(args.github_token)
config = json_data['update-config']
tag = config['tag']
user = None
src = "master"
dst = None
if args.fork:
user = config['via-fork']['github-user']
elif args.branch:
src = config['via-branch']['src-branch']
dst = config['via-branch']['dst-branch']
else:
userlog.error("Must specify either -f or -b command line option")
exit(1)
# Get the github sha corresponding to the specified mbed-os tag # Get the github sha corresponding to the specified mbed-os tag
cmd = ['git', 'rev-list', '-1', args.tag] cmd = ['git', 'rev-list', '-1', tag]
return_code, ref = run_cmd_with_output(cmd) return_code, ref = run_cmd_with_output(cmd)
if return_code: if return_code:
update_log.error("Could not obtain SHA for tag: %s", args.tag) update_log.error("Could not obtain SHA for tag: %s", tag)
sys.exit(1) sys.exit(1)
# Loop through the examples # Loop through the examples
failures = [] failures = []
successes = [] successes = []
results = {} results = {}
template = dirname(abspath(__file__))
os.chdir('examples') os.chdir('examples')
for example in json_data['examples']: for example in json_data['examples']:
# Determine if this example should be updated and if so update any found # Determine if this example should be updated and if so update any found
# mbed-os.lib files. # mbed-os.lib files.
# Only user or branch can be specified on the command line result = upgrade_example(github, example, tag, ref, user, src, dst, template)
if args.github_user:
result = upgrade_example(github, example, args.tag, ref, user=args.github_user)
else:
result = upgrade_example(github, example, args.tag, ref, branch=args.branch)
if result: if result:
successes += [example['name']] successes += [example['name']]