Skip to content

Commit 037b193

Browse files
authored
🐛 Backward compatibility test: Don't fail on updating additionalProperties (#15532)
1 parent 10bcd9f commit 037b193

File tree

4 files changed

+64
-14
lines changed

4 files changed

+64
-14
lines changed

airbyte-integrations/bases/source-acceptance-test/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## 0.2.1
4+
Don't fail on updating `additionalProperties`: fix IndexError [#15532](https://github.com/airbytehq/airbyte/pull/15532/)
5+
36
## 0.2.0
47
Finish backward compatibility syntactic tests implementation: check that cursor fields were not changed. [#15520](https://github.com/airbytehq/airbyte/pull/15520/)
58

airbyte-integrations/bases/source-acceptance-test/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ COPY pytest.ini setup.py ./
3333
COPY source_acceptance_test ./source_acceptance_test
3434
RUN pip install .
3535

36-
LABEL io.airbyte.version=0.2.0
36+
LABEL io.airbyte.version=0.2.1
3737
LABEL io.airbyte.name=airbyte/source-acceptance-test
3838

3939
ENTRYPOINT ["python", "-m", "pytest", "-p", "source_acceptance_test.plugin", "-r", "fEsx"]

airbyte-integrations/bases/source-acceptance-test/source_acceptance_test/utils/backward_compatibility.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,12 @@ def assert_is_backward_compatible(self): # pragma: no cover
5151
pass
5252

5353
def check_if_value_of_type_field_changed(self, diff: DeepDiff):
54-
"""Check if a type was changed"""
54+
"""Check if a type was changed on a property"""
5555
# Detect type value change in case type field is declared as a string (e.g "str" -> "int"):
56-
type_values_changed = [change for change in diff.get("values_changed", []) if change.path(output_format="list")[-1] == "type"]
57-
58-
# Detect type value change in case type field is declared as a single item list (e.g ["str"] -> ["int"]):
59-
type_values_changed_in_list = [
60-
change for change in diff.get("values_changed", []) if change.path(output_format="list")[-2] == "type"
56+
changes_on_property_type = [
57+
change for change in diff.get("values_changed", []) if {"properties", "type"}.issubset(change.path(output_format="list"))
6158
]
62-
if type_values_changed or type_values_changed_in_list:
59+
if changes_on_property_type:
6360
self._raise_error("The'type' field value was changed.", diff)
6461

6562
def check_if_new_type_was_added(self, diff: DeepDiff): # pragma: no cover
@@ -75,7 +72,7 @@ def check_if_new_type_was_added(self, diff: DeepDiff): # pragma: no cover
7572

7673
def check_if_type_of_type_field_changed(self, diff: DeepDiff):
7774
"""
78-
Detect the change of type of a type field
75+
Detect the change of type of a type field on a property
7976
e.g:
8077
- "str" -> ["str"] VALID
8178
- "str" -> ["str", "null"] VALID
@@ -85,7 +82,9 @@ def check_if_type_of_type_field_changed(self, diff: DeepDiff):
8582
- ["str"] -> "int" INVALID
8683
- ["str"] -> 1 INVALID
8784
"""
88-
type_changes = [change for change in diff.get("type_changes", []) if change.path(output_format="list")[-1] == "type"]
85+
type_changes = [
86+
change for change in diff.get("type_changes", []) if {"properties", "type"}.issubset(change.path(output_format="list"))
87+
]
8988
for change in type_changes:
9089
# We only accept change on the type field if the new type for this field is list or string
9190
# This might be something already guaranteed by JSON schema validation.
@@ -145,7 +144,9 @@ def check_if_added_a_new_required_property(self, diff: DeepDiff):
145144

146145
def check_if_field_was_made_not_nullable(self, diff: DeepDiff):
147146
"""Detect when field was made not nullable but is still a list: e.g ["string", "null"] -> ["string"]"""
148-
removed_nullable = [change for change in diff.get("iterable_item_removed", []) if change.path(output_format="list")[-2] == "type"]
147+
removed_nullable = [
148+
change for change in diff.get("iterable_item_removed", []) if {"properties", "type"}.issubset(change.path(output_format="list"))
149+
]
149150
if removed_nullable:
150151
self._raise_error("A field type was narrowed or made a field not nullable", diff)
151152

airbyte-integrations/bases/source-acceptance-test/unit_tests/test_backward_compatibility.py

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,54 @@ def as_pytest_param(self):
513513
name="Not changing a spec should not fail",
514514
should_fail=False,
515515
),
516+
Transition(
517+
ConnectorSpecification(
518+
connectionSpecification={
519+
"type": "object",
520+
"required": ["my_required_string"],
521+
"additionalProperties": False,
522+
"properties": {
523+
"my_required_string": {"type": "string"},
524+
},
525+
}
526+
),
527+
ConnectorSpecification(
528+
connectionSpecification={
529+
"type": "object",
530+
"required": ["my_required_string"],
531+
"additionalProperties": True,
532+
"properties": {
533+
"my_required_string": {"type": "string"},
534+
},
535+
}
536+
),
537+
name="Top level: Changing the value of additionalProperties should not fail",
538+
should_fail=False,
539+
),
540+
Transition(
541+
ConnectorSpecification(
542+
connectionSpecification={
543+
"type": "object",
544+
"properties": {
545+
"my_nested_object": {"type": "object", "properties": {"my_property": {"type": ["integer"]}}},
546+
},
547+
}
548+
),
549+
ConnectorSpecification(
550+
connectionSpecification={
551+
"type": "object",
552+
"properties": {
553+
"my_nested_object": {
554+
"type": "object",
555+
"additionalProperties": True,
556+
"properties": {"my_property": {"type": ["integer"]}},
557+
},
558+
},
559+
}
560+
),
561+
name="Nested level: Changing the value of additionalProperties should not fail",
562+
should_fail=False,
563+
),
516564
Transition(
517565
ConnectorSpecification(
518566
connectionSpecification={
@@ -898,7 +946,6 @@ def as_pytest_param(self):
898946
# Checking that all transitions in VALID_SPEC_TRANSITIONS have should_fail = False to prevent typos
899947
assert not all([transition.should_fail for transition in VALID_SPEC_TRANSITIONS])
900948

901-
902949
ALL_SPEC_TRANSITIONS_PARAMS = [transition.as_pytest_param() for transition in FAILING_SPEC_TRANSITIONS + VALID_SPEC_TRANSITIONS]
903950

904951

@@ -920,7 +967,7 @@ def test_spec_backward_compatibility(previous_connector_spec, actual_connector_s
920967
def test_validate_previous_configs(previous_connector_spec, actual_connector_spec, should_fail):
921968
expectation = pytest.raises(NonBackwardCompatibleError) if should_fail else does_not_raise()
922969
with expectation:
923-
validate_previous_configs(previous_connector_spec, actual_connector_spec, 100)
970+
validate_previous_configs(previous_connector_spec, actual_connector_spec, 200)
924971

925972

926973
FAILING_CATALOG_TRANSITIONS = [
@@ -1152,7 +1199,6 @@ def test_validate_previous_configs(previous_connector_spec, actual_connector_spe
11521199
# Checking that all transitions in VALID_CATALOG_TRANSITIONS have should_fail = False to prevent typos
11531200
assert not all([transition.should_fail for transition in VALID_CATALOG_TRANSITIONS])
11541201

1155-
11561202
ALL_CATALOG_TRANSITIONS_PARAMS = [transition.as_pytest_param() for transition in FAILING_CATALOG_TRANSITIONS + VALID_CATALOG_TRANSITIONS]
11571203

11581204

0 commit comments

Comments
 (0)