Add testing and auto-publish features to release_aar.py.
Bug: webrtc:8365 Change-Id: I6dda3773d62ea37d371933691144499ba17898d7 Reviewed-on: https://webrtc-review.googlesource.com/7614 Reviewed-by: Patrik Höglund <phoglund@webrtc.org> Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20274}
This commit is contained in:
committed by
Commit Bot
parent
2a5e7906a9
commit
201509b1c1
@ -15,6 +15,7 @@ this script for authentication.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -37,20 +38,35 @@ from android.build_aar import BuildAar
|
|||||||
|
|
||||||
|
|
||||||
ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
|
ARCHS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
|
||||||
REPOSITORY_API = 'https://api.bintray.com/content/google/webrtc/google-webrtc'
|
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'
|
GROUP_ID = 'org/webrtc'
|
||||||
ARTIFACT_ID = 'google-webrtc'
|
ARTIFACT_ID = 'google-webrtc'
|
||||||
COMMIT_POSITION_REGEX = r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$'
|
COMMIT_POSITION_REGEX = r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$'
|
||||||
UPLOAD_TIMEOUT_SECONDS = 10.0
|
API_TIMEOUT_SECONDS = 10.0
|
||||||
UPLOAD_TRIES = 3
|
UPLOAD_TRIES = 3
|
||||||
# The sleep time is increased exponentially.
|
# The sleep time is increased exponentially.
|
||||||
UPLOAD_RETRY_BASE_SLEEP_SECONDS = 2.0
|
UPLOAD_RETRY_BASE_SLEEP_SECONDS = 2.0
|
||||||
|
GRADLEW_BIN = os.path.join(CHECKOUT_ROOT,
|
||||||
|
'examples/androidtests/third_party/gradle/gradlew')
|
||||||
|
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():
|
def _ParseArgs():
|
||||||
parser = argparse.ArgumentParser(description='Releases WebRTC on Bintray.')
|
parser = argparse.ArgumentParser(description='Releases WebRTC on Bintray.')
|
||||||
parser.add_argument('--use-goma', action='store_true', default=False,
|
parser.add_argument('--use-goma', action='store_true', default=False,
|
||||||
help='Use goma.')
|
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('--verbose', action='store_true', default=False,
|
parser.add_argument('--verbose', action='store_true', default=False,
|
||||||
help='Debug logging.')
|
help='Debug logging.')
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
@ -82,7 +98,7 @@ def _UploadFile(user, password, filename, version, target_file):
|
|||||||
|
|
||||||
target_dir = version + '/' + GROUP_ID + '/' + ARTIFACT_ID + '/' + version
|
target_dir = version + '/' + GROUP_ID + '/' + ARTIFACT_ID + '/' + version
|
||||||
target_path = target_dir + '/' + target_file
|
target_path = target_dir + '/' + target_file
|
||||||
url = REPOSITORY_API + '/' + target_path
|
url = CONTENT_API + '/' + target_path
|
||||||
|
|
||||||
logging.info('Uploading %s to %s', filename, url)
|
logging.info('Uploading %s to %s', filename, url)
|
||||||
with open(filename) as fh:
|
with open(filename) as fh:
|
||||||
@ -91,7 +107,7 @@ def _UploadFile(user, password, filename, version, target_file):
|
|||||||
for attempt in xrange(UPLOAD_TRIES):
|
for attempt in xrange(UPLOAD_TRIES):
|
||||||
try:
|
try:
|
||||||
response = requests.put(url, data=file_data, auth=(user, password),
|
response = requests.put(url, data=file_data, auth=(user, password),
|
||||||
timeout=UPLOAD_TIMEOUT_SECONDS)
|
timeout=API_TIMEOUT_SECONDS)
|
||||||
break
|
break
|
||||||
except requests.exceptions.Timeout as e:
|
except requests.exceptions.Timeout as e:
|
||||||
logging.warning('Timeout while uploading: %s', e)
|
logging.warning('Timeout while uploading: %s', e)
|
||||||
@ -114,7 +130,96 @@ def _GeneratePom(target_file, version, commit):
|
|||||||
fh.write(pom)
|
fh.write(pom)
|
||||||
|
|
||||||
|
|
||||||
def ReleaseAar(use_goma):
|
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)
|
||||||
|
|
||||||
|
# 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):
|
||||||
version = '1.0.' + _GetCommitPos()
|
version = '1.0.' + _GetCommitPos()
|
||||||
commit = _GetCommitHash()
|
commit = _GetCommitHash()
|
||||||
logging.info('Releasing AAR version %s with hash %s', version, commit)
|
logging.info('Releasing AAR version %s with hash %s', version, commit)
|
||||||
@ -143,17 +248,28 @@ def ReleaseAar(use_goma):
|
|||||||
_UploadFile(user, api_key, third_party_licenses_file, version,
|
_UploadFile(user, api_key, third_party_licenses_file, version,
|
||||||
'THIRD_PARTY_LICENSES.md')
|
'THIRD_PARTY_LICENSES.md')
|
||||||
_UploadFile(user, api_key, pom_file, version, base_name + '.pom')
|
_UploadFile(user, api_key, pom_file, version, base_name + '.pom')
|
||||||
|
|
||||||
|
tests_pass = skip_tests or _TestAAR(tmp_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:
|
finally:
|
||||||
shutil.rmtree(tmp_dir, True)
|
shutil.rmtree(tmp_dir, True)
|
||||||
|
|
||||||
logging.info('Library successfully uploaded. Please test and publish it on '
|
|
||||||
'Bintray.')
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = _ParseArgs()
|
args = _ParseArgs()
|
||||||
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
|
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
|
||||||
ReleaseAar(args.use_goma)
|
ReleaseAar(args.use_goma, args.skip_tests, args.publish)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
11
tools_webrtc/android/templates/maven-repository.jinja
Normal file
11
tools_webrtc/android/templates/maven-repository.jinja
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url '{{ url }}'
|
||||||
|
credentials {
|
||||||
|
username '{{ username }}'
|
||||||
|
password '{{ password }}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user