From 0d6d9488ae5183b5f0ebe7617dbfc4d13df37a8c Mon Sep 17 00:00:00 2001 From: Byoungchan Lee Date: Fri, 16 Jul 2021 03:13:37 +0900 Subject: [PATCH] Rename release_aar.py and modify it for validation of aar file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As announced in the google groups [1], the pre-built Android aar is no longer distributed and last update was August 2020. [2] So we can remove the code that uploads aar to bintray in release_aar.py. Still, the ability to create an Android aar and use it in a gradle project (examples/aarproject) is useful. It can also be used to validate aar by running PeerConnectionClientTest from examples/androidtests. So I renamed release_aar.py to test_aar.py and make it working without releasing the aar to an external hosting server. This makes it easy to verify further changes to the aar. [1] https://groups.google.com/g/discuss-webrtc/c/Ozvbd0p7Q1Y/m/TtQyRI1KAgAJ [2] https://mvnrepository.com/artifact/org.webrtc/google-webrtc?repo=bt-google-webrtc Bug: webrtc:11962 Change-Id: Ibe066a3a770569924e3b57805986808e1dd19df6 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/220622 Commit-Queue: Byoungchan Lee Reviewed-by: Xavier Lepaul‎ Cr-Commit-Position: refs/heads/master@{#34540} --- examples/aarproject/app/build.gradle | 7 +- tools_webrtc/android/release_aar.py | 307 --------------------------- tools_webrtc/android/test_aar.py | 145 +++++++++++++ 3 files changed, 149 insertions(+), 310 deletions(-) delete mode 100644 tools_webrtc/android/release_aar.py create mode 100755 tools_webrtc/android/test_aar.py diff --git a/examples/aarproject/app/build.gradle b/examples/aarproject/app/build.gradle index b4f2acdbdd..77dc3703ee 100644 --- a/examples/aarproject/app/build.gradle +++ b/examples/aarproject/app/build.gradle @@ -42,10 +42,11 @@ android { } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) + if (project.hasProperty('aarDir')) { + implementation fileTree(dir: project.aarDir, include: ['google-webrtc-*.aar']) + } implementation fileTree(dir: '../../androidapp/third_party/autobanh/lib', include: ['autobanh.jar']) - implementation 'com.android.support:appcompat-v7:26.1.0' - implementation 'org.webrtc:google-webrtc:1.0.+' + implementation 'com.android.support:support-annotations:26.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' diff --git a/tools_webrtc/android/release_aar.py b/tools_webrtc/android/release_aar.py deleted file mode 100644 index bc7f471ae3..0000000000 --- a/tools_webrtc/android/release_aar.py +++ /dev/null @@ -1,307 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. -# -# Use of this source code is governed by a BSD-style license -# that can be found in the LICENSE file in the root of the source -# tree. An additional intellectual property rights grant can be found -# in the file PATENTS. All contributing project authors may -# be found in the AUTHORS file in the root of the source tree. -"""Script for publishing WebRTC AAR on Bintray. - -Set BINTRAY_USER and BINTRAY_API_KEY environment variables before running -this script for authentication. -""" - -import argparse -import json -import logging -import os -import re -import shutil -import subprocess -import sys -import tempfile -import time - -SCRIPT_DIR = os.path.dirname(os.path.realpath(sys.argv[0])) -CHECKOUT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir)) - -sys.path.append(os.path.join(CHECKOUT_ROOT, 'third_party')) -import requests -import jinja2 - -sys.path.append(os.path.join(CHECKOUT_ROOT, 'tools_webrtc')) -from android.build_aar import BuildAar - -ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'] -MAVEN_REPOSITORY = 'https://google.bintray.com/webrtc' -API = 'https://api.bintray.com' -PACKAGE_PATH = 'google/webrtc/google-webrtc' -CONTENT_API = API + '/content/' + PACKAGE_PATH -PACKAGES_API = API + '/packages/' + PACKAGE_PATH -GROUP_ID = 'org/webrtc' -ARTIFACT_ID = 'google-webrtc' -COMMIT_POSITION_REGEX = r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$' -API_TIMEOUT_SECONDS = 10.0 -UPLOAD_TRIES = 3 -# The sleep time is increased exponentially. -UPLOAD_RETRY_BASE_SLEEP_SECONDS = 2.0 -GRADLEW_BIN = os.path.join(CHECKOUT_ROOT, - 'examples/androidtests/third_party/gradle/gradlew') -ADB_BIN = os.path.join(CHECKOUT_ROOT, - 'third_party/android_sdk/public/platform-tools/adb') -AAR_PROJECT_DIR = os.path.join(CHECKOUT_ROOT, 'examples/aarproject') -AAR_PROJECT_GRADLE = os.path.join(AAR_PROJECT_DIR, 'build.gradle') -AAR_PROJECT_APP_GRADLE = os.path.join(AAR_PROJECT_DIR, 'app', 'build.gradle') -AAR_PROJECT_DEPENDENCY = "implementation 'org.webrtc:google-webrtc:1.0.+'" -AAR_PROJECT_VERSION_DEPENDENCY = "implementation 'org.webrtc:google-webrtc:%s'" - - -def _ParseArgs(): - parser = argparse.ArgumentParser(description='Releases WebRTC on Bintray.') - parser.add_argument('--use-goma', - action='store_true', - default=False, - help='Use goma.') - parser.add_argument('--skip-tests', - action='store_true', - default=False, - help='Skips running the tests.') - parser.add_argument( - '--publish', - action='store_true', - default=False, - help='Automatically publishes the library if the tests pass.') - parser.add_argument( - '--build-dir', - default=None, - help='Temporary directory to store the build files. If not specified, ' - 'a new directory will be created.') - parser.add_argument('--verbose', - action='store_true', - default=False, - help='Debug logging.') - return parser.parse_args() - - -def _GetCommitHash(): - commit_hash = subprocess.check_output(['git', 'rev-parse', 'HEAD'], - cwd=CHECKOUT_ROOT).strip() - return commit_hash - - -def _GetCommitPos(): - commit_message = subprocess.check_output( - ['git', 'rev-list', '--format=%B', '--max-count=1', 'HEAD'], - cwd=CHECKOUT_ROOT) - commit_pos_match = re.search(COMMIT_POSITION_REGEX, commit_message, - re.MULTILINE) - if not commit_pos_match: - raise Exception('Commit position not found in the commit message: %s' % - commit_message) - return commit_pos_match.group(1) - - -def _UploadFile(user, password, filename, version, target_file): - # URL is of format: - # ///// - # Example: - # https://api.bintray.com/content/google/webrtc/google-webrtc/1.0.19742/org/webrtc/google-webrtc/1.0.19742/google-webrtc-1.0.19742.aar - - target_dir = version + '/' + GROUP_ID + '/' + ARTIFACT_ID + '/' + version - target_path = target_dir + '/' + target_file - url = CONTENT_API + '/' + target_path - - logging.info('Uploading %s to %s', filename, url) - with open(filename) as fh: - file_data = fh.read() - - for attempt in xrange(UPLOAD_TRIES): - try: - response = requests.put(url, - data=file_data, - auth=(user, password), - timeout=API_TIMEOUT_SECONDS) - break - except requests.exceptions.Timeout as e: - logging.warning('Timeout while uploading: %s', e) - time.sleep(UPLOAD_RETRY_BASE_SLEEP_SECONDS**attempt) - else: - raise Exception('Failed to upload %s' % filename) - - if not response.ok: - raise Exception('Failed to upload %s. Response: %s' % - (filename, response)) - logging.info('Uploaded %s: %s', filename, response) - - -def _GeneratePom(target_file, version, commit): - env = jinja2.Environment(loader=jinja2.PackageLoader('release_aar'), ) - template = env.get_template('pom.jinja') - pom = template.render(version=version, commit=commit) - with open(target_file, 'w') as fh: - fh.write(pom) - - -def _TestAAR(tmp_dir, username, password, version): - """Runs AppRTCMobile tests using the AAR. Returns true if the tests pass.""" - logging.info('Testing library.') - env = jinja2.Environment(loader=jinja2.PackageLoader('release_aar'), ) - - gradle_backup = os.path.join(tmp_dir, 'build.gradle.backup') - app_gradle_backup = os.path.join(tmp_dir, 'app-build.gradle.backup') - - # Make backup copies of the project files before modifying them. - shutil.copy2(AAR_PROJECT_GRADLE, gradle_backup) - shutil.copy2(AAR_PROJECT_APP_GRADLE, app_gradle_backup) - - try: - maven_repository_template = env.get_template('maven-repository.jinja') - maven_repository = maven_repository_template.render( - url=MAVEN_REPOSITORY, username=username, password=password) - - # Append Maven repository to build file to download unpublished files. - with open(AAR_PROJECT_GRADLE, 'a') as gradle_file: - gradle_file.write(maven_repository) - - # Read app build file. - with open(AAR_PROJECT_APP_GRADLE, 'r') as gradle_app_file: - gradle_app = gradle_app_file.read() - - if AAR_PROJECT_DEPENDENCY not in gradle_app: - raise Exception('%s not found in the build file.' % - AAR_PROJECT_DEPENDENCY) - # Set version to the version to be tested. - target_dependency = AAR_PROJECT_VERSION_DEPENDENCY % version - gradle_app = gradle_app.replace(AAR_PROJECT_DEPENDENCY, - target_dependency) - - # Write back. - with open(AAR_PROJECT_APP_GRADLE, 'w') as gradle_app_file: - gradle_app_file.write(gradle_app) - - # Uninstall any existing version of AppRTCMobile. - logging.info( - 'Uninstalling previous AppRTCMobile versions. It is okay for ' - 'these commands to fail if AppRTCMobile is not installed.') - subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc']) - subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc.test']) - - # Run tests. - try: - # First clean the project. - subprocess.check_call([GRADLEW_BIN, 'clean'], cwd=AAR_PROJECT_DIR) - # Then run the tests. - subprocess.check_call([GRADLEW_BIN, 'connectedDebugAndroidTest'], - cwd=AAR_PROJECT_DIR) - except subprocess.CalledProcessError: - logging.exception('Test failure.') - return False # Clean or tests failed - - return True # Tests pass - finally: - # Restore backups. - shutil.copy2(gradle_backup, AAR_PROJECT_GRADLE) - shutil.copy2(app_gradle_backup, AAR_PROJECT_APP_GRADLE) - - -def _PublishAAR(user, password, version, additional_args): - args = { - 'publish_wait_for_secs': 0 # Publish asynchronously. - } - args.update(additional_args) - - url = CONTENT_API + '/' + version + '/publish' - response = requests.post(url, - data=json.dumps(args), - auth=(user, password), - timeout=API_TIMEOUT_SECONDS) - - if not response.ok: - raise Exception('Failed to publish. Response: %s' % response) - - -def _DeleteUnpublishedVersion(user, password, version): - url = PACKAGES_API + '/versions/' + version - response = requests.get(url, - auth=(user, password), - timeout=API_TIMEOUT_SECONDS) - if not response.ok: - raise Exception('Failed to get version info. Response: %s' % response) - - version_info = json.loads(response.content) - if version_info['published']: - logging.info('Version has already been published, not deleting.') - return - - logging.info('Deleting unpublished version.') - response = requests.delete(url, - auth=(user, password), - timeout=API_TIMEOUT_SECONDS) - if not response.ok: - raise Exception('Failed to delete version. Response: %s' % response) - - -def ReleaseAar(use_goma, skip_tests, publish, build_dir): - version = '1.0.' + _GetCommitPos() - commit = _GetCommitHash() - logging.info('Releasing AAR version %s with hash %s', version, commit) - - user = os.environ.get('BINTRAY_USER', None) - api_key = os.environ.get('BINTRAY_API_KEY', None) - if not user or not api_key: - raise Exception( - 'Environment variables BINTRAY_USER and BINTRAY_API_KEY ' - 'must be defined.') - - # If build directory is not specified, create a temporary directory. - use_tmp_dir = not build_dir - if use_tmp_dir: - build_dir = tempfile.mkdtemp() - - try: - base_name = ARTIFACT_ID + '-' + version - aar_file = os.path.join(build_dir, base_name + '.aar') - third_party_licenses_file = os.path.join(build_dir, 'LICENSE.md') - pom_file = os.path.join(build_dir, base_name + '.pom') - - logging.info('Building at %s', build_dir) - BuildAar(ARCHS, - aar_file, - use_goma=use_goma, - ext_build_dir=os.path.join(build_dir, 'aar-build')) - _GeneratePom(pom_file, version, commit) - - _UploadFile(user, api_key, aar_file, version, base_name + '.aar') - _UploadFile(user, api_key, third_party_licenses_file, version, - 'THIRD_PARTY_LICENSES.md') - _UploadFile(user, api_key, pom_file, version, base_name + '.pom') - - tests_pass = skip_tests or _TestAAR(build_dir, user, api_key, version) - if not tests_pass: - logging.info('Discarding library.') - _PublishAAR(user, api_key, version, {'discard': True}) - _DeleteUnpublishedVersion(user, api_key, version) - raise Exception('Test failure. Discarded library.') - - if publish: - logging.info('Publishing library.') - _PublishAAR(user, api_key, version, {}) - else: - logging.info( - 'Note: The library has not not been published automatically.' - ' Please do so manually if desired.') - finally: - if use_tmp_dir: - shutil.rmtree(build_dir, True) - - -def main(): - args = _ParseArgs() - logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) - ReleaseAar(args.use_goma, args.skip_tests, args.publish, args.build_dir) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools_webrtc/android/test_aar.py b/tools_webrtc/android/test_aar.py new file mode 100755 index 0000000000..cb8ad121a2 --- /dev/null +++ b/tools_webrtc/android/test_aar.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. +"""Script for building and testing WebRTC AAR. +""" + +import argparse +import logging +import os +import re +import shutil +import subprocess +import sys +import tempfile + +SCRIPT_DIR = os.path.dirname(os.path.realpath(sys.argv[0])) +CHECKOUT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir)) + +sys.path.append(os.path.join(CHECKOUT_ROOT, 'tools_webrtc')) +from android.build_aar import BuildAar + +ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'] +ARTIFACT_ID = 'google-webrtc' +COMMIT_POSITION_REGEX = r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$' +GRADLEW_BIN = os.path.join(CHECKOUT_ROOT, + 'examples/androidtests/third_party/gradle/gradlew') +ADB_BIN = os.path.join(CHECKOUT_ROOT, + 'third_party/android_sdk/public/platform-tools/adb') +AAR_PROJECT_DIR = os.path.join(CHECKOUT_ROOT, 'examples/aarproject') + + +def _ParseArgs(): + parser = argparse.ArgumentParser(description='Releases WebRTC on Bintray.') + parser.add_argument('--use-goma', + action='store_true', + default=False, + help='Use goma.') + parser.add_argument('--skip-tests', + action='store_true', + default=False, + help='Skips running the tests.') + parser.add_argument( + '--build-dir', + default=None, + help='Temporary directory to store the build files. If not specified, ' + 'a new directory will be created.') + parser.add_argument('--verbose', + action='store_true', + default=False, + help='Debug logging.') + return parser.parse_args() + + +def _GetCommitHash(): + commit_hash = subprocess.check_output( + ['git', 'rev-parse', 'HEAD'], cwd=CHECKOUT_ROOT).decode('UTF-8').strip() + return commit_hash + + +def _GetCommitPos(): + commit_message = subprocess.check_output( + ['git', 'rev-list', '--format=%B', '--max-count=1', 'HEAD'], + cwd=CHECKOUT_ROOT).decode('UTF-8') + commit_pos_match = re.search(COMMIT_POSITION_REGEX, commit_message, + re.MULTILINE) + if not commit_pos_match: + raise Exception('Commit position not found in the commit message: %s' % + commit_message) + return commit_pos_match.group(1) + + +def _TestAAR(build_dir): + """Runs AppRTCMobile tests using the AAR. Returns true if the tests pass.""" + logging.info('Testing library.') + + # Uninstall any existing version of AppRTCMobile. + logging.info( + 'Uninstalling previous AppRTCMobile versions. It is okay for ' + 'these commands to fail if AppRTCMobile is not installed.') + subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc']) + subprocess.call([ADB_BIN, 'uninstall', 'org.appspot.apprtc.test']) + + # Run tests. + try: + # First clean the project. + subprocess.check_call([GRADLEW_BIN, 'clean'], cwd=AAR_PROJECT_DIR) + # Then run the tests. + subprocess.check_call([ + GRADLEW_BIN, + 'connectedDebugAndroidTest', + '-PaarDir=' + os.path.abspath(build_dir)], + cwd=AAR_PROJECT_DIR) + except subprocess.CalledProcessError: + logging.exception('Test failure.') + return False # Clean or tests failed + + return True # Tests pass + + +def BuildAndTestAar(use_goma, skip_tests, build_dir): + version = '1.0.' + _GetCommitPos() + commit = _GetCommitHash() + logging.info( + 'Building and Testing AAR version %s with hash %s', version, commit) + + # If build directory is not specified, create a temporary directory. + use_tmp_dir = not build_dir + if use_tmp_dir: + build_dir = tempfile.mkdtemp() + + try: + base_name = ARTIFACT_ID + '-' + version + aar_file = os.path.join(build_dir, base_name + '.aar') + + logging.info('Building at %s', build_dir) + BuildAar(ARCHS, + aar_file, + use_goma=use_goma, + ext_build_dir=os.path.join(build_dir, 'aar-build')) + + tests_pass = skip_tests or _TestAAR(build_dir) + if not tests_pass: + raise Exception('Test failure.') + + logging.info('Test success.') + + finally: + if use_tmp_dir: + shutil.rmtree(build_dir, True) + + +def main(): + args = _ParseArgs() + logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) + BuildAndTestAar(args.use_goma, args.skip_tests, args.build_dir) + + +if __name__ == '__main__': + sys.exit(main())