Skip to content

Commit

Permalink
feat: create a bitrisescript payload builder
Browse files Browse the repository at this point in the history
  • Loading branch information
ahal committed Mar 22, 2024
1 parent 942d402 commit 3bb2c22
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 3 deletions.
10 changes: 10 additions & 0 deletions src/mozilla_taskgraph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
from importlib import import_module

from taskgraph.config import validate_graph_config
from taskgraph.util import schema

# Schemas for YAML files should use dashed identifiers by default. If there are
# components of the schema for which there is a good reason to use another format,
# exceptions can be added here.
schema.EXCEPTED_SCHEMA_IDENTIFIERS.extend(
[
"bitrise",
]
)


def register(graph_config):
Expand Down
105 changes: 104 additions & 1 deletion src/mozilla_taskgraph/worker_types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,108 @@
from taskgraph.transforms.task import payload_builder
from voluptuous import Required
from voluptuous import Extra, Optional, Required


@payload_builder(
"scriptworker-bitrise",
schema={
Required("bitrise"): {
Required(
"app", description="Name of Bitrise App to schedule workflows on."
): str,
Required(
"workflows",
description="List of workflows to trigger on specified app.",
): [str],
Optional(
"build_params",
description="Parameters describing the build context to pass "
"onto Bitrise. All keys are optional but specific workflows "
"may depend on particular keys being set.",
): {
Optional(
"branch",
description="The branch running the build. For pull "
"requests, this should be the head branch.",
): str,
Optional(
"branch_dest",
description="The destination branch where the branch "
"running the build will merge into. Only valid for pull "
"requests.",
): str,
Optional(
"branch_dest_repo_owner",
description="The repository owning the destination branch. "
"Only valid for pull requests.",
): str,
Optional(
"branch_repo_owner", description="The repository owning the branch."
): str,
Optional(
"commit_hash",
description="The hash of the commit running the build.",
): str,
Optional(
"commit_message",
description="The commit message of the commit running the build.",
): str,
Optional(
"environments",
description="Environment variables to pass into the build.",
): dict,
Optional(
"pull_request_author",
description="The author of the pull request running the build.",
): str,
Optional(
"pull_request_id",
description="The id of the pull request running the build.",
): int,
Optional(
"skip_git_status_report",
description="Whether Bitrise should send a status report to "
"Github (default False).",
): bool,
Optional(
"tag", description="The tag of the commit running the build."
): str,
},
},
Extra: object,
},
)
def build_bitrise_payload(config, task, task_def):
bitrise = task["worker"]["bitrise"]
build_params = task_def["payload"] = bitrise.get("build_params") or {}
task_def["tags"]["worker-implementation"] = "scriptworker"

scope_prefix = config.graph_config["scriptworker"]["scope-prefix"]
scopes = task_def.setdefault("scopes", [])
scopes.append(f"{scope_prefix}:bitrise:app:{bitrise['app']}")
scopes.extend(
[f"{scope_prefix}:bitrise:workflow:{wf}" for wf in bitrise["workflows"]]
)

# Set some build_params implicitly from Taskcluster params.
build_params.setdefault("commit_hash", config.params["head_rev"])
build_params.setdefault("branch_repo_owner", config.params["head_repository"])

if config.params["head_ref"]:
build_params.setdefault("branch", config.params["head_ref"])

if config.params["head_tag"]:
build_params.setdefault("tag", config.params["head_tag"])

if config.params["tasks_for"] == "github-pull-request":
build_params.setdefault("pull_request_author", config.params["owner"])

if config.params["base_ref"]:
build_params.setdefault("branch_dest", config.params["base_ref"])

if config.params["base_repository"]:
build_params.setdefault(
"branch_dest_repo_owner", config.params["base_repository"]
)


@payload_builder(
Expand Down
6 changes: 4 additions & 2 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,15 @@ def file_url(self, path, pretty=False):
def parameters():
return FakeParameters(
{
"base_repository": "http://hg.example.com",
"base_ref": "123456",
"base_repository": "http://example.com/base/repo",
"build_date": 0,
"build_number": 1,
"enable_always_target": True,
"head_repository": "http://hg.example.com",
"head_repository": "http://example.com/head/repo",
"head_rev": "abcdef",
"head_ref": "default",
"head_tag": "",
"level": "1",
"moz_build_date": 0,
"next_version": "1.0.1",
Expand Down
100 changes: 100 additions & 0 deletions test/test_worker_types.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,106 @@
import inspect
from pprint import pprint

import pytest
from taskgraph.transforms.task import payload_builders
from taskgraph.util.schema import validate_schema

from mozilla_taskgraph import worker_types


@pytest.mark.parametrize(
"worker,extra_params,expected",
(
pytest.param({}, {}, Exception, id="missing bitrise"),
pytest.param({"bitrise": {"workflows": []}}, {}, Exception, id="missing app"),
pytest.param(
{"bitrise": {"app": "foo"}}, {}, Exception, id="missing workflows"
),
pytest.param(
{"bitrise": {"app": "some-app", "workflows": ["bar", "baz"]}},
{},
{
"payload": {
"branch": "default",
"branch_repo_owner": "http://example.com/head/repo",
"commit_hash": "abcdef",
},
"scopes": [
"foo:bitrise:app:some-app",
"foo:bitrise:workflow:bar",
"foo:bitrise:workflow:baz",
],
"tags": {"worker-implementation": "scriptworker"},
},
id="default params",
),
pytest.param(
{"bitrise": {"app": "some-app", "workflows": ["bar"]}},
{"tasks_for": "github-pull-request"},
{
"payload": {
"branch": "default",
"branch_dest": "123456",
"branch_dest_repo_owner": "http://example.com/base/repo",
"branch_repo_owner": "http://example.com/head/repo",
"commit_hash": "abcdef",
"pull_request_author": "some-owner",
},
"scopes": ["foo:bitrise:app:some-app", "foo:bitrise:workflow:bar"],
"tags": {"worker-implementation": "scriptworker"},
},
id="pull request",
),
pytest.param(
{"bitrise": {"app": "some-app", "workflows": ["bar"]}},
{
"base_ref": "",
"base_repository": "",
"head_ref": "",
"head_tag": "some-tag",
"tasks_for": "github-pull-request",
},
{
"payload": {
"branch_repo_owner": "http://example.com/head/repo",
"commit_hash": "abcdef",
"pull_request_author": "some-owner",
"tag": "some-tag",
},
"scopes": ["foo:bitrise:app:some-app", "foo:bitrise:workflow:bar"],
"tags": {"worker-implementation": "scriptworker"},
},
id="opposite params", # this test helps hit other half of if statements
),
),
)
def test_build_bitrise_payload(
make_graph_config, make_transform_config, parameters, worker, extra_params, expected
):
schema = payload_builders["scriptworker-bitrise"].schema

graph_config = make_graph_config(
extra_config={"scriptworker": {"scope-prefix": "foo"}}
)
parameters.update(extra_params)
config = make_transform_config(params=parameters, graph_cfg=graph_config)

worker.setdefault("implementation", "scriptworker-bitrise")
task = {"worker": worker}
task_def = {"tags": {}}

if inspect.isclass(expected) and issubclass(expected, Exception):
with pytest.raises(expected):
validate_schema(schema, worker, "schema error")
worker_types.build_bitrise_payload(config, task, task_def)
else:
validate_schema(schema, worker, "schema error")
worker_types.build_bitrise_payload(config, task, task_def)
print("Dumping result:")
pprint(task_def, indent=2)
assert task_def == expected


def test_build_shipit_payload():
task = {"worker": {"release-name": "foo"}}
task_def = {"tags": {}}
Expand Down

0 comments on commit 3bb2c22

Please sign in to comment.