diff --git a/examples/targets/ibkr/default.example.json b/examples/targets/ibkr/default.example.json index ae65256..6b3c16f 100644 --- a/examples/targets/ibkr/default.example.json +++ b/examples/targets/ibkr/default.example.json @@ -35,7 +35,8 @@ "plugin": "example_notification_plugin", "signal_path": "gs://example-bucket/strategy-artifacts/example_strategy_profile/plugins/example_notification_plugin/latest_signal.json", "enabled": true, - "expected_mode": "shadow" + "expected_mode": "shadow", + "expected_schema_version": "example_notification_plugin.v1" } ], "extra_variables": {} diff --git a/examples/targets/longbridge/sg.example.json b/examples/targets/longbridge/sg.example.json index 09e68e3..973e393 100644 --- a/examples/targets/longbridge/sg.example.json +++ b/examples/targets/longbridge/sg.example.json @@ -36,7 +36,8 @@ "plugin": "example_notification_plugin", "signal_path": "gs://example-bucket/strategy-artifacts/example_strategy_profile/plugins/example_notification_plugin/latest_signal.json", "enabled": true, - "expected_mode": "shadow" + "expected_mode": "shadow", + "expected_schema_version": "example_notification_plugin.v1" } ], "extra_variables": { diff --git a/examples/targets/schwab/live.example.json b/examples/targets/schwab/live.example.json index eb4a05e..438b71f 100644 --- a/examples/targets/schwab/live.example.json +++ b/examples/targets/schwab/live.example.json @@ -35,7 +35,8 @@ "plugin": "example_notification_plugin", "signal_path": "gs://example-bucket/strategy-artifacts/example_strategy_profile/plugins/example_notification_plugin/latest_signal.json", "enabled": true, - "expected_mode": "shadow" + "expected_mode": "shadow", + "expected_schema_version": "example_notification_plugin.v1" } ], "extra_variables": {} diff --git a/schemas/runtime-target.schema.json b/schemas/runtime-target.schema.json index 26268d4..d31d7c9 100644 --- a/schemas/runtime-target.schema.json +++ b/schemas/runtime-target.schema.json @@ -143,6 +143,9 @@ }, "expected_mode": { "type": "string" + }, + "expected_schema_version": { + "type": "string" } } } diff --git a/scripts/runtime_settings.py b/scripts/runtime_settings.py index ab244a5..db175d4 100644 --- a/scripts/runtime_settings.py +++ b/scripts/runtime_settings.py @@ -248,6 +248,12 @@ def validate_plugin_mounts(target: dict[str, Any], errors: list[str]) -> None: if not isinstance(mount.get("enabled"), bool): errors.append(f"plugin_mounts[{index}].enabled must be boolean") + expected_schema_version = mount.get("expected_schema_version") + if expected_schema_version is not None and ( + not isinstance(expected_schema_version, str) or not expected_schema_version.strip() + ): + errors.append(f"plugin_mounts[{index}].expected_schema_version must be a non-empty string") + signal_path = mount.get("signal_path") if not isinstance(signal_path, str) or not signal_path.startswith("gs://"): errors.append(f"plugin_mounts[{index}].signal_path must be a gs:// URI") diff --git a/tests/test_runtime_settings.py b/tests/test_runtime_settings.py index 6e5e7b4..b22543d 100644 --- a/tests/test_runtime_settings.py +++ b/tests/test_runtime_settings.py @@ -49,6 +49,21 @@ def test_example_targets_have_matching_plugin_mount(self): ) ) + def test_plugin_mount_schema_version_is_rendered_for_platform_parser(self): + _, target = self.load_target("examples/targets/schwab/live.example.json") + assignments = {item.name: item.value for item in runtime_settings.build_assignments(target)} + + self.assertIn('"expected_schema_version":"example_notification_plugin.v1"', assignments["SCHWAB_STRATEGY_PLUGIN_MOUNTS_JSON"]) + + def test_plugin_mount_schema_version_must_be_non_empty_string(self): + _, target = self.load_target("examples/targets/schwab/live.example.json") + target["plugin_mounts"][0]["expected_schema_version"] = "" + + self.assertIn( + "plugin_mounts[0].expected_schema_version must be a non-empty string", + runtime_settings.validate_target(target), + ) + def test_generated_variables_cannot_be_overridden(self): _, target = self.load_target("examples/targets/schwab/live.example.json") target["extra_variables"] = {"STRATEGY_PROFILE": "old_strategy"}