summaryrefslogtreecommitdiffstats
path: root/taskcluster/android_taskgraph/job.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--taskcluster/android_taskgraph/job.py208
1 files changed, 208 insertions, 0 deletions
diff --git a/taskcluster/android_taskgraph/job.py b/taskcluster/android_taskgraph/job.py
new file mode 100644
index 0000000000..520b8788a3
--- /dev/null
+++ b/taskcluster/android_taskgraph/job.py
@@ -0,0 +1,208 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+from pipes import quote as shell_quote
+
+from gecko_taskgraph.transforms.job import configure_taskdesc_for_run, run_job_using
+from taskgraph.util import path
+from taskgraph.util.schema import Schema, taskref_or_string
+from voluptuous import Optional, Required
+
+secret_schema = {
+ Required("name"): str,
+ Required("path"): str,
+ Required("key"): str,
+ Optional("json"): bool,
+ Optional("decode"): bool,
+}
+
+dummy_secret_schema = {
+ Required("content"): str,
+ Required("path"): str,
+ Optional("json"): bool,
+}
+
+gradlew_schema = Schema(
+ {
+ Required("using"): "gradlew",
+ Optional("pre-gradlew"): [[str]],
+ Required("gradlew"): [str],
+ Optional("post-gradlew"): [[str]],
+ # Base work directory used to set up the task.
+ Required("workdir"): str,
+ Optional("use-caches"): bool,
+ Optional("secrets"): [secret_schema],
+ Optional("dummy-secrets"): [dummy_secret_schema],
+ }
+)
+
+run_commands_schema = Schema(
+ {
+ Required("using"): "run-commands",
+ Optional("pre-commands"): [[str]],
+ Required("commands"): [[taskref_or_string]],
+ Required("workdir"): str,
+ Optional("use-caches"): bool,
+ Optional("secrets"): [secret_schema],
+ Optional("dummy-secrets"): [dummy_secret_schema],
+ }
+)
+
+
+@run_job_using("docker-worker", "run-commands", schema=run_commands_schema)
+def configure_run_commands_schema(config, job, taskdesc):
+ run = job["run"]
+ pre_commands = run.pop("pre-commands", [])
+ pre_commands += [
+ _generate_dummy_secret_command(secret)
+ for secret in run.pop("dummy-secrets", [])
+ ]
+ pre_commands += [
+ _generate_secret_command(secret) for secret in run.get("secrets", [])
+ ]
+
+ all_commands = pre_commands + run.pop("commands", [])
+
+ run["command"] = _convert_commands_to_string(all_commands)
+ _inject_secrets_scopes(run, taskdesc)
+ _set_run_task_attributes(job)
+ configure_taskdesc_for_run(config, job, taskdesc, job["worker"]["implementation"])
+
+
+@run_job_using("docker-worker", "gradlew", schema=gradlew_schema)
+def configure_gradlew(config, job, taskdesc):
+ run = job["run"]
+ worker = taskdesc["worker"] = job["worker"]
+
+ fetches_dir = "/builds/worker/fetches"
+ topsrc_dir = "/builds/worker/checkouts/gecko"
+ worker.setdefault("env", {}).update(
+ {
+ "ANDROID_SDK_ROOT": path.join(fetches_dir, "android-sdk-linux"),
+ "GRADLE_USER_HOME": path.join(
+ topsrc_dir, "mobile/android/gradle/dotgradle-online"
+ ),
+ "MOZ_BUILD_DATE": config.params["moz_build_date"],
+ }
+ )
+ worker["env"].setdefault(
+ "MOZCONFIG",
+ path.join(
+ topsrc_dir,
+ "mobile/android/config/mozconfigs/android-arm/nightly-android-lints",
+ ),
+ )
+ worker["env"].setdefault(
+ "MOZ_ANDROID_FAT_AAR_ARCHITECTURES", "armeabi-v7a,arm64-v8a,x86,x86_64"
+ )
+
+ dummy_secrets = [
+ _generate_dummy_secret_command(secret)
+ for secret in run.pop("dummy-secrets", [])
+ ]
+ secrets = [_generate_secret_command(secret) for secret in run.get("secrets", [])]
+ worker["env"].update(
+ {
+ "PRE_GRADLEW": _convert_commands_to_string(run.pop("pre-gradlew", [])),
+ "GET_SECRETS": _convert_commands_to_string(dummy_secrets + secrets),
+ "GRADLEW_ARGS": " ".join(run.pop("gradlew")),
+ "POST_GRADLEW": _convert_commands_to_string(run.pop("post-gradlew", [])),
+ }
+ )
+ run[
+ "command"
+ ] = "/builds/worker/checkouts/gecko/taskcluster/scripts/builder/build-android.sh"
+ _inject_secrets_scopes(run, taskdesc)
+ _set_run_task_attributes(job)
+ configure_taskdesc_for_run(config, job, taskdesc, job["worker"]["implementation"])
+
+
+def _generate_secret_command(secret):
+ secret_command = [
+ "/builds/worker/checkouts/gecko/taskcluster/scripts/get-secret.py",
+ "-s",
+ secret["name"],
+ "-k",
+ secret["key"],
+ "-f",
+ secret["path"],
+ ]
+ if secret.get("json"):
+ secret_command.append("--json")
+
+ if secret.get("decode"):
+ secret_command.append("--decode")
+
+ return secret_command
+
+
+def _generate_dummy_secret_command(secret):
+ secret_command = [
+ "/builds/worker/checkouts/gecko/taskcluster/scripts/write-dummy-secret.py",
+ "-f",
+ secret["path"],
+ "-c",
+ secret["content"],
+ ]
+ if secret.get("json"):
+ secret_command.append("--json")
+
+ return secret_command
+
+
+def _convert_commands_to_string(commands):
+ should_artifact_reference = False
+ should_task_reference = False
+
+ sanitized_commands = []
+ for command in commands:
+ sanitized_parts = []
+ for part in command:
+ if isinstance(part, dict):
+ if "artifact-reference" in part:
+ part_string = part["artifact-reference"]
+ should_artifact_reference = True
+ elif "task-reference" in part:
+ part_string = part["task-reference"]
+ should_task_reference = True
+ else:
+ raise ValueError(f"Unsupported dict: {part}")
+ else:
+ part_string = part
+
+ sanitized_parts.append(part_string)
+ sanitized_commands.append(sanitized_parts)
+
+ shell_quoted_commands = [
+ " ".join(map(shell_quote, command)) for command in sanitized_commands
+ ]
+ full_string_command = " && ".join(shell_quoted_commands)
+
+ if should_artifact_reference and should_task_reference:
+ raise NotImplementedError(
+ '"arifact-reference" and "task-reference" cannot be both used'
+ )
+ elif should_artifact_reference:
+ return {"artifact-reference": full_string_command}
+ elif should_task_reference:
+ return {"task-reference": full_string_command}
+ else:
+ return full_string_command
+
+
+def _inject_secrets_scopes(run, taskdesc):
+ secrets = run.pop("secrets", [])
+ scopes = taskdesc.setdefault("scopes", [])
+ new_secret_scopes = ["secrets:get:{}".format(secret["name"]) for secret in secrets]
+ new_secret_scopes = list(
+ set(new_secret_scopes)
+ ) # Scopes must not have any duplicates
+ scopes.extend(new_secret_scopes)
+
+
+def _set_run_task_attributes(job):
+ run = job["run"]
+ run["cwd"] = "{checkout}"
+ run["using"] = "run-task"