Skip to content

Commit f46aaff

Browse files
SATS: fix backwards compatibility (#16429)
* SATS: fix backwards compatibility * #16429 source acceptance tests: modify validation for specs only * #16429 source acceptance tests: add typing * SATs: fix changelog Co-authored-by: Augustin <[email protected]>
1 parent 0ab777f commit f46aaff

File tree

4 files changed

+63
-9
lines changed

4 files changed

+63
-9
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.3
4+
Backward compatibility tests: improve `check_if_type_of_type_field_changed` to make it less radical when validating specs and allow `'str' -> ['str', '<another_type>']` type changes.[#16429](https://github.com/airbytehq/airbyte/pull/16429/)
5+
36
## 0.2.2
47
Backward compatibility tests: improve `check_if_cursor_field_was_changed` to make it less radical and allow stream addition to catalog.[#15835](https://github.com/airbytehq/airbyte/pull/15835/)
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.2
36+
LABEL io.airbyte.version=0.2.3
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: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def check_if_new_type_was_added(self, diff: DeepDiff): # pragma: no cover
7070
if new_values_in_type_list:
7171
self._raise_error("A new value was added to a 'type' field")
7272

73-
def check_if_type_of_type_field_changed(self, diff: DeepDiff):
73+
def check_if_type_of_type_field_changed(self, diff: DeepDiff, allow_type_widening: bool = False):
7474
"""
7575
Detect the change of type of a type field on a property
7676
e.g:
@@ -91,11 +91,20 @@ def check_if_type_of_type_field_changed(self, diff: DeepDiff):
9191
if isinstance(change.t1, str):
9292
if not isinstance(change.t2, list):
9393
self._raise_error("A 'type' field was changed from string to an invalid value.", diff)
94-
# If the new type field is a list we want to make sure it only has the original type (t1) and null: e.g. "str" -> ["str", "null"]
95-
# We want to raise an error otherwise.
96-
t2_not_null_types = [_type for _type in change.t2 if _type != "null"]
97-
if not (len(t2_not_null_types) == 1 and t2_not_null_types[0] == change.t1):
98-
self._raise_error("The 'type' field was changed to a list with multiple invalid values", diff)
94+
if allow_type_widening:
95+
# If the new type field is a list we want to make sure it contains the original type (t1):
96+
# e.g. "str" -> ["str", "null"]
97+
# "int" -> ["int", "str"]
98+
# We want to raise an error otherwise.
99+
if change.t1 not in change.t2:
100+
self._raise_error("The 'type' field was changed to a list which does not contain previous type", diff)
101+
else:
102+
# If the new type field is a list we want to make sure it only has the original type (t1)
103+
# and null: e.g. "str" -> ["str", "null"]
104+
# We want to raise an error otherwise.
105+
t2_not_null_types = [_type for _type in change.t2 if _type != "null"]
106+
if not (len(t2_not_null_types) == 1 and t2_not_null_types[0] == change.t1):
107+
self._raise_error("The 'type' field was changed to a list with multiple invalid values", diff)
99108
if isinstance(change.t1, list):
100109
if not isinstance(change.t2, str):
101110
self._raise_error("The 'type' field was changed from a list to an invalid value", diff)
@@ -121,7 +130,7 @@ def assert_is_backward_compatible(self):
121130
self.check_if_added_a_new_required_property(self.connection_specification_diff)
122131
self.check_if_value_of_type_field_changed(self.connection_specification_diff)
123132
# self.check_if_new_type_was_added(self.connection_specification_diff) We want to allow type expansion atm
124-
self.check_if_type_of_type_field_changed(self.connection_specification_diff)
133+
self.check_if_type_of_type_field_changed(self.connection_specification_diff, allow_type_widening=True)
125134
self.check_if_field_was_made_not_nullable(self.connection_specification_diff)
126135
self.check_if_enum_was_narrowed(self.connection_specification_diff)
127136
self.check_if_declared_new_enum_field(self.connection_specification_diff)
@@ -213,7 +222,7 @@ def compute_diffs(self):
213222
def assert_is_backward_compatible(self):
214223
self.check_if_stream_was_removed(self.streams_json_schemas_diff)
215224
self.check_if_value_of_type_field_changed(self.streams_json_schemas_diff)
216-
self.check_if_type_of_type_field_changed(self.streams_json_schemas_diff)
225+
self.check_if_type_of_type_field_changed(self.streams_json_schemas_diff, allow_type_widening=False)
217226
self.check_if_cursor_field_was_changed(self.streams_cursor_fields_diff)
218227

219228
def check_if_stream_was_removed(self, diff: DeepDiff):

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,26 @@ def as_pytest_param(self):
939939
name="Nested level: Removing the enum field should not fail.",
940940
should_fail=False,
941941
),
942+
Transition(
943+
ConnectorSpecification(
944+
connectionSpecification={
945+
"type": "object",
946+
"properties": {
947+
"my_string": {"type": "integer"},
948+
},
949+
}
950+
),
951+
ConnectorSpecification(
952+
connectionSpecification={
953+
"type": "object",
954+
"properties": {
955+
"my_string": {"type": ["integer", "string"]},
956+
},
957+
}
958+
),
959+
name="Changing a 'type' field from a string to a list containing that same string should not fail.",
960+
should_fail=False,
961+
),
942962
]
943963

944964
# Checking that all transitions in FAILING_SPEC_TRANSITIONS have should_fail == True to prevent typos
@@ -1131,6 +1151,28 @@ def test_validate_previous_configs(previous_connector_spec, actual_connector_spe
11311151
),
11321152
},
11331153
),
1154+
Transition(
1155+
name="Changing a 'type' field from a string to something else than a list containing just that string and null should fail.",
1156+
should_fail=True,
1157+
previous={
1158+
"test_stream": AirbyteStream.parse_obj(
1159+
{
1160+
"name": "test_stream",
1161+
"json_schema": {"properties": {"user": {"type": "object", "properties": {"username": {"type": "integer"}}}}},
1162+
"default_cursor_field": ["a"],
1163+
}
1164+
),
1165+
},
1166+
current={
1167+
"test_stream": AirbyteStream.parse_obj(
1168+
{
1169+
"name": "test_stream",
1170+
"json_schema": {"properties": {"user": {"type": "object", "properties": {"username": {"type": ["integer", "string"]}}}}},
1171+
"default_cursor_field": ["b"],
1172+
}
1173+
),
1174+
},
1175+
)
11341176
]
11351177

11361178
VALID_CATALOG_TRANSITIONS = [

0 commit comments

Comments
 (0)