build_android_app.py (9992B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 """ 5 Apply some defaults and minor modifications to the jobs defined in the 6 build-apk and build-bundle kinds. 7 """ 8 9 from taskgraph.transforms.base import TransformSequence 10 from taskgraph.util import path 11 12 from android_taskgraph.build_config import get_variant 13 14 transforms = TransformSequence() 15 16 17 @transforms.add 18 def add_common_config(config, tasks): 19 for task in tasks: 20 fetches = task.setdefault("fetches", {}) 21 fetches["toolchain"] = [ 22 "android-sdk-linux", 23 "linux64-embedded-uniffi-bindgen", 24 "linux64-nimbus-fml", 25 "android-gradle-dependencies", 26 "linux64-jdk", 27 ] 28 fetches["build-fat-aar"] = [ 29 "target.maven.zip", 30 {"artifact": "mozconfig", "extract": False}, 31 ] 32 33 run = task.setdefault("run", {}) 34 run["using"] = "gradlew" 35 run["use-caches"] = False 36 37 treeherder = task.setdefault("treeherder", {}) 38 treeherder["kind"] = "build" 39 treeherder["tier"] = 1 40 41 task["worker-type"] = "b-linux-docker-amd" 42 43 worker = task.setdefault("worker", {}) 44 worker["docker-image"] = {} 45 worker["docker-image"]["in-tree"] = "android-components" 46 worker["max-run-time"] = 7200 47 worker["chain-of-trust"] = True 48 worker.setdefault("env", {}).setdefault( 49 "MOZCONFIG", "/builds/worker/fetches/mozconfig" 50 ) 51 build_fat_aar = config.kind_dependencies_tasks[ 52 task["dependencies"]["build-fat-aar"] 53 ] 54 if build_fat_aar.attributes.get("shippable", False): 55 worker["env"].setdefault( 56 "MOZ_UPDATE_CHANNEL", 57 build_fat_aar.attributes.get( 58 "update-channel", "nightly-{}".format(config.params["project"]) 59 ), 60 ) 61 62 yield task 63 64 65 @transforms.add 66 def add_variant_config(config, tasks): 67 for task in tasks: 68 attributes = task.setdefault("attributes", {}) 69 if not attributes.get("build-type"): 70 attributes["build-type"] = task["name"] 71 yield task 72 73 74 @transforms.add 75 def add_shippable_secrets(config, tasks): 76 for task in tasks: 77 secrets = task["run"].setdefault("secrets", []) 78 dummy_secrets = task["run"].setdefault("dummy-secrets", []) 79 80 if ( 81 task.pop("include-shippable-secrets", False) 82 and config.params["level"] == "3" 83 ): 84 secrets.extend([ 85 { 86 "key": key, 87 "name": _get_secret_index(task["name"]), 88 "path": target_file, 89 } 90 for key, target_file in _get_secrets_keys_and_target_files(task) 91 ]) 92 else: 93 dummy_secrets.extend([ 94 { 95 "content": fake_value, 96 "path": target_file, 97 } 98 for fake_value, target_file in ( 99 ("faketoken", ".adjust_token"), 100 ("faketoken", ".mls_token"), 101 ("https://fake@sentry.prod.mozaws.net/368", ".sentry_token"), 102 ) 103 ]) 104 105 yield task 106 107 108 def _get_secrets_keys_and_target_files(task): 109 secrets = [ 110 ("adjust", ".adjust_token"), 111 ("sentry_dsn", ".sentry_token"), 112 ("mls", ".mls_token"), 113 ("nimbus_url", ".nimbus"), 114 ] 115 116 if task["name"].startswith("fenix-"): 117 gradle_build_type = task["run"]["gradle-build-type"] 118 secrets.extend([ 119 ( 120 "firebase", 121 f"app/src/{gradle_build_type}/res/values/firebase.xml", 122 ), 123 ("wallpaper_url", ".wallpaper_url"), 124 ("pocket_consumer_key", ".pocket_consumer_key"), 125 ]) 126 127 return secrets 128 129 130 def _get_secret_index(task_name): 131 product_name = task_name.split("-")[0] 132 secret_name = task_name[len(product_name) + 1 :] 133 secret_project_name = ( 134 "focus-android" if product_name in ("focus", "klar") else product_name 135 ) 136 return f"project/mobile/firefox-android/{secret_project_name}/{secret_name}" 137 138 139 @transforms.add 140 def build_pre_gradle_command(config, tasks): 141 for task in tasks: 142 source_project_name = task["source-project-name"] 143 pre_gradlew = task["run"].setdefault("pre-gradlew", []) 144 pre_gradlew.append(["cd", path.join("mobile", "android", source_project_name)]) 145 146 yield task 147 148 149 @transforms.add 150 def build_gradle_command(config, tasks): 151 for task in tasks: 152 gradle_build_type = task["run"].get("gradle-build-type") 153 gradle_build_name = task["run"].get("gradle-build-name") 154 155 variant_name = "" 156 if gradle_build_type and gradle_build_name: 157 variant_name = get_variant(gradle_build_type, gradle_build_name)[ 158 "name" 159 ].capitalize() 160 161 package_command = task["run"].pop("gradle-package-command", "assemble") 162 gradle_command = [ 163 "clean", 164 f"{package_command}{variant_name}", 165 ] 166 167 if task["run"].pop("track-apk-size", False): 168 gradle_command.append(f"apkSize{variant_name}") 169 170 task["run"]["gradlew"] = gradle_command 171 172 yield task 173 174 175 @transforms.add 176 def add_baseline_profile_path(config, tasks): 177 for task in tasks: 178 baseline_profile_path = task["run"].pop("baseline-profile-path", "") 179 if baseline_profile_path: 180 task["run"]["gradlew"].append( 181 f"-PbaselineProfilePath={baseline_profile_path}" 182 ) 183 184 yield task 185 186 187 @transforms.add 188 def extra_gradle_options(config, tasks): 189 for task in tasks: 190 for extra in task["run"].pop("gradle-extra-options", []): 191 task["run"]["gradlew"].append(extra) 192 193 yield task 194 195 196 @transforms.add 197 def add_test_build_type(config, tasks): 198 for task in tasks: 199 test_build_type = task["run"].pop("test-build-type", "") 200 if test_build_type: 201 task["run"]["gradlew"].append(f"-PtestBuildType={test_build_type}") 202 yield task 203 204 205 @transforms.add 206 def add_disable_optimization(config, tasks): 207 for task in tasks: 208 if task.pop("disable-optimization", False): 209 task["run"]["gradlew"].append("-PdisableOptimization") 210 yield task 211 212 213 @transforms.add 214 def add_nightly_version(config, tasks): 215 for task in tasks: 216 if task.pop("include-nightly-version", False): 217 task["run"]["gradlew"].extend([ 218 # We only set the `official` flag here. The actual version name will be determined 219 # by Gradle (depending on the Gecko/A-C version being used) 220 "-Pofficial" 221 ]) 222 yield task 223 224 225 @transforms.add 226 def add_release_version(config, tasks): 227 for task in tasks: 228 if task.pop("include-release-version", False): 229 task["run"]["gradlew"].extend([ 230 "-PversionName={}".format(config.params["version"]), 231 "-Pofficial", 232 ]) 233 yield task 234 235 236 @transforms.add 237 def add_artifacts(config, tasks): 238 for task in tasks: 239 gradle_build_type = task["run"].pop("gradle-build-type", "") 240 gradle_build_name = task["run"].pop("gradle-build-name", "") 241 gradle_build = task["run"].pop("gradle-build", "") 242 source_project_name = task.pop("source-project-name") 243 244 if not gradle_build_type or not gradle_build_name or not gradle_build: 245 yield task 246 continue 247 248 variant_config = get_variant(gradle_build_type, gradle_build_name) 249 artifacts = task.setdefault("worker", {}).setdefault("artifacts", []) 250 251 task["attributes"]["apks"] = apks = {} 252 253 if "apk-artifact-template" in task: 254 artifact_template = task.pop("apk-artifact-template") 255 256 # Fenix has no product flavor, so APK paths don't include it. 257 if gradle_build == "fenix": 258 apk_path = gradle_build_type 259 else: 260 apk_path = f"{gradle_build}/{gradle_build_type}" 261 262 for apk in variant_config["apks"]: 263 apk_name = artifact_template["name"].format( 264 gradle_build=gradle_build, **apk 265 ) 266 artifacts.append({ 267 "type": artifact_template["type"], 268 "name": apk_name, 269 "path": artifact_template["path"].format( 270 gradle_build_type=gradle_build_type, 271 gradle_build=gradle_build, 272 apk_path=apk_path, 273 source_project_name=source_project_name, 274 **apk, 275 ), 276 }) 277 apks[apk["abi"]] = { 278 "name": apk_name, 279 } 280 elif "aab-artifact-template" in task: 281 variant_name = variant_config["name"] 282 artifact_template = task.pop("aab-artifact-template") 283 284 # Fenix has no product flavor, so AAB filenames don't include it. 285 if gradle_build == "fenix": 286 aab_filename = f"app-{gradle_build_type}.aab" 287 else: 288 aab_filename = f"app-{gradle_build}-{gradle_build_type}.aab" 289 290 artifacts.append({ 291 "type": artifact_template["type"], 292 "name": artifact_template["name"], 293 "path": artifact_template["path"].format( 294 gradle_build_type=gradle_build_type, 295 gradle_build=gradle_build, 296 source_project_name=source_project_name, 297 variant_name=variant_name, 298 aab_filename=aab_filename, 299 ), 300 }) 301 task["attributes"]["aab"] = artifact_template["name"] 302 303 yield task