summaryrefslogtreecommitdiffstats
path: root/taskcluster/android_taskgraph/transforms/build_components.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--taskcluster/android_taskgraph/transforms/build_components.py207
1 files changed, 207 insertions, 0 deletions
diff --git a/taskcluster/android_taskgraph/transforms/build_components.py b/taskcluster/android_taskgraph/transforms/build_components.py
new file mode 100644
index 0000000000..d4e1f8c508
--- /dev/null
+++ b/taskcluster/android_taskgraph/transforms/build_components.py
@@ -0,0 +1,207 @@
+# 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/.
+
+
+import datetime
+
+from mozilla_version.mobile import GeckoVersion
+from taskgraph.transforms.base import TransformSequence
+from taskgraph.util.schema import resolve_keyed_by
+
+from ..build_config import get_extensions, get_path
+
+transforms = TransformSequence()
+
+
+@transforms.add
+def resolve_keys(config, tasks):
+ for task in tasks:
+ for field in (
+ "include-coverage",
+ "run-on-projects",
+ "shipping-phase",
+ "run.gradlew",
+ "treeherder.symbol",
+ "dependencies.build-fat-aar",
+ ):
+ resolve_keyed_by(
+ task,
+ field,
+ item_name=task["name"],
+ **{
+ "build-type": task["attributes"]["build-type"],
+ "component": task["attributes"]["component"],
+ },
+ )
+
+ yield task
+
+
+@transforms.add
+def handle_update_channel(config, tasks):
+ for task in tasks:
+ build_fat_aar = config.kind_dependencies_tasks[
+ task["dependencies"]["build-fat-aar"]
+ ]
+ if build_fat_aar.attributes.get("shippable"):
+ task["worker"].setdefault("env", {}).setdefault(
+ "MOZ_UPDATE_CHANNEL",
+ build_fat_aar.attributes.get("update-channel", "default"),
+ )
+ yield task
+
+
+@transforms.add
+def handle_coverage(config, tasks):
+ for task in tasks:
+ if task.pop("include-coverage", False):
+ task["run"]["gradlew"].insert(0, "-Pcoverage")
+ yield task
+
+
+@transforms.add
+def interpolate_missing_values(config, tasks):
+ timestamp = _get_timestamp(config)
+ version = config.params["version"]
+ nightly_version = get_nightly_version(config, version)
+
+ for task in tasks:
+ for field in ("description", "run.gradlew", "treeherder.symbol"):
+ component = task["attributes"]["component"]
+ _deep_format(
+ task,
+ field,
+ component=component,
+ nightlyVersion=nightly_version,
+ timestamp=timestamp,
+ treeherder_group=component[:25],
+ )
+
+ yield task
+
+
+def _get_timestamp(config):
+ push_date_string = config.params["moz_build_date"]
+ push_date_time = datetime.datetime.strptime(push_date_string, "%Y%m%d%H%M%S")
+ return push_date_time.strftime("%Y%m%d.%H%M%S-1")
+
+
+def _get_buildid(config):
+ return config.params.moz_build_date.strftime("%Y%m%d%H%M%S")
+
+
+def get_nightly_version(config, version):
+ buildid = _get_buildid(config)
+ parsed_version = GeckoVersion.parse(version)
+ return f"{parsed_version.major_number}.{parsed_version.minor_number}.{buildid}"
+
+
+def craft_path_version(version, build_type, nightly_version):
+ """Helper function to craft the correct version to bake in the artifacts full
+ path section"""
+ path_version = version
+ # XXX: for nightly releases we need to s/X.0.0/X.0.<buildid>/g in versions
+ if build_type == "nightly":
+ path_version = path_version.replace(version, nightly_version)
+ return path_version
+
+
+def _deep_format(object, field, **format_kwargs):
+ keys = field.split(".")
+ last_key = keys[-1]
+ for key in keys[:-1]:
+ object = object[key]
+
+ one_before_last_object = object
+ object = object[last_key]
+
+ if isinstance(object, str):
+ one_before_last_object[last_key] = object.format(**format_kwargs)
+ elif isinstance(object, list):
+ one_before_last_object[last_key] = [
+ item.format(**format_kwargs) for item in object
+ ]
+ else:
+ raise ValueError(f"Unsupported type for object: {object}")
+
+
+@transforms.add
+def add_artifacts(config, tasks):
+ _get_timestamp(config)
+ version = config.params["version"]
+ nightly_version = get_nightly_version(config, version)
+
+ for task in tasks:
+ artifact_template = task.pop("artifact-template", {})
+ task["attributes"]["artifacts"] = artifacts = {}
+
+ component = task["attributes"]["component"]
+ build_artifact_definitions = task.setdefault("worker", {}).setdefault(
+ "artifacts", []
+ )
+
+ for key in [
+ "tests-artifact-template",
+ "lint-artifact-template",
+ "jacoco-coverage-template",
+ ]:
+ if key in task:
+ optional_artifact_template = task.pop(key, {})
+ build_artifact_definitions.append(
+ {
+ "type": optional_artifact_template["type"],
+ "name": optional_artifact_template["name"],
+ "path": optional_artifact_template["path"].format(
+ component_path=get_path(component)
+ ),
+ }
+ )
+
+ if artifact_template:
+ all_extensions = get_extensions(component)
+ artifact_file_names_per_extension = {
+ extension: "{component}-{version}{timestamp}{extension}".format(
+ component=component,
+ version=version,
+ timestamp="",
+ extension=extension,
+ )
+ for extension in all_extensions
+ }
+ # XXX: rather than adding more complex logic above, we simply post-adjust the
+ # dictionary for `nightly` types of graphs
+ if task["attributes"]["build-type"] == "nightly":
+ for ext, path in artifact_file_names_per_extension.items():
+ if version in path:
+ artifact_file_names_per_extension[ext] = path.replace(
+ version, nightly_version
+ )
+
+ for (
+ extension,
+ artifact_file_name,
+ ) in artifact_file_names_per_extension.items():
+ artifact_full_name = artifact_template["name"].format(
+ artifact_file_name=artifact_file_name,
+ )
+ build_artifact_definitions.append(
+ {
+ "type": artifact_template["type"],
+ "name": artifact_full_name,
+ "path": artifact_template["path"].format(
+ component_path=get_path(component),
+ component=component,
+ version=craft_path_version(
+ version,
+ task["attributes"]["build-type"],
+ nightly_version,
+ ),
+ artifact_file_name=artifact_file_name,
+ ),
+ }
+ )
+
+ artifacts[extension] = artifact_full_name
+
+ yield task