blob: 14e9ec67c71c6d5053456eb9908400ff2b205c03 [file] [log] [blame] [edit]
#!/usr/bin/env python3
# Copyright (C) 2021 The Android Open Source Project
#
# 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.
"""Packages prebuilts and SDK sources for GitHub releases.
Usage: ./tools/release/package-github-release-artifacts v20.0
IMPORTANT: This script must be run from the git tag being packaged. The SDK
source files are generated from the current working directory, so running this
script from a different commit will result in mismatched SDK sources.
This will generate:
- One .zip file for every os-arch combo (e.g. android-arm.zip)
- SDK source zips (perfetto-cpp-sdk-src.zip, perfetto-c-sdk-src.zip)
All files will be placed into /tmp/perfetto-v20.0-github-release/ .
"""
import argparse
import subprocess
import os
import sys
import tempfile
import shutil
def exec(*args):
print(' '.join(args))
subprocess.check_call(args)
def get_repo_root():
"""Returns the root directory of the Perfetto repository."""
script_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.abspath(os.path.join(script_dir, '..', '..'))
def verify_git_state(expected_version):
"""Verifies git is on the correct tag with no uncommitted changes."""
warnings = []
# Check for uncommitted changes
try:
result = subprocess.run(['git', 'status', '--porcelain'],
capture_output=True,
text=True)
if result.returncode == 0 and result.stdout.strip():
warnings.append(
f'Working directory has uncommitted changes:\n{result.stdout}')
except Exception as e:
warnings.append(f'Could not check git status: {e}')
# Check current tag
try:
result = subprocess.run(['git', 'describe', '--exact-match', '--tags'],
capture_output=True,
text=True)
if result.returncode == 0:
current_tag = result.stdout.strip()
if current_tag != expected_version:
warnings.append(
f'On tag {current_tag}, but packaging {expected_version}')
else:
warnings.append(f'Not on a git tag (expected {expected_version})')
except Exception as e:
warnings.append(f'Could not check git tag: {e}')
if warnings:
print('WARNING: SDK sources may not match the release tag:')
for warning in warnings:
print(f' - {warning}')
return input('\nContinue anyway? [y/N] ').lower().strip() in ['y', 'yes']
print(f'✓ On tag {expected_version} with clean working directory')
return True
def download_sdk_sources(tmpdir, version):
"""Downloads SDK source zips from GCS."""
sdk_zips = [
'perfetto-cpp-sdk-src.zip',
'perfetto-c-sdk-src.zip',
]
print('\n--- Downloading SDK amalgamated sources from GCS ---')
for zip_name in sdk_zips:
url = f'gs://perfetto-luci-artifacts/{version}/sdk/{zip_name}'
exec('gsutil', 'cp', url, os.path.join(tmpdir, zip_name))
return sdk_zips
def main():
parser = argparse.ArgumentParser(epilog='Example: %s v19.0' % __file__)
parser.add_argument('version', help='Version tag (e.g., v20.0)')
args = parser.parse_args()
# Verify we're on the correct tag with no uncommitted changes
if not verify_git_state(args.version):
print('Aborted.')
return 1
tmpdir = '/tmp/perfetto-%s-github-release' % args.version
src = 'gs://perfetto-luci-artifacts/%s/' % args.version
os.makedirs(tmpdir, exist_ok=True)
# Download and package prebuilts
print('--- Downloading prebuilts from GCS ---')
os.chdir(tmpdir)
exec('gcloud', 'storage', 'rsync', '--recursive', '--checksums-only', src,
tmpdir + '/')
zips = []
for arch in os.listdir(tmpdir):
if arch == 'sdk' or not os.path.isdir(os.path.join(tmpdir, arch)):
continue
exec('zip', '-9r', '%s.zip' % arch, arch)
zips.append(arch + '.zip')
# Download SDK source zips
sdk_zips = download_sdk_sources(tmpdir, args.version)
zips.extend(sdk_zips)
print('')
print('=' * 70)
print('%d zip files saved in %s' % (len(zips), tmpdir))
print('Prebuilt binaries: %d' % (len(zips) - len(sdk_zips)))
print('SDK sources: %d' % len(sdk_zips))
print('Files: %s' % ', '.join(sorted(zips)))
print('=' * 70)
if __name__ == '__main__':
sys.exit(main())