Repository navigation
feat(cdk): section-aware CHECK for the stepped setup form (check-section) - #1255
Conversation
A connector whose spec declares `sections` (each listing the `groups` of properties it shows) can be checked one section at a time. The config JSON then carries a top-level `check-section` key naming the section and only holds the fields collected up to that section. The entrypoint resolves the key against the spec: no key keeps today's full check; an unknown section, a non-string value or a spec without sections fail with a config error; the last section runs the full check because the configuration is complete by then; any other section is delegated to the connector's new `check_section`. The partial config is validated against the spec narrowed to the section (`required` keeps the properties whose group belongs to that section or an earlier one). `BaseConnector.check_section` fails with a system error unless the connector overrides it; `AbstractSource.check_section` wraps a new `check_section_connection`, the counterpart of `check_connection`.
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This CDK VersionYou can test this version of the CDK using the following: # Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/airbyte-python-cdk.git@feat/check-section#egg=airbyte-python-cdk[dev]' --help
# Update a connector to use the CDK from this branch ref:
cd airbyte-integrations/connectors/source-example
poe use-cdk-branch feat/check-sectionPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
PyTest Results (Fast)6 297 tests +222 6 275 ✅ +231 5m 59s ⏱️ - 3m 37s Results for commit 33341e3. ± Comparison against base commit 61ddc6a. This pull request removes 5 and adds 227 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
PyTest Results (Full)6 300 tests +222 6 278 ✅ +231 12m 0s ⏱️ + 3m 37s Results for commit 33341e3. ± Comparison against base commit 61ddc6a. This pull request removes 5 and adds 227 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A section check validates the partial config against the spec narrowed to the section, but root-level `oneOf`, `anyOf`, `allOf`, `not`, `if`/`then`/`else`, `dependencies`, `dependentRequired` and `dependentSchemas` can still require fields of later sections and blocked the check before the connector ran. The narrowed spec now drops those keywords; every present field keeps its own schema and the full check applies the constraints again. Also documents and tests that a null `check-section` is rejected like any other non-string value.
The default `check_section` returned nothing but a raise while declaring an `AirbyteConnectionStatus`; it now returns a failed status naming the missing implementation, and `check_section_connection` reuses that message as its (False, error) tuple. This also removes the local import of AirbyteTracedException in connector.py. The config error helper in check_section.py is inlined.
|
Patrick Nilan (@pnilan) I marked it as ready for review to get Devin’s AI review while I’m still fixing things, but thanks for taking an early look! |
Both defaults now build their message from one constant, CHECK_SECTION_NOT_IMPLEMENTED, instead of AbstractSource reaching into BaseConnector for it, and the docstrings describe the two methods as the section counterparts of check and check_connection.
A section declares `"check": true` when the platform should run a CHECK with `check-section` once the user completes it. `requested_section` rejects a section without the flag with a config error, so a section which exists for layout only (such as a final review step covered by the full check before creation) is never checked on its own.
A declarative source validates a configuration by reading from the streams its `check` component names, so `check_section` runs that same check on the configuration collected so far. Manifest-only connectors can then declare `sections` in their spec without any Python code; the manifest is responsible for ordering the sections so that the checked ones already hold every field the check streams need.
The webapp shows the sections which declare a numeric `order` first, sorted by it, and the others in list order after them. The section helpers took the list position as the order, so a spec listing its sections out of `order` would require a later step's fields on the first step and could take the lowest-`order` section for the last one. `_sections` now sorts the same way the webapp does, and `section_spec` walks that sorted list. Tests cover sections listed out of `order` and sections without one.
What
CDK side of the stepped setup form: CHECK becomes section-aware.
A connector whose spec declares
sectionsnext togroups(each section listing the groups of properties it shows, in form order) can be checked one section at a time. The configuration JSON then carries a top-levelcheck-sectionkey naming the section, and only holds the fields of that section and of the sections before it. Without the key, CHECK is exactly today's full check.A section declares
"check": truewhen the platform should run a CHECK withcheck-sectiononce the user completes it. A section without the flag exists for layout only and is never checked on its own: the platform never sends its id, and the connector rejects it with a config error if it does. The typical case is a final review step, which the full check before creating the source covers anyway.check-sectionsource.check(config), unchangedsource.check(config)without the key: the configuration is complete by thensource.check_section(section, config)without the keysectionsCONNECTION_STATUSwith a config error naming the declared sections"check": trueCONNECTION_STATUSwith a config error saying the section has no checkBefore any of that, the partial config is validated against the spec narrowed to the section:
requiredonly keeps the properties whosegroupbelongs to that section or to an earlier one, and every property keeps its own schema, so the present fields are still validated in full.How
airbyte_cdk/sources/utils/check_section.py:CHECK_SECTION_KEY,declared_sections,checkable_sections,requested_section,is_last_section,strip_check_section,section_spec.AirbyteEntrypoint.check: resolves the section, narrows the validation, dispatches (_check).discoverandreadare untouched.BaseConnector.check_section(logger, section, config): new hook, fails with asystem_errorunless the connector overrides it, so a spec declaring sections without an implementation is loud.AbstractSource.check_sectionwraps a newcheck_section_connection(logger, section, config) -> (bool, error), the counterpart ofcheck_connection, so sources keep the tuple-returning style.ConcurrentDeclarativeSource.check_sectionruns the manifest'scheckcomponent on the partial configuration: a declarative source validates by reading its check streams, so manifest-only connectors declaresectionsin their spec without any Python code (feat(source-google-sheets): stepped setup form sections and section-aware CHECK airbyte#90237, feat(source-linkedin-ads): stepped setup form sections and section-aware CHECK airbyte#90238).The contract for implementations: validate the fields of the section, the fields of earlier sections it depends on, and the server-side prerequisites those fields describe, and nothing beyond; report a missing or invalid field through a config error naming it. The spec orders sections so that no section relies on a later one.
Tests
unit_tests/sources/utils/test_check_section.py: section resolution (absent, declared, unknown, non-string, no sections, section withoutcheck), last section, key stripping,requirednarrowing (first, middle and last section; other spec fields kept), root cross-property constraints dropped.unit_tests/test_entrypoint.py:checkend to end with a sectioned spec: delegation with the partial config, full check for the last section, failure ofcheck_sectionreported as a failed status, system error when the source does not implement it, narrowed validation still rejecting a missing section field, full validation without the key, invalid section values, spec without sections.unit_tests/sources/test_abstract_source.py:check_sectionwrapscheck_section_connection; default is a system error.unit_tests/sources/declarative/test_concurrent_declarative_source.py:check_sectionruns the declared check on the partial config and returns its status.Consumers: source-s3 (airbytehq/airbyte#90132), source-facebook-marketing (#90231), source-salesforce (#90232), source-shopify (#90233), and the manifest-only source-google-sheets (#90237) and source-linkedin-ads (#90238).
🤖 Generated with Claude Code