Skip to content

Commit 70d156b

Browse files
feat: convert all interconnected/dependent schemas to msgspec
1 parent 77f68a1 commit 70d156b

11 files changed

Lines changed: 699 additions & 1158 deletions

File tree

docs/conf.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343
# This pattern also affects html_static_path and html_extra_path.
4444
exclude_patterns = ["docs/_build", "Thumbs.db", ".DS_Store"]
4545

46+
# Suppress ambiguous cross-reference warnings from autodoc.
47+
# Multiple Schema classes define fields with the same name (e.g. "path"),
48+
# which Sphinx can't disambiguate.
49+
suppress_warnings = ["ref.python"]
50+
4651

4752
# -- Options for HTML output -------------------------------------------------
4853

src/taskgraph/config.py

Lines changed: 68 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -8,106 +8,83 @@
88
import sys
99
from dataclasses import dataclass
1010
from pathlib import Path
11+
from typing import Literal, Optional, Union
1112

12-
from voluptuous import ALLOW_EXTRA, All, Any, Extra, Length, Optional, Required
13-
14-
from .util.caches import CACHES
1513
from .util.python_path import find_object
16-
from .util.schema import LegacySchema, optionally_keyed_by, validate_schema
14+
from .util.schema import Schema, TaskPriority, optionally_keyed_by, validate_schema
1715
from .util.vcs import get_repository
1816
from .util.yaml import load_yaml
1917

2018
logger = logging.getLogger(__name__)
2119

20+
CacheType = Literal["cargo", "checkout", "npm", "pip", "uv"]
21+
22+
23+
class WorkerAlias(Schema):
24+
provisioner: optionally_keyed_by("level", str, use_msgspec=True) # type: ignore
25+
implementation: str
26+
os: str
27+
worker_type: optionally_keyed_by("level", str, use_msgspec=True) # type: ignore
28+
29+
30+
class WorkersConfig(Schema):
31+
aliases: dict[str, WorkerAlias]
32+
33+
34+
class RunConfig(Schema):
35+
# List of caches to enable, or a boolean to enable/disable all of them.
36+
use_caches: Optional[Union[bool, list[CacheType]]] = None
37+
38+
39+
class RepositoryConfig(Schema, forbid_unknown_fields=False):
40+
name: str
41+
project_regex: Optional[str] = None
42+
ssh_secret_name: Optional[str] = None
43+
# FIXME: Extra keys allowed via forbid_unknown_fields=False
44+
45+
46+
class TaskgraphConfig(Schema):
47+
repositories: dict[str, RepositoryConfig]
48+
# Python function to call to register extensions.
49+
register: Optional[str] = None
50+
decision_parameters: Optional[str] = None
51+
# The taskcluster index prefix to use for caching tasks.
52+
# Defaults to `trust-domain`.
53+
cached_task_prefix: Optional[str] = None
54+
# Should tasks from pull requests populate the cache
55+
cache_pull_requests: Optional[bool] = None
56+
# Regular expressions matching index paths to be summarized.
57+
index_path_regexes: Optional[list[str]] = None
58+
# Configuration related to the 'run' transforms.
59+
run: Optional[RunConfig] = None
60+
61+
def __post_init__(self):
62+
# Validate repositories has at least 1 entry (was All(..., Length(min=1)))
63+
if not self.repositories:
64+
raise ValueError("'repositories' must have at least one entry")
65+
2266

2367
#: Schema for the graph config
24-
graph_config_schema = LegacySchema(
25-
{
26-
# The trust-domain for this graph.
27-
# (See https://firefox-source-docs.mozilla.org/taskcluster/taskcluster/taskgraph.html#taskgraph-trust-domain) # noqa
28-
Required("trust-domain"): str,
29-
Optional(
30-
"docker-image-kind",
31-
description="Name of the docker image kind (default: docker-image)",
32-
): str,
33-
Required("task-priority"): optionally_keyed_by(
34-
"project",
35-
"level",
36-
Any(
37-
"highest",
38-
"very-high",
39-
"high",
40-
"medium",
41-
"low",
42-
"very-low",
43-
"lowest",
44-
),
45-
),
46-
Optional(
47-
"task-deadline-after",
48-
description="Default 'deadline' for tasks, in relative date format. "
49-
"Eg: '1 week'",
50-
): optionally_keyed_by("project", str),
51-
Optional(
52-
"task-expires-after",
53-
description="Default 'expires-after' for level 1 tasks, in relative date format. "
54-
"Eg: '90 days'",
55-
): str,
56-
Required("workers"): {
57-
Required("aliases"): {
58-
str: {
59-
Required("provisioner"): optionally_keyed_by("level", str),
60-
Required("implementation"): str,
61-
Required("os"): str,
62-
Required("worker-type"): optionally_keyed_by("level", str),
63-
}
64-
},
65-
},
66-
Required("taskgraph"): {
67-
Optional(
68-
"register",
69-
description="Python function to call to register extensions.",
70-
): str,
71-
Optional("decision-parameters"): str,
72-
Optional(
73-
"cached-task-prefix",
74-
description="The taskcluster index prefix to use for caching tasks. "
75-
"Defaults to `trust-domain`.",
76-
): str,
77-
Optional(
78-
"cache-pull-requests",
79-
description="Should tasks from pull requests populate the cache",
80-
): bool,
81-
Optional(
82-
"index-path-regexes",
83-
description="Regular expressions matching index paths to be summarized.",
84-
): [str],
85-
Optional(
86-
"run",
87-
description="Configuration related to the 'run' transforms.",
88-
): {
89-
Optional(
90-
"use-caches",
91-
description="List of caches to enable, or a boolean to "
92-
"enable/disable all of them.",
93-
): Any(bool, list(CACHES.keys())),
94-
},
95-
Required("repositories"): All(
96-
{
97-
str: {
98-
Required("name"): str,
99-
Optional("project-regex"): str,
100-
Optional("ssh-secret-name"): str,
101-
# FIXME
102-
Extra: str,
103-
}
104-
},
105-
Length(min=1),
106-
),
107-
},
108-
},
109-
extra=ALLOW_EXTRA,
110-
)
68+
class GraphConfigSchema(Schema, forbid_unknown_fields=False):
69+
# The trust-domain for this graph.
70+
trust_domain: str
71+
task_priority: optionally_keyed_by( # type: ignore
72+
"project", "level", TaskPriority, use_msgspec=True
73+
)
74+
workers: WorkersConfig
75+
taskgraph: TaskgraphConfig
76+
# Name of the docker image kind (default: docker-image)
77+
docker_image_kind: Optional[str] = None
78+
# Default 'deadline' for tasks, in relative date format. Eg: '1 week'
79+
task_deadline_after: Optional[
80+
optionally_keyed_by("project", str, use_msgspec=True) # type: ignore
81+
] = None
82+
# Default 'expires-after' for level 1 tasks, in relative date format.
83+
# Eg: '90 days'
84+
task_expires_after: Optional[str] = None
85+
86+
87+
graph_config_schema = GraphConfigSchema
11188

11289

11390
@dataclass(frozen=True, eq=False)

0 commit comments

Comments
 (0)