releases-comm-central/taskcluster/comm_taskgraph/decision.py

202 строки
6.8 KiB
Python

# 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 argparse
import logging
import os
import sys
from redo import retry
from taskgraph.decision import (
_determine_more_accurate_base_ref,
_determine_more_accurate_base_rev,
_get_env_prefix,
)
from taskgraph.taskgraph import TaskGraph
from taskgraph.util.taskcluster import get_artifact
from taskgraph.util.vcs import get_repository
from gecko_taskgraph.util.backstop import is_backstop
from gecko_taskgraph.util.hg import get_hg_commit_message
from gecko_taskgraph.util.partials import populate_release_history
from gecko_taskgraph.util.taskgraph import (
find_decision_task,
find_existing_tasks_from_previous_kinds,
)
from . import COMM
from comm_taskgraph.parameters import get_defaults
from comm_taskgraph.util.suite import is_suite_only_push
logger = logging.getLogger(__name__)
BALROG_PRODUCT = "Thunderbird"
# Backstop defaults
BACKSTOP_TIME_INTERVAL = 60 * 22 # minutes
INTEGRATION_PROJECTS = {"comm-central"}
PER_PROJECT_PARAMETERS = {
"ash": {
"target_tasks_method": "ash_tasks",
},
"jamun": {
"target_tasks_method": "nightly_desktop",
"release_type": "nightly",
},
"try-comm-central": {
"enable_always_target": True,
"target_tasks_method": lambda parameters: "codereview"
if parameters.get("target_tasks_method") == "codereview"
else "try_cc_tasks",
},
"comm-central": {
"target_tasks_method": "comm_central_tasks",
"release_type": "nightly",
},
"comm-beta": {
"target_tasks_method": "mozilla_beta_tasks",
"release_type": "beta",
},
"comm-release": {
"target_tasks_method": "mozilla_release_tasks",
"release_type": "release",
},
"comm-esr115": {
"target_tasks_method": "mozilla_esr115_tasks",
"release_type": "esr115",
},
}
CRON_OPTIONS = {
"nightly_desktop": {
"existing_tasks": lambda parameters, graph_config: get_existing_tasks(
parameters, graph_config
),
"release_history": lambda parameters, graph_config: populate_release_history(
BALROG_PRODUCT, parameters["project"]
),
}
}
def restore_options():
"""
Some parameters need the original commandline arguments that are not passed
to comm_taskgraph.get_decision_parameters. But, sys.argv is still around so
they can be found out again.
"""
parser = argparse.ArgumentParser()
parser.add_argument("--target-tasks-method")
parser.add_argument("--tasks-for")
result = parser.parse_known_args()
return vars(result[0])
def get_decision_parameters(graph_config, parameters):
logger.info("{}.get_decision_parameters called".format(__name__))
commit_message = get_hg_commit_message(COMM)
options = restore_options()
# Apply default values for all Thunderbird CI projects
parameters.update(get_defaults(graph_config.vcs_root))
# If the target method is nightly, we should build partials. This means
# knowing what has been released previously.
# An empty release_history is fine, it just means no partials will be built
project = parameters["project"]
if project in PER_PROJECT_PARAMETERS:
for _parameter, _value in PER_PROJECT_PARAMETERS[project].items():
parameters[_parameter] = _value(parameters) if callable(_value) else _value
logger.info("project parameters set for project {} from {}.".format(project, __file__))
else:
# Projects without a target_tasks_method should not exist for Thunderbird CI
raise Exception("No target_tasks_method is defined for project {}.".format(project))
# `target_tasks_method` has higher precedence than `project` parameters
if options.get("target_tasks_method"):
parameters["target_tasks_method"] = options["target_tasks_method"]
# ..but can be overridden by the commit message: if it contains the special
# string "DONTBUILD" and this is an on-push decision task, then use the
# special 'nothing' target task method.
if "DONTBUILD" in commit_message and options["tasks_for"] == "hg-push":
parameters["target_tasks_method"] = "nothing"
del parameters["backstop"]
parameters["backstop"] = is_backstop(
parameters,
trust_domain="comm",
time_interval=BACKSTOP_TIME_INTERVAL,
integration_projects=INTEGRATION_PROJECTS,
)
for n in (
"COMM_BASE_REPOSITORY",
"COMM_BASE_REV",
"COMM_HEAD_REPOSITORY",
"COMM_HEAD_REV",
"COMM_HEAD_REF",
):
val = os.environ.get(n, "")
parameters[n.lower()] = val
repo_path = COMM
repo = get_repository(repo_path)
logger.info("Determining comm_base_ref...")
parameters["comm_base_ref"] = _determine_more_accurate_base_ref(
repo,
candidate_base_ref="",
head_ref=parameters.get("comm_head_ref"),
base_rev=parameters.get("comm_base_rev"),
)
logger.info("Determining comm_base_rev...")
parameters["comm_base_rev"] = _determine_more_accurate_base_rev(
repo,
base_ref=parameters["comm_base_ref"],
candidate_base_rev=parameters.get("comm_base_rev"),
head_rev=parameters.get("comm_head_rev"),
env_prefix=_get_env_prefix(graph_config),
)
parameters.setdefault("release_history", dict())
if parameters.get("tasks_for", "") == "cron":
for key, _callable in CRON_OPTIONS.get(parameters["target_tasks_method"], {}).items():
result = _callable(parameters, graph_config)
parameters[key] = result
comm_head_repository = parameters.get("comm_head_repository")
comm_head_rev = parameters.get("comm_head_rev")
# Do not run any jobs if this is a suite-only push, but the push could be used for
# a cron decision task later (like for a Daily build)
if (
is_suite_only_push(comm_head_repository, comm_head_rev)
and options["tasks_for"] == "hg-push"
):
logger.info("This is a suite-only push; setting target_tasks_method to 'nothing'.")
parameters["target_tasks_method"] = "nothing"
def get_existing_tasks(parameters, graph_config):
"""
Find the decision task corresponding to the on-push graph, and return
a mapping of labels to task-ids from it.
"""
try:
decision_task = retry(
find_decision_task,
args=(parameters, graph_config),
attempts=4,
sleeptime=5 * 60,
)
except Exception:
logger.exception("Didn't find existing push task.")
sys.exit(1)
_, task_graph = TaskGraph.from_json(get_artifact(decision_task, "public/full-task-graph.json"))
return find_existing_tasks_from_previous_kinds(task_graph, [decision_task], [])