Skip to content

Commit 698ca57

Browse files
fix: restore payload_builder wrapping for dict schemas
1 parent e901417 commit 698ca57

4 files changed

Lines changed: 61 additions & 0 deletions

File tree

src/taskgraph/transforms/task.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616
from dataclasses import dataclass
1717
from typing import Callable, Literal, Optional, Union
1818

19+
import voluptuous
20+
1921
from taskgraph.transforms.base import TransformSequence
2022
from taskgraph.util.hash import hash_path
2123
from taskgraph.util.keyed_by import evaluate_keyed_by
2224
from taskgraph.util.schema import (
2325
IndexSchema,
26+
LegacySchema,
2427
OptimizationType,
2528
Schema,
2629
TaskPriority,
@@ -194,6 +197,14 @@ class PayloadBuilder:
194197

195198

196199
def payload_builder(name, schema):
200+
if isinstance(schema, dict):
201+
schema = LegacySchema(
202+
{
203+
voluptuous.Required("implementation"): name,
204+
voluptuous.Optional("os"): str,
205+
}
206+
).extend(schema)
207+
197208
def wrap(func):
198209
assert name not in payload_builders, f"duplicate payload builder name {name}"
199210
payload_builders[name] = PayloadBuilder(schema, func)

src/taskgraph/util/schema.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ def validate_schema(schema, obj, msg_prefix):
4848
# Handle plain Python types (e.g. str, int) via msgspec.convert
4949
elif isinstance(schema, type):
5050
msgspec.convert(obj, schema)
51+
# Handle plain dict schemas (e.g. from downstream payload builders)
52+
elif isinstance(schema, dict):
53+
voluptuous.Schema(schema)(obj)
5154
else:
5255
raise TypeError(f"Unsupported schema type: {type(schema)}")
5356
except (

test/test_transforms_task.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
Tests for the 'task' transforms.
33
"""
44

5+
import unittest
56
from copy import deepcopy
67
from pathlib import Path
78
from pprint import pprint
89

910
import pytest
11+
import voluptuous
1012
from pytest_taskgraph import FakeParameters
1113

1214
from taskgraph.transforms import task
@@ -966,3 +968,38 @@ def test_task_priority(run_transform, graph_config, test_task):
966968
assert task_dict["task"]["priority"] == priority
967969
else:
968970
assert task_dict["task"]["priority"] == graph_config["task-priority"]
971+
972+
973+
class TestPayloadBuilderDictSchema(unittest.TestCase):
974+
"""Regression test: payload_builder must wrap dict schemas with
975+
'implementation' and 'os' keys via LegacySchema.extend(), matching
976+
the v18.1 behavior."""
977+
978+
def test_dict_schema_wraps_implementation_key(self):
979+
"""A dict schema should be extended to require 'implementation'."""
980+
# Clear any previously-registered test builder
981+
task.payload_builders.pop("test-builder", None)
982+
983+
@task.payload_builder("test-builder", schema={"command": [str]})
984+
def _builder(config, task, task_def):
985+
pass
986+
987+
schema = task.payload_builders["test-builder"].schema
988+
assert isinstance(schema, voluptuous.Schema)
989+
990+
# Valid: includes implementation matching the builder name
991+
schema({"implementation": "test-builder", "command": ["echo"]})
992+
993+
# Valid: os is optional
994+
schema({"implementation": "test-builder", "command": ["echo"], "os": "linux"})
995+
996+
# Invalid: wrong implementation value
997+
with self.assertRaises(voluptuous.MultipleInvalid):
998+
schema({"implementation": "wrong-name", "command": ["echo"]})
999+
1000+
# Invalid: missing implementation
1001+
with self.assertRaises(voluptuous.MultipleInvalid):
1002+
schema({"command": ["echo"]})
1003+
1004+
# Cleanup
1005+
task.payload_builders.pop("test-builder", None)

test/test_util_schema.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,16 @@ def test_index_schema_accepts_all_fields(self):
269269
},
270270
"index schema",
271271
)
272+
class TestValidateSchemaDictHandler(unittest.TestCase):
273+
"""validate_schema must accept plain dict schemas passed
274+
by downstream payload builders without raising TypeError."""
275+
276+
def test_dict_schema_valid(self):
277+
validate_schema({"name": str, "count": int}, {"name": "a", "count": 1}, "pfx")
278+
279+
def test_dict_schema_invalid(self):
280+
with self.assertRaises(Exception):
281+
validate_schema({"name": str}, {"name": 123}, "pfx")
272282

273283

274284
def test_optionally_keyed_by():

0 commit comments

Comments
 (0)