From 4e920f2b04d61e2e54a080423bd766c5df1a97c8 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 12 Apr 2019 22:07:13 +0200 Subject: [PATCH] ci: use a custom android sdk manager with pinning and mirroring --- src/ci/docker/arm-android/Dockerfile | 16 +- src/ci/docker/arm-android/android-sdk.lock | 6 + src/ci/docker/scripts/android-sdk-manager.py | 190 +++++++++++++++++++ src/ci/docker/scripts/android-sdk.sh | 82 +++----- 4 files changed, 225 insertions(+), 69 deletions(-) create mode 100644 src/ci/docker/arm-android/android-sdk.lock create mode 100755 src/ci/docker/scripts/android-sdk-manager.py mode change 100644 => 100755 src/ci/docker/scripts/android-sdk.sh diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index bbf700ae233..b934d1ce971 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -7,23 +7,21 @@ COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r15c-linux-x86_64.zip arm 14 -# Note: -# Do not upgrade to `openjdk-9-jre-headless`, as it will cause certificate error -# when installing the Android SDK (see PR #45193). This is unfortunate, but -# every search result suggested either disabling HTTPS or replacing JDK 9 by -# JDK 8 as the solution (e.g. https://stackoverflow.com/q/41421340). :| RUN dpkg --add-architecture i386 && \ apt-get update && \ apt-get install -y --no-install-recommends \ libgl1-mesa-glx \ libpulse0 \ libstdc++6:i386 \ - openjdk-8-jre-headless \ - tzdata + openjdk-9-jre-headless \ + tzdata \ + wget \ + python3 COPY scripts/android-sdk.sh /scripts/ -RUN . /scripts/android-sdk.sh && \ - download_and_create_avd 4333796 armeabi-v7a 18 5264690 +COPY scripts/android-sdk-manager.py /scripts/ +COPY arm-android/android-sdk.lock /android/sdk/android-sdk.lock +RUN /scripts/android-sdk.sh ENV PATH=$PATH:/android/sdk/emulator ENV PATH=$PATH:/android/sdk/tools diff --git a/src/ci/docker/arm-android/android-sdk.lock b/src/ci/docker/arm-android/android-sdk.lock new file mode 100644 index 00000000000..a1be8a4346b --- /dev/null +++ b/src/ci/docker/arm-android/android-sdk.lock @@ -0,0 +1,6 @@ +emulator emulator-linux-5264690.zip 48c1cda2bdf3095d9d9d5c010fbfb3d6d673e3ea +patcher;v4 3534162-studio.sdk-patcher.zip 046699c5e2716ae11d77e0bad814f7f33fab261e +platform-tools platform-tools_r28.0.2-linux.zip 46a4c02a9b8e4e2121eddf6025da3c979bf02e28 +platforms;android-18 android-18_r03.zip e6b09b3505754cbbeb4a5622008b907262ee91cb +system-images;android-18;default;armeabi-v7a sys-img/android/armeabi-v7a-18_r05.zip 580b583720f7de671040d5917c8c9db0c7aa03fd +tools sdk-tools-linux-4333796.zip 8c7c28554a32318461802c1291d76fccfafde054 diff --git a/src/ci/docker/scripts/android-sdk-manager.py b/src/ci/docker/scripts/android-sdk-manager.py new file mode 100755 index 00000000000..7c9a8b82e92 --- /dev/null +++ b/src/ci/docker/scripts/android-sdk-manager.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +# Simpler reimplementation of Android's sdkmanager +# Extra features of this implementation are pinning and mirroring + +# These URLs are the Google repositories containing the list of available +# packages and their versions. The list has been generated by listing the URLs +# fetched while executing `tools/bin/sdkmanager --list` +BASE_REPOSITORY = "https://dl.google.com/android/repository/" +REPOSITORIES = [ + "sys-img/android/sys-img2-1.xml", + "sys-img/android-wear/sys-img2-1.xml", + "sys-img/android-wear-cn/sys-img2-1.xml", + "sys-img/android-tv/sys-img2-1.xml", + "sys-img/google_apis/sys-img2-1.xml", + "sys-img/google_apis_playstore/sys-img2-1.xml", + "addon2-1.xml", + "glass/addon2-1.xml", + "extras/intel/addon2-1.xml", + "repository2-1.xml", +] + +# Available hosts: linux, macosx and windows +HOST_OS = "linux" + +# Mirroring options +MIRROR_BUCKET = "rust-lang-ci2" +MIRROR_BASE_DIR = "rust-ci-mirror/android/" + +import argparse +import hashlib +import os +import subprocess +import sys +import tempfile +import urllib.request +import xml.etree.ElementTree as ET + +class Package: + def __init__(self, path, url, sha1, deps=None): + if deps is None: + deps = [] + self.path = path.strip() + self.url = url.strip() + self.sha1 = sha1.strip() + self.deps = deps + + def download(self, base_url): + _, file = tempfile.mkstemp() + url = base_url + self.url + subprocess.run(["curl", "-o", file, url], check=True) + # Ensure there are no hash mismatches + with open(file, "rb") as f: + sha1 = hashlib.sha1(f.read()).hexdigest() + if sha1 != self.sha1: + raise RuntimeError( + "hash mismatch for package " + self.path + ": " + + sha1 + " vs " + self.sha1 + " (known good)" + ) + return file + + def __repr__(self): + return " /dev/null - yes | sdkmanager platform-tools \ - "platforms;android-$api" \ - "system-images;android-$api;default;$abi" > /dev/null -} - -download_emulator() { - # Download a pinned version of the emulator since upgrades can cause issues - curl -fo emulator.zip "https://dl.google.com/android/repository/emulator-linux-$1.zip" - rm -rf "${ANDROID_HOME}/emulator" - unzip -q emulator.zip -d "${ANDROID_HOME}" - rm -f emulator.zip -} - -create_avd() { - abi=$1 - api=$2 - - # See https://developer.android.com/studio/command-line/avdmanager.html for - # usage of `avdmanager`. - echo no | avdmanager create avd \ - -n "$abi-$api" \ - -k "system-images;android-$api;default;$abi" -} - -download_and_create_avd() { - download_sdk $1 - download_sysimage $2 $3 - create_avd $2 $3 - download_emulator $4 -} - -# Usage: +# To add a new packages to the SDK or to update an existing one you need to +# run the command: # -# download_and_create_avd 4333796 armeabi-v7a 18 5264690 +# android-sdk-manager.py add-to-lockfile $LOCKFILE # -# 4333796 => -# SDK tool version. -# Copy from https://developer.android.com/studio/index.html#command-tools -# armeabi-v7a => -# System image ABI -# 18 => -# Android API Level (18 = Android 4.3 = Jelly Bean MR2) -# 5264690 => -# Android Emulator version. -# Copy from the "build_id" in the `/android/sdk/emulator/emulator -version` output +# Then, after every lockfile update the mirror has to be synchronized as well: +# +# android-sdk-manager.py update-mirror $LOCKFILE +# +/scripts/android-sdk-manager.py install "${LOCKFILE}" "${ANDROID_HOME}" + +details=$(cat "${LOCKFILE}" \ + | grep system-images \ + | sed 's/^system-images;android-\([0-9]\+\);default;\([a-z0-9-]\+\) /\1 \2 /g') +api="$(echo "${details}" | awk '{print($1)}')" +abi="$(echo "${details}" | awk '{print($2)}')" + +# See https://developer.android.com/studio/command-line/avdmanager.html for +# usage of `avdmanager`. +echo no | avdmanager create avd \ + -n "$abi-$api" \ + -k "system-images;android-$api;default;$abi" +