Files
firebase-ios-sdk/Releases/update-versions.py
T

302 lines
9.1 KiB
Python
Executable File

#!/usr/bin/python
# Copyright 2018 Google
#
# 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.
"""update-versions.py creates a release branch and commit with version updates.
With the required --version parameter, this script will update all files in
the repo based on the versions in Releases/Manifests/{version}.json.
It will create a release branch, push and tag the updates, and push the
updated podspecs to cpdc-internal.
"""
import argparse
import json
import os
import subprocess
import sys
import tempfile
test_mode = False # Flag to disable external repo updates
def SetupArguments():
"""SetupArguments sets up the set of command-line arguments.
Returns:
Args: The set of command line arguments
"""
parser = argparse.ArgumentParser(description='Update Pod Versions')
parser.add_argument('--version', required=True, help='Firebase version')
parser.add_argument(
'--test_mode',
dest='test_mode',
action='store_true',
help='Log commands instead of updating public repo')
parser.add_argument(
'--tag_update',
dest='tag_update',
action='store_true',
help='Update the tags only')
parser.add_argument(
'--base_branch',
dest='base_branch',
default='master',
help='Base branch for new release')
parser.add_argument(
'--push_only',
dest='push_only',
action='store_true',
help='Skip all of script except pushing podspecs to cpdc_internal')
args = parser.parse_args()
return args
def LogOrRun(command):
"""Log or run a command depending on test_mode value.
Args:
command: command to log or run.
"""
if test_mode:
print 'Log only: {}'.format(command)
else:
os.system(command)
def LogAndRun(command):
"""Log and run a command depending on test_mode value.
Args:
command: command to log and run.
"""
print 'Log only: {}'.format(command)
os.system(command)
def GetVersionData(git_root, version):
"""Update version specifier in FIROptions.m.
Args:
git_root: root of git checkout.
version: the next version to release.
Returns:
Dictionary with pod keys and version values.
"""
json_file = os.path.join(git_root, 'Releases', 'Manifests',
'{}.json'.format(version))
if os.path.isfile(json_file):
return json.load(open(json_file))
else:
sys.exit('Missing version file:{}'.format(json_file))
def CreateReleaseBranch(release_branch, base_branch):
"""Create and push the release branch.
Args:
release_branch: the name of the git release branch.
"""
os.system('git checkout {}'.format(base_branch))
os.system('git pull')
os.system('git checkout -b {}'.format(release_branch))
LogOrRun('git push origin {}'.format(release_branch))
LogOrRun('git branch --set-upstream-to=origin/{} {}'.format(release_branch,
release_branch))
def UpdatePodSpecs(git_root, version_data, firebase_version):
"""Update the podspecs with the right version.
Args:
git_root: root of git checkout.
version_data: dictionary of versions to be updated.
firebase_version: the Firebase version.
"""
core_podspec = os.path.join(git_root, 'FirebaseCore.podspec')
os.system("sed -i.bak -e \"s/\\(Firebase_VERSION=\\).*'/\\1{}'/\" {}".format(
firebase_version, core_podspec))
for pod, version in version_data.items():
podspec = os.path.join(git_root, '{}.podspec'.format(pod))
os.system("sed -i.bak -e \"s/\\(\\.version.*=[[:space:]]*'\\).*'/\\1{}'/\" "
'{}'.format(version, podspec))
def UpdatePodfiles(git_root, version):
"""Update Podfile's to reference the latest Firebase pod.
Args:
git_root: root of git checkout.
version: the next Firebase version to release.
"""
firebase_podfile = os.path.join(git_root, 'Example', 'Podfile')
firestore_podfile = os.path.join(git_root, 'Firestore', 'Example', 'Podfile')
collision_podfile = os.path.join(git_root, 'SymbolCollisionTest', 'Podfile')
sed_command = ("sed -i.bak -e \"s#\\(pod "
"'Firebase/CoreOnly',[[:space:]]*'\\).*'#\\1{}'#\" {}")
os.system(sed_command.format(version, firebase_podfile))
os.system(sed_command.format(version, firestore_podfile))
sed_command = ("sed -i.bak -e \"s#\\(pod "
"'Firebase',[[:space:]]*'\\).*'#\\1{}'#\" {}")
os.system(sed_command.format(version, collision_podfile))
def GenerateTag(pod, version):
""" Generate a tag from a pod and a version.
Args:
pod: name of the pod for which to generate the tag.
version: version of the pod to tag.
Returns:
Tag.
"""
if pod == "Firebase":
return 'CocoaPods-{}'.format(version)
if pod.startswith("Firebase"):
return '{}-{}'.format(pod[len('Firebase'):], version)
if pod.startswith("Google"):
return '{}-{}'.format(pod[len('Google'):], version)
sys.exit("Script does not support generating a tag for {}".format(pod))
def UpdateTags(version_data, first=False):
"""Update tags.
Args:
version_data: dictionary of versions to be updated.
firebase_version: the Firebase version.
first: set to true the first time the versions are set.
"""
for pod, version in version_data.items():
tag = GenerateTag(pod, version)
if not first:
LogOrRun("git push --delete origin '{}'".format(tag))
LogOrRun("git tag --delete '{}'".format(tag))
LogOrRun("git tag '{}'".format(tag))
LogOrRun("git push origin '{}'".format(tag))
def CheckVersions(version_data, firebase_version):
"""Ensure that versions do not already exist as tags.
Args:
version_data: dictionary of versions to be updated.
"""
error = False
for pod, version in version_data.items():
tag = GenerateTag(pod, version)
if pod == "Firebase":
if version != firebase_version:
sys.exit("Aborting: Release version must match Firebase pod version.")
find = subprocess.Popen(
['git', 'tag', '-l', tag],
stdout=subprocess.PIPE).communicate()[0].rstrip()
if tag == find:
print "{} tag already exists".format(tag)
error = True
if error:
sys.exit("Aborting: Remove pre-existing tags and retry")
def GetCpdcInternal():
"""Find the firebase repo.
"""
tmp_file = tempfile.mktemp()
os.system('pod repo list | grep -B2 sso://cpdc-internal/firebase | head -1 > {}'
.format(tmp_file))
with open(tmp_file,'r') as o:
output_var = ''.join(o.readlines()).strip()
os.system('rm -rf {}'.format(tmp_file))
return output_var
# TODO update PushPodspecs to push dependent pods first, like when FirebaseCore
# depends on the most recent version of GoogleUtilities.
def PushPodspecs(version_data):
"""Push podspecs to cpdc-firebase.
Args:
version_data: dictionary of versions to be updated.
"""
pods = version_data.keys()
for pod in pods:
LogOrRun('pod cache clean {} --all'.format(pod))
if pod == 'Firebase':
# Do the Firebase pod last
continue
if pod == 'FirebaseFirestore':
warnings_ok = ' --allow-warnings'
else:
warnings_ok = ''
podspec = '{}.podspec'.format(pod)
LogAndRun('pod repo push --skip-tests --use-json {} {}{}'
.format(GetCpdcInternal(), podspec, warnings_ok))
# This command will need to be rerun if any pods need to be pushed from Rapid.
LogAndRun('pod repo push --skip-tests --use-json --skip-import-validation ' +
'--sources=sso://cpdc-internal/firebase.git,https://cdn.cocoapods.org' +
' {} Firebase.podspec {}'.format(GetCpdcInternal(), warnings_ok))
def UpdateVersions():
"""UpdateVersions is the main body to create the branch and change versions.
"""
global test_mode
args = SetupArguments()
test_mode = args.test_mode
# Validate version is proper format
major, minor, patch = args.version.split('.')
if (not major.isdigit()) or (not minor.isdigit()) or (not patch.isdigit()):
sys.exit('Invalid version parameter')
git_root = subprocess.Popen(
['git', 'rev-parse', '--show-toplevel'],
stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')
version_data = GetVersionData(git_root, args.version)
if not args.push_only:
if args.tag_update:
UpdateTags(version_data)
return
CheckVersions(version_data, args.version)
release_branch = 'release-{}'.format(args.version)
CreateReleaseBranch(release_branch, args.base_branch)
UpdatePodSpecs(git_root, version_data, args.version)
UpdatePodfiles(git_root, args.version)
LogOrRun('git commit -am "Update versions for Release {}"'
.format(args.version))
LogOrRun('git push origin {}'.format(release_branch))
UpdateTags(version_data, True)
PushPodspecs(version_data)
if __name__ == '__main__':
UpdateVersions()