Skip to content

Commit 91cfd89

Browse files
authored
feat(connectors-qa): support manifest-only connectors (#43377)
1 parent 6006a4f commit 91cfd89

File tree

10 files changed

+109
-21
lines changed

10 files changed

+109
-21
lines changed

airbyte-ci/connectors/connectors_qa/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ poe lint
108108

109109
## Changelog
110110

111+
### 1.6.0
112+
113+
Added `manifest-only` connectors support — they will run basic assets and metadata checks.
114+
111115
### 1.5.1
112116

113117
Bumped dependencies.

airbyte-ci/connectors/connectors_qa/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "connectors-qa"
3-
version = "1.5.1"
3+
version = "1.6.0"
44
description = "A package to run QA checks on Airbyte connectors, generate reports and documentation."
55
authors = ["Airbyte <[email protected]>"]
66
readme = "README.md"

airbyte-ci/connectors/connectors_qa/src/connectors_qa/checks/metadata.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
22

3-
43
import os
54
from datetime import datetime, timedelta
65

@@ -40,8 +39,11 @@ class CheckConnectorLanguageTag(MetadataCheck):
4039

4140
PYTHON_LANGUAGE_TAG = "language:python"
4241
JAVA_LANGUAGE_TAG = "language:java"
42+
MANIFEST_ONLY_LANGUAGE_TAG = "language:manifest-only"
4343

4444
def get_expected_language_tag(self, connector: Connector) -> str:
45+
if (connector.code_directory / "manifest.yaml").exists():
46+
return self.MANIFEST_ONLY_LANGUAGE_TAG
4547
if (connector.code_directory / consts.SETUP_PY_FILE_NAME).exists() or (
4648
connector.code_directory / consts.PYPROJECT_FILE_NAME
4749
).exists():
@@ -145,7 +147,6 @@ class ValidateBreakingChangesDeadlines(MetadataCheck):
145147
minimum_days_until_deadline = 7
146148

147149
def _run(self, connector: Connector) -> CheckResult:
148-
149150
# fetch the current branch version of the connector first.
150151
# we'll try and see if there are any breaking changes associated
151152
# with it next.

airbyte-ci/connectors/connectors_qa/src/connectors_qa/checks/packaging.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
22

3-
43
import semver
54
import toml
65
from connector_ops.utils import Connector, ConnectorLanguage # type: ignore
@@ -63,6 +62,24 @@ def _run(self, connector: Connector) -> CheckResult:
6362
return self.create_check_result(connector=connector, passed=True, message="PyPi publishing is enabled")
6463

6564

65+
class CheckManifestOnlyConnectorBaseImage(PackagingCheck):
66+
name = "Manifest-only connectors must use `source-declarative-manifest` as their base image"
67+
description = "Manifest-only connectors must use `airbyte/source-declarative-manifest` as their base image."
68+
applies_to_connector_languages = [ConnectorLanguage.MANIFEST_ONLY]
69+
70+
def _run(self, connector: Connector) -> CheckResult:
71+
base_image = get(connector.metadata, "connectorBuildOptions.baseImage")
72+
base_image_name = base_image.split(":")[0] if base_image else None
73+
74+
if base_image_name != "docker.io/airbyte/source-declarative-manifest":
75+
return self.create_check_result(
76+
connector=connector,
77+
passed=False,
78+
message=f"A manifest-only connector must use `source-declarative-manifest` base image. Replace the base image in {consts.METADATA_FILE_NAME} file",
79+
)
80+
return self.create_check_result(connector=connector, passed=True, message="Connector uses source-declarative-manifest base image")
81+
82+
6683
class CheckConnectorLicense(PackagingCheck):
6784
name = "Connectors must be licensed under MIT or Elv2"
6885
description = f"Connectors must be licensed under the MIT or Elv2 license. This is to ensure that all connectors are licensed under a permissive license. More details in our [License FAQ]({consts.LICENSE_FAQ_URL})."
@@ -218,4 +235,5 @@ def _run(self, connector: Connector) -> CheckResult:
218235
CheckVersionFollowsSemver(),
219236
CheckConnectorVersionMatchInPyproject(),
220237
CheckPublishToPyPiIsEnabled(),
238+
CheckManifestOnlyConnectorBaseImage(),
221239
]

airbyte-ci/connectors/connectors_qa/src/connectors_qa/checks/security.py

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class CheckConnectorUsesPythonBaseImage(SecurityCheck):
122122
applies_to_connector_languages = [
123123
ConnectorLanguage.PYTHON,
124124
ConnectorLanguage.LOW_CODE,
125+
ConnectorLanguage.MANIFEST_ONLY,
125126
]
126127

127128
def _run(self, connector: Connector) -> CheckResult:

airbyte-ci/connectors/connectors_qa/src/connectors_qa/consts.py

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
LOW_CODE_MANIFEST_FILE_NAME = "manifest.yaml"
1414
METADATA_DOCUMENTATION_URL = "https://docs.airbyte.com/connector-development/connector-metadata-file"
1515
METADATA_FILE_NAME = "metadata.yaml"
16+
MANIFEST_FILE_NAME = "manifest.yaml"
1617
POETRY_LOCK_FILE_NAME = "poetry.lock"
1718
PYPROJECT_FILE_NAME = "pyproject.toml"
1819
SEMVER_FOR_CONNECTORS_DOC_URL = "https://docs.airbyte.com/contributing-to-airbyte/#semantic-versioning-for-connectors"

airbyte-ci/connectors/connectors_qa/src/connectors_qa/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
ConnectorLanguage.JAVA,
1818
ConnectorLanguage.LOW_CODE,
1919
ConnectorLanguage.PYTHON,
20+
ConnectorLanguage.MANIFEST_ONLY,
2021
]
2122

2223
ALL_TYPES = ["source", "destination"]
@@ -62,7 +63,6 @@ def __repr__(self) -> str:
6263

6364

6465
class Check(ABC):
65-
6666
requires_metadata: bool = True
6767
runs_on_released_connectors: bool = True
6868

airbyte-ci/connectors/connectors_qa/tests/unit_tests/test_checks/test_metadata.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
2+
from __future__ import annotations
23

34
import os
45

@@ -9,7 +10,6 @@
910

1011

1112
class TestValidateMetadata:
12-
1313
def test_fail_when_deserialization_fails(self, mocker, tmp_path):
1414
# Arrange
1515
mocker.patch.object(metadata, "validate_and_load", return_value=(None, "error"))
@@ -38,6 +38,19 @@ def test_pass_when_metadata_file_is_valid(self, mocker, tmp_path):
3838
assert result.status == CheckStatus.PASSED
3939
assert result.message == "Metadata file valid."
4040

41+
def test_checks_apply_to_manifest_only_connectors(self, mocker, tmp_path):
42+
# Arrange
43+
connector = mocker.MagicMock(metadata={"tags": ["language:manifest-only"]}, code_directory=tmp_path)
44+
code_directory = tmp_path
45+
(code_directory / consts.MANIFEST_FILE_NAME).touch()
46+
47+
# Act
48+
result = metadata.CheckConnectorLanguageTag()._run(connector)
49+
50+
# Assert
51+
assert result.status == CheckStatus.PASSED
52+
assert result.message == "Language tag language:manifest-only is present in the metadata file"
53+
4154

4255
class TestCheckConnectorLanguageTag:
4356
def test_fail_when_no_language_tags(self, mocker):
@@ -118,7 +131,6 @@ def test_pass_when_java(self, mocker, tmp_path):
118131

119132

120133
class TestCheckConnectorCDKTag:
121-
122134
def test_fail_when_no_cdk_tags(self, mocker):
123135
# Arrange
124136
connector = mocker.MagicMock(metadata={"tags": []})
@@ -160,7 +172,7 @@ def test_fail_when_python_tag_on_low_code_connector(self, mocker, tmp_path):
160172
connector = mocker.MagicMock(technical_name="source-test", metadata={"tags": ["cdk:python"]}, code_directory=tmp_path)
161173
code_directory = tmp_path
162174
(code_directory / "source_test").mkdir()
163-
(code_directory / "source_test"/ consts.LOW_CODE_MANIFEST_FILE_NAME).touch()
175+
(code_directory / "source_test" / consts.LOW_CODE_MANIFEST_FILE_NAME).touch()
164176

165177
# Act
166178
result = metadata.CheckConnectorCDKTag()._run(connector)

airbyte-ci/connectors/connectors_qa/tests/unit_tests/test_checks/test_packaging.py

+42
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
2+
from __future__ import annotations
23

34
from connectors_qa import consts
45
from connectors_qa.checks import packaging
@@ -57,6 +58,47 @@ def test_pass_when_poetry_is_used(self, tmp_path, mocker):
5758
assert result.message == "Poetry is used for dependency management"
5859

5960

61+
class TestCheckManifestOnlyConnectorBaseImage:
62+
def test_pass_with_source_declarative_manifest(self, mocker, tmp_path):
63+
connector = mocker.MagicMock(
64+
code_directory=tmp_path,
65+
metadata={"connectorBuildOptions": {"baseImage": "docker.io/airbyte/source-declarative-manifest:4.3.0@SHA"}},
66+
)
67+
68+
# Act
69+
result = packaging.CheckManifestOnlyConnectorBaseImage()._run(connector)
70+
71+
# Assert
72+
assert result.status == CheckStatus.PASSED
73+
assert "Connector uses source-declarative-manifest base image" in result.message
74+
75+
def test_fail_with_different_image(self, mocker, tmp_path):
76+
connector = mocker.MagicMock(
77+
code_directory=tmp_path,
78+
metadata={"connectorBuildOptions": {"baseImage": "docker.io/airbyte/connector-base-image:2.0.0@SHA"}},
79+
)
80+
81+
# Act
82+
result = packaging.CheckManifestOnlyConnectorBaseImage()._run(connector)
83+
84+
# Assert
85+
assert result.status == CheckStatus.FAILED
86+
assert "A manifest-only connector must use `source-declarative-manifest` base image" in result.message
87+
88+
def test_fail_with_missing_image(self, mocker, tmp_path):
89+
connector = mocker.MagicMock(
90+
code_directory=tmp_path,
91+
metadata={"connectorBuildOptions": {}},
92+
)
93+
94+
# Act
95+
result = packaging.CheckManifestOnlyConnectorBaseImage()._run(connector)
96+
97+
# Assert
98+
assert result.status == CheckStatus.FAILED
99+
assert "A manifest-only connector must use `source-declarative-manifest` base image" in result.message
100+
101+
60102
class TestCheckPublishToPyPiIsEnabled:
61103
def test_fail_if_publish_to_pypi_is_not_enabled(self, mocker):
62104
# Arrange

docs/contributing-to-airbyte/resources/qa-checks.md

+22-13
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ They are by no mean replacing the need for a manual review of the connector code
1111
### Breaking changes must be accompanied by a migration guide
1212

1313
_Applies to the following connector types: source, destination_
14-
_Applies to the following connector languages: java, low-code, python_
14+
_Applies to the following connector languages: java, low-code, python, manifest-only_
1515
_Applies to connector with any support level_
1616
_Applies to connector with any Airbyte usage level_
1717

@@ -21,7 +21,7 @@ This document should contain a section for each breaking change, in order of the
2121
### Connectors must have user facing documentation
2222

2323
_Applies to the following connector types: source, destination_
24-
_Applies to the following connector languages: java, low-code, python_
24+
_Applies to the following connector languages: java, low-code, python, manifest-only_
2525
_Applies to connector with any support level_
2626
_Applies to connector with any Airbyte usage level_
2727

@@ -30,7 +30,7 @@ The user facing connector documentation should be stored under `./docs/integrati
3030
### Connectors must have a changelog entry for each version
3131

3232
_Applies to the following connector types: source, destination_
33-
_Applies to the following connector languages: java, low-code, python_
33+
_Applies to the following connector languages: java, low-code, python, manifest-only_
3434
_Applies to connector with any support level_
3535
_Applies to connector with any Airbyte usage level_
3636

@@ -41,7 +41,7 @@ Each new version of a connector must have a changelog entry defined in the user
4141
### Connectors must have valid metadata.yaml file
4242

4343
_Applies to the following connector types: source, destination_
44-
_Applies to the following connector languages: java, low-code, python_
44+
_Applies to the following connector languages: java, low-code, python, manifest-only_
4545
_Applies to connector with any support level_
4646
_Applies to connector with any Airbyte usage level_
4747

@@ -50,7 +50,7 @@ Connectors must have a `metadata.yaml` file at the root of their directory. This
5050
### Connector must have a language tag in metadata
5151

5252
_Applies to the following connector types: source, destination_
53-
_Applies to the following connector languages: java, low-code, python_
53+
_Applies to the following connector languages: java, low-code, python, manifest-only_
5454
_Applies to connector with any support level_
5555
_Applies to connector with any Airbyte usage level_
5656

@@ -68,7 +68,7 @@ Python connectors must have a CDK tag in their metadata. It must be set in the `
6868
### Breaking change deadline should be a week in the future
6969

7070
_Applies to the following connector types: source, destination_
71-
_Applies to the following connector languages: java, low-code, python_
71+
_Applies to the following connector languages: java, low-code, python, manifest-only_
7272
_Applies to connector with any support level_
7373
_Applies to connector with any Airbyte usage level_
7474

@@ -77,7 +77,7 @@ If the connector version has a breaking change, the deadline field must be set t
7777
### Certified source connector must have a value filled out for maxSecondsBetweenMessages in metadata
7878

7979
_Applies to the following connector types: source_
80-
_Applies to the following connector languages: java, low-code, python_
80+
_Applies to the following connector languages: java, low-code, python, manifest-only_
8181
_Applies to connector with certified support level_
8282
_Applies to connector with any Airbyte usage level_
8383

@@ -97,7 +97,7 @@ Connectors must use [Poetry](https://python-poetry.org/) for dependency manageme
9797
### Connectors must be licensed under MIT or Elv2
9898

9999
_Applies to the following connector types: source, destination_
100-
_Applies to the following connector languages: java, low-code, python_
100+
_Applies to the following connector languages: java, low-code, python, manifest-only_
101101
_Applies to connector with any support level_
102102
_Applies to connector with any Airbyte usage level_
103103

@@ -115,7 +115,7 @@ Connectors license in metadata.yaml and pyproject.toml file must match. This is
115115
### Connector version must follow Semantic Versioning
116116

117117
_Applies to the following connector types: source, destination_
118-
_Applies to the following connector languages: java, low-code, python_
118+
_Applies to the following connector languages: java, low-code, python, manifest-only_
119119
_Applies to connector with any support level_
120120
_Applies to connector with any Airbyte usage level_
121121

@@ -139,12 +139,21 @@ _Applies to connector with any Airbyte usage level_
139139

140140
Python connectors must have [PyPi](https://pypi.org/) publishing enabled in their `metadata.yaml` file. This is declared by setting `remoteRegistries.pypi.enabled` to `true` in metadata.yaml. This is to ensure that all connectors can be published to PyPi and can be used in `PyAirbyte`.
141141

142+
### Manifest-only connectors must use `source-declarative-manifest` as their base image
143+
144+
_Applies to the following connector types: source, destination_
145+
_Applies to the following connector languages: manifest-only_
146+
_Applies to connector with any support level_
147+
_Applies to connector with any Airbyte usage level_
148+
149+
Manifest-only connectors must use `airbyte/source-declarative-manifest` as their base image.
150+
142151
## 💼 Assets
143152

144153
### Connectors must have an icon
145154

146155
_Applies to the following connector types: source, destination_
147-
_Applies to the following connector languages: java, low-code, python_
156+
_Applies to the following connector languages: java, low-code, python, manifest-only_
148157
_Applies to connector with any support level_
149158
_Applies to connector with any Airbyte usage level_
150159

@@ -155,7 +164,7 @@ Each connector must have an icon available in at the root of the connector code
155164
### Connectors must use HTTPS only
156165

157166
_Applies to the following connector types: source, destination_
158-
_Applies to the following connector languages: java, low-code, python_
167+
_Applies to the following connector languages: java, low-code, python, manifest-only_
159168
_Applies to connector with any support level_
160169
_Applies to connector with any Airbyte usage level_
161170

@@ -164,7 +173,7 @@ Connectors must use HTTPS only when making requests to external services.
164173
### Python connectors must not use a Dockerfile and must declare their base image in metadata.yaml file
165174

166175
_Applies to the following connector types: source, destination_
167-
_Applies to the following connector languages: python, low-code_
176+
_Applies to the following connector languages: python, low-code, manifest-only_
168177
_Applies to connector with any support level_
169178
_Applies to connector with any Airbyte usage level_
170179

@@ -176,7 +185,7 @@ This is to ensure that all connectors use a base image which is maintained and h
176185
### Medium to High Use Connectors must enable acceptance tests
177186

178187
_Applies to the following connector types: source_
179-
_Applies to the following connector languages: java, low-code, python_
188+
_Applies to the following connector languages: java, low-code, python, manifest-only_
180189
_Applies to connector with any support level_
181190
_Applies to connector with medium, high Airbyte usage level_
182191

0 commit comments

Comments
 (0)