# 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/.
# Support for running tasks that download remote content and re-export # it as task artifacts.
import os import re from typing import Literal, Optional
import attr import taskgraph from mozpack import path as mozpath from mozshellutil import quote as shell_quote from taskgraph.transforms.base import TransformSequence from taskgraph.util.schema import Schema, validate_schema from taskgraph.util.treeherder import join_symbol
import gecko_taskgraph from gecko_taskgraph.transforms.task import TaskDescriptionSchema
from ..util.cached_tasks import add_optimization
CACHE_TYPE = "content.v1"
class FetchTypeSchema(Schema, forbid_unknown_fields=False, kw_only=True):
type: str
class FetchSchema(Schema, kw_only=True): # Name of the task.
name: str # Relative path (from config.path) to the file the task was defined in.
task_from: Optional[str] = None # Description of the task.
description: str # An alias that can be used instead of the real fetch job name in # fetch stanzas for jobs.
fetch_alias: Optional[str] = None # The prefix of the taskcluster artifact being uploaded. # Defaults to `public/`; if it starts with something other than # `public/` the artifact will require scopes to access.
artifact_prefix: Optional[str] = None
attributes: Optional[dict[str, object]] = None
run_on_repo_type: TaskDescriptionSchema.__annotations__["run_on_repo_type"] = None
fetch: FetchTypeSchema # noqa: F821
# define a collection of payload builders, depending on the worker implementation
fetch_builders = {}
@attr.s(frozen=True) class FetchBuilder:
schema = attr.ib()
builder = attr.ib()
@transforms.add def process_fetch_job(config, jobs): # Converts fetch-url entries to the job schema. for job in jobs:
typ = job["fetch"]["type"]
name = job["name"]
fetch = job.pop("fetch")
if typ notin fetch_builders: raise Exception(f"Unknown fetch type {typ} in fetch {name}")
validate_schema(fetch_builders[typ].schema, fetch, f"In task.fetch {name!r}:")
@transforms.add def make_task(config, jobs): # Fetch tasks are idempotent and immutable. Have them live for # essentially forever. if config.params["level"] == "3":
expires = "1000 years" else:
expires = "28 days"
for job in jobs:
name = job["name"]
artifact_prefix = job.get("artifact-prefix", "public")
env = job.get("env", {})
env.update({"UPLOAD_DIR": "/builds/worker/artifacts"})
attributes = job.get("attributes", {})
attributes["artifact_prefix"] = artifact_prefix
attributes["fetch-artifact"] = mozpath.join(
artifact_prefix, job["artifact_name"]
)
alias = job.get("fetch-alias") if alias:
attributes["fetch-alias"] = alias
# Fetches that are used for local development need to be built on a # level-3 branch to be installable via `mach bootstrap`. if attributes.get("local-fetch"):
task["run-on-projects"] = ["integration", "release"]
# This adds the level to the index path automatically.
add_optimization(
config,
task,
cache_type=CACHE_TYPE,
cache_name=cache_name,
digest_data=job["digest_data"],
) yield task
class GpgSignatureSchema(Schema, forbid_unknown_fields=False, kw_only=True): # URL where GPG signature document can be obtained. Can contain the # value ``{url}``, which will be substituted with the value from ``url``.
sig_url: str # Path to file containing GPG public key(s) used to validate download.
key_path: str
class StaticUrlFetchSchema(Schema, forbid_unknown_fields=False, kw_only=True):
type: Literal["static-url"] # The URL to download.
url: str # The SHA-256 of the downloaded content.
sha256: str # Size of the downloaded entity, in bytes.
size: int # GPG signature verification.
gpg_signature: Optional[GpgSignatureSchema] = None
headers: Optional[list[str]] = None # The name to give to the generated artifact. Defaults to the file # portion of the URL. Using a different extension converts the # archive to the given type. Only conversion to .tar.zst is supported.
artifact_name: Optional[str] = None # Strip the given number of path components at the beginning of # each file entry in the archive. Requires an artifact-name ending with .tar.zst.
strip_components: Optional[int] = None # Add the given prefix to each file entry in the archive. # Requires an artifact-name ending with .tar.zst.
add_prefix: Optional[str] = None # IMPORTANT: when adding anything that changes the behavior of the task, # it is important to update the digest data used to compute cache hits.
return { "command": command, "artifact_name": artifact_name, "env": env, # We don't include the GPG signature in the digest because it isn't # materially important for caching: GPG signatures are supplemental # trust checking beyond what the shasum already provides. "digest_data": args + [artifact_name],
}
class GitFetchSchema(Schema, forbid_unknown_fields=False, kw_only=True):
type: Literal["git"]
repo: str # Either revision or branch must be provided (validated at runtime).
revision: Optional[str] = None
branch: Optional[str] = None
include_dot_git: Optional[bool] = None
artifact_name: Optional[str] = None
path_prefix: Optional[str] = None # ssh-key is a taskcluster secret path (e.g. project/civet/github-deploy-key) # In the secret dictionary, the key should be specified as # "ssh_privkey": "-----BEGIN OPENSSH PRIVATE KEY-----\nkfksnb3jc..." # n.b. The OpenSSH private key file format requires a newline at the end of the file.
ssh_key: Optional[str] = None
if"revision"in fetch and"branch"in fetch: raise Exception("revision and branch cannot be used in the same context")
revision_or_branch = None
if"revision"in fetch:
revision_or_branch = fetch["revision"] ifnot re.match(r"[0-9a-fA-F]{40}", fetch["revision"]): raise Exception(f'Revision is not a sha1 in fetch task "{name}"') else: # we are sure we are dealing with a branch
revision_or_branch = fetch["branch"]
class ChromiumFetchSchema(Schema, forbid_unknown_fields=False, kw_only=True):
type: Literal["chromium-fetch"]
script: str # Platform type for chromium build
platform: str # Chromium revision to obtain
revision: Optional[str] = None # The name to give to the generated artifact.
artifact_name: str
class CftChromedriverFetchSchema(Schema, forbid_unknown_fields=False, kw_only=True):
type: Literal["cft-chromedriver-fetch"]
script: str # Platform type for chromium build
platform: str # The name to give to the generated artifact.
artifact_name: str # The chrome channel to download from.
channel: Optional[str] = None # Determine if we are fetching a backup (stable version - 1) driver.
backup: Optional[bool] = None # Pin a stable version of chrome to download from. To be used together with `backup`.
version: Optional[str] = None
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.