summaryrefslogtreecommitdiffstats
path: root/taskcluster/taskgraph/transforms/partner_attribution.py
blob: 5396d733d5a3d483b7c921d70862a34f9d343546 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# 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 partner attribution task into an actual task description.
"""

from __future__ import absolute_import, print_function, unicode_literals

from collections import defaultdict
import json
import logging

import six

from taskgraph.transforms.base import TransformSequence
from taskgraph.util.partners import (
    apply_partner_priority,
    check_if_partners_enabled,
    get_partner_config_by_kind,
    generate_attribution_code,
)

log = logging.getLogger(__name__)

transforms = TransformSequence()
transforms.add(check_if_partners_enabled)
transforms.add(apply_partner_priority)


@transforms.add
def add_command_arguments(config, tasks):
    enabled_partners = config.params.get("release_partners")
    dependencies = {}
    fetches = defaultdict(set)
    attributions = []
    release_artifacts = []
    attribution_config = get_partner_config_by_kind(config, config.kind)

    for partner_config in attribution_config.get("configs", []):
        # we might only be interested in a subset of all partners, eg for a respin
        if enabled_partners and partner_config["campaign"] not in enabled_partners:
            continue
        attribution_code = generate_attribution_code(
            attribution_config["defaults"], partner_config
        )
        for platform in partner_config["platforms"]:
            stage_platform = platform.replace("-shippable", "")
            for locale in partner_config["locales"]:
                # find the upstream, throw away locales we don't have, somehow. Skip ?
                if locale == "en-US":
                    upstream_label = "repackage-signing-{platform}/opt".format(
                        platform=platform
                    )
                    upstream_artifact = "target.installer.exe"
                else:
                    upstream_label = (
                        "repackage-signing-l10n-{locale}-{platform}/opt".format(
                            locale=locale, platform=platform
                        )
                    )
                    upstream_artifact = "{locale}/target.installer.exe".format(
                        locale=locale
                    )
                if upstream_label not in config.kind_dependencies_tasks:
                    raise Exception(
                        "Can't find upstream task for {} {}".format(platform, locale)
                    )
                upstream = config.kind_dependencies_tasks[upstream_label]

                # set the dependencies to just what we need rather than all of l10n
                dependencies.update({upstream.label: upstream.label})

                fetches[upstream_label].add((upstream_artifact, stage_platform, locale))

                artifact_part = "{platform}/{locale}/target.installer.exe".format(
                    platform=stage_platform, locale=locale
                )
                artifact = (
                    "releng/partner/{partner}/{sub_partner}/{artifact_part}".format(
                        partner=partner_config["campaign"],
                        sub_partner=partner_config["content"],
                        artifact_part=artifact_part,
                    )
                )
                # config for script
                # TODO - generalise input & output ??
                #  add releng/partner prefix via get_artifact_prefix..()
                attributions.append(
                    {
                        "input": "/builds/worker/fetches/{}".format(artifact_part),
                        "output": "/builds/worker/artifacts/{}".format(artifact),
                        "attribution": attribution_code,
                    }
                )
                release_artifacts.append(artifact)

    # bail-out early if we don't have any attributions to do
    if not attributions:
        return

    for task in tasks:
        worker = task.get("worker", {})
        worker["chain-of-trust"] = True

        task.setdefault("dependencies", {}).update(dependencies)
        task.setdefault("fetches", {})
        for upstream_label, upstream_artifacts in fetches.items():
            task["fetches"][upstream_label] = [
                {
                    "artifact": upstream_artifact,
                    "dest": "{platform}/{locale}".format(
                        platform=platform, locale=locale
                    ),
                    "extract": False,
                    "verify-hash": True,
                }
                for upstream_artifact, platform, locale in upstream_artifacts
            ]
        worker.setdefault("env", {})["ATTRIBUTION_CONFIG"] = six.ensure_text(
            json.dumps(attributions, sort_keys=True)
        )
        worker["artifacts"] = [
            {
                "name": "releng/partner",
                "path": "/builds/worker/artifacts/releng/partner",
                "type": "directory",
            }
        ]
        task["release-artifacts"] = release_artifacts
        task["label"] = config.kind

        yield task