# 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/. """
Transform the repackage task into an actual task description. """
from typing import Optional, Union
from taskgraph.transforms.base import TransformSequence from taskgraph.util.copy import deepcopy from taskgraph.util.dependencies import get_primary_dependency from taskgraph.util.schema import Schema, optionally_keyed_by, resolve_keyed_by from taskgraph.util.taskcluster import get_artifact_prefix
from gecko_taskgraph.transforms.job import JobDescriptionSchema from gecko_taskgraph.util.attributes import copy_attributes_from_dependent_job from gecko_taskgraph.util.platforms import architecture, archive_format from gecko_taskgraph.util.workertypes import worker_type_implementation
class MozharnessSchema(Schema, forbid_unknown_fields=False, kw_only=True): # Config files passed to the mozharness script
config: optionally_keyed_by("build-platform", list[str], use_msgspec=True) # type: ignore # noqa: F821 # Additional paths to look for mozharness configs in. These should be # relative to the base of the source checkout
config_paths: Optional[list[str]] = None # if true, perform a checkout of a comm-central based branch inside the # gecko checkout
comm_checkout: Optional[bool] = None
run_as_root: Optional[bool] = None
use_caches: Optional[Union[bool, list[str]]] = None
class PackagingDescriptionSchema(Schema, kw_only=True): # unique label to describe this repackaging task
label: Optional[str] = None
worker_type: Optional[str] = None
worker: Optional[object] = None
attributes: JobDescriptionSchema.__annotations__["attributes"] = None
dependencies: JobDescriptionSchema.__annotations__["dependencies"] = None # treeherder is allowed here to override any defaults we use for repackaging. See # taskcluster/gecko_taskgraph/transforms/task.py for the schema details, and the # below transforms for defaults of various values.
treeherder: JobDescriptionSchema.__annotations__["treeherder"] = None # If a l10n task, the corresponding locale
locale: Optional[str] = None # Routes specific to this task, if defined
routes: Optional[list[str]] = None # passed through directly to the job description
extra: JobDescriptionSchema.__annotations__["extra"] = None # passed through to job description
fetches: JobDescriptionSchema.__annotations__["fetches"] = None
run_on_projects: JobDescriptionSchema.__annotations__["run_on_projects"] = None
run_on_repo_type: JobDescriptionSchema.__annotations__["run_on_repo_type"] = None # Shipping product and phase
shipping_product: JobDescriptionSchema.__annotations__["shipping_product"] = None
shipping_phase: JobDescriptionSchema.__annotations__["shipping_phase"] = None
package_formats: optionally_keyed_by( # type: ignore # noqa: F821 "build-platform", "release-type", "build-type",
list[str],
use_msgspec=True,
)
msi: Optional[MsiSchema] = None
msix: Optional[MsixSchema] = None
flatpak: Optional[FlatpakSchema] = None # All l10n jobs use mozharness
mozharness: MozharnessSchema # noqa: F821
task_from: JobDescriptionSchema.__annotations__["task_from"] = None
@transforms.add def copy_in_useful_magic(config, jobs): """Copy attributes from upstream task to be used for keyed configuration.""" for job in jobs:
dep = get_primary_dependency(config, job) assert dep
@transforms.add def handle_keyed_by(config, jobs): """Resolve fields that can be keyed by platform, etc, but not `msix.*` fields
that can be keyed by `package-format`. Such fields are handled specially below. """
fields = [ "mozharness.config", "msi.display-name", "package-formats", "worker.max-run-time", "flatpak.name", "flatpak.branch",
] for job in jobs:
job = deepcopy(job) # don't overwrite dict values here for field in fields:
resolve_keyed_by(
item=job,
field=field,
item_name="?",
**{ "release-type": config.params["release_type"], "level": config.params["level"], "shipping-product": job.get("shipping-product"),
},
) yield job
@transforms.add def make_repackage_description(config, jobs): for job in jobs:
dep_job = get_primary_dependency(config, job) assert dep_job
# Search dependencies before adding langpack dependencies.
signing_task = None
repackage_signing_task = None for dependency in dependencies.keys(): if"repackage-signing"in dependency:
repackage_signing_task = dependency elif"signing"in dependency or"notarization"in dependency:
signing_task = dependency elif"shippable-l10n"in dependency: # Thunderbird does not sign langpacks, so we find them in the langpack build task
signing_task = dependency
if config.kind == "repackage-msi":
treeherder["symbol"] = "MSI({})".format(locale or"N") if display_name := job.get("msi", {}).get("display-name"):
attributes["msi_display_name"] = display_name
# The keys are unique, like `shippable-l10n-signing-linux64-shippable-1/opt`, so we # can't ask for the tasks directly, we must filter for them. for t in config.kind_dependencies_tasks.values(): if t.kind != "shippable-l10n-signing": continue if t.attributes["build_platform"] != "linux64-shippable": continue if t.attributes["build_type"] != "opt": continue
dependencies.update({t.label: t.label})
fetches.update({
t.label: [
{ "artifact": f"{loc}/target.langpack.xpi", "extract": False, # Otherwise we can't disambiguate locales! "dest": f"distribution/extensions/{loc}",
} for loc in t.attributes["chunk_locales"]
]
})
elif config.kind in ("repackage-deb", "repackage-rpm"):
attributes["repackage_type"] = config.kind
description = ( "Repackaging the '{build_platform}/{build_type}' " "{version} build into a '.{package}' package"
).format(
build_platform=attributes.get("build_platform"),
build_type=attributes.get("build_type"),
version=config.params["version"],
package=config.kind.split("-")[1],
)
langpack_locales = [] if config.kind in ("repackage-flatpak", "repackage-rpm"): assertnot locale
if attributes.get("l10n_chunk") or attributes.get("chunk_locales"): # We don't want to produce flatpaks for single-locale repack builds. continue
fetches = job.setdefault("fetches", {}) # The keys are unique, like `shippable-l10n-signing-linux64-shippable-1/opt`, so we # can't ask for the tasks directly, we must filter for them. for t in config.kind_dependencies_tasks.values(): # Filter out tasks that are either not the wrong kind, not the # right product or not the right platform to keep one langpack # per locale if attributes.get("shippable"): if t.kind != "shippable-l10n-signing": continue if t.attributes["shipping_product"] != job["shipping-product"]: continue if t.attributes["build_platform"] notin ( "linux64-shippable", "linux64-devedition",
): continue elif t.kind != "l10n"or t.attributes["build_platform"] != "linux64": continue if t.attributes["build_type"] != "opt": continue
repackage_config = []
package_formats = job.get("package-formats") if use_stub andnot repackage_signing_task and"msix"notin package_formats: # if repackage_signing_task doesn't exists, generate the stub installer
package_formats += ["installer-stub"] for format in package_formats:
command = deepcopy(PACKAGE_FORMATS[format])
substs = { "archive_format": archive_format(build_platform), "_locale": _fetch_subst_locale, "architecture": architecture(build_platform), "version_display": config.params["version"], "mar-channel-id": attributes["mar-channel-id"], "build_number": config.params["build_number"], "shipping_product": job["shipping-product"], "release_type": config.params["release_type"], "flatpak-name": job.get("flatpak", {}).get("name"), "flatpak-branch": job.get("flatpak", {}).get("branch"),
} # Allow us to replace `args` as well, but specifying things expanded in mozharness # without breaking .format and without allowing unknown through.
substs.update({name: f"{{{name}}}"for name in MOZHARNESS_EXPANSIONS})
# We need to resolve `msix.*` values keyed by `package-format` for each format, not # just once, so we update a temporary copy just for extracting these values.
temp_job = deepcopy(job) for msix_key in ( "channel", "identity-name", "publisher", "publisher-display-name", "vendor",
):
resolve_keyed_by(
item=temp_job,
field=f"msix.{msix_key}",
item_name="?",
**{ "package-format": format, "release-type": config.params["release_type"], "level": config.params["level"],
},
)
# Turn `msix.channel` into `msix-channel`, etc.
value = temp_job.get("msix", {}).get(msix_key) if value:
substs.update(
{f"msix-{msix_key}": value},
)
command["inputs"] = {
name: filename.format(**substs) for name, filename in command["inputs"].items()
}
command["args"] = [arg.format(**substs) for arg in command["args"]] if"installer"in format and"aarch64"notin build_platform:
command["args"].append("--use-upx")
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.32Bemerkung:
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.