| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- #!/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 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()
|