Skip to content

feat: add any_of strategy to CheckStream for dynamic check stream selection#997

Draft
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1776813694-check-stream-any-of-strategy
Draft

feat: add any_of strategy to CheckStream for dynamic check stream selection#997
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1776813694-check-stream-any-of-strategy

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

Summary

Adds a new optional strategy field on the low-code CheckStream component so that manifest authors can list multiple candidate check streams and have the check pass as soon as any of them is available, rather than requiring every listed stream to be available.

This is phase 1 from airbytehq/airbyte-internal-issues#16231 ("Option 1 — any_of strategy on CheckStream"), the recommended starting point in the design discussion. It unblocks the permission-scope class of check failures (HubSpot, Salesforce, GitHub org-scoped tokens, etc.) without requiring any protocol changes.

Resolves airbytehq/airbyte-internal-issues#16231:

What changed

  • CheckStream gains an optional strategy field with two values:
    • all (default) — current behavior: every listed stream must be available.
    • any_of — passes on the first available stream (short-circuits), and only fails if every listed stream is unavailable. Failure message aggregates the per-stream reasons so users can see why each candidate was rejected.
  • Manifest schema (declarative_component_schema.yaml) and the generated pydantic model (declarative_component_schema.py) were updated to expose the new field.
  • model_to_component_factory.create_check_stream threads the new field through.
  • Dynamic stream check semantics are unchanged — per the open question in the issue, strategy only affects static stream_names; dynamic_streams_check_configs continue to use all-style semantics within a group.

Declarative-First Evaluation

This change is a declarative-first improvement: it extends the existing CheckStream declarative component with a new field rather than introducing any custom Python component. No custom component is added, introduced, or required. The new behavior is entirely opt-in via manifest.

Breaking Change Evaluation

Not breaking. The new field is optional and defaults to all, which is identical to the pre-change behavior. No schema, spec, stream, or state format changes. Standard non-breaking versioning applies (the CDK uses semantic-pr-release-drafter driven by the feat: prefix, so this will land as a MINOR bump).

Test Coverage

Added unit tests in unit_tests/sources/declarative/checks/test_check_stream.py:

  • test_check_stream_strategy_defaults_to_all — default preserved
  • test_check_stream_rejects_unsupported_strategy — validation for unknown values
  • test_check_stream_any_of_returns_success_when_first_stream_is_available — short-circuits on first success
  • test_check_stream_any_of_returns_success_when_later_stream_is_available
  • test_check_stream_any_of_fails_only_when_all_streams_are_unavailable — aggregated failure message references each rejected candidate
  • test_check_stream_all_strategy_fails_if_any_stream_is_unavailableall semantics preserved

And factory-level tests in test_model_to_component_factory.py:

  • test_create_check_stream — strategy defaults to "all" when the manifest omits the field
  • test_create_check_stream_with_any_of_strategy — manifest strategy: any_of round-trips through the factory

All 39 tests in unit_tests/sources/declarative/checks/test_check_stream.py pass locally. Ruff check/format and mypy are clean on the touched files.

Review & Testing Checklist for Human

  • Confirm the strategy enum + default on CheckStream in declarative_component_schema.yaml matches the design intent from airbytehq/airbyte-internal-issues#16231 (phase 1).
  • Verify the aggregated any_of failure message format is acceptable for end users (currently: None of the configured check streams were available. Stream X is not available: ...; Stream Y is not available: ...).
  • Sanity-check that the pydantic model edit in declarative_component_schema.py is equivalent to what bin/generate-component-manifest-dagger.sh would regenerate from the YAML — I couldn't run the Dagger-based regeneration in this environment, so I mirrored the existing pattern used for ScopesJoinStrategy manually.
  • Optional: try adopting strategy: any_of on one of the connectors cited in the issue (HubSpot / Salesforce / GitHub) to validate the end-to-end UX.

Notes

  • Stream-name validation (stream_name not in source.streams(config)) is kept as-is for both strategies: if a manifest author lists a stream that is not part of the resolved catalog, we still raise ValueError. This is a manifest-author bug, distinct from the user-side availability problem the any_of strategy targets.
  • Phases 2 and 3 from the issue (per-stream use_for_check tag, and the protocol-level configured_catalog change) are intentionally left for follow-up PRs per the proposed phasing in the issue.

Link to Devin session: https://app.devin.ai/sessions/aad1e769a24649299440898c94ce2a03

…ection

Adds a new optional 'strategy' field on the low-code CheckStream component.

- strategy: all (default) preserves existing behavior: every listed
  stream must be available for the check to pass.
- strategy: any_of passes as soon as any listed stream is available,
  and only fails if every listed stream is unavailable. Short-circuits
  on the first success, aggregates failure reasons otherwise.

This unblocks connectors where different users have scope for
different streams (e.g. permission-scoped OAuth tokens) and a single
hardcoded check stream would otherwise produce misleading failures.

Resolves airbytehq/airbyte-internal-issues#16231

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@github-actions
Copy link
Copy Markdown

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

Testing This CDK Version

You 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@devin/1776813694-check-stream-any-of-strategy#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 devin/1776813694-check-stream-any-of-strategy

PR Slash Commands

Airbyte Maintainers can execute the following slash commands on your PR:

  • /autofix - Fixes most formatting and linting issues
  • /poetry-lock - Updates poetry.lock file
  • /test - Runs connector tests with the updated CDK
  • /prerelease - Triggers a prerelease publish with default arguments
  • /poe build - Regenerate git-committed build artifacts, such as the pydantic models which are generated from the manifest JSON schema in YAML.
  • /poe <command> - Runs any poe command in the CDK environment
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

@github-actions
Copy link
Copy Markdown

PyTest Results (Fast)

4 029 tests  +7   4 018 ✅ +7   7m 56s ⏱️ +10s
    1 suites ±0      11 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 2c4c3bf. ± Comparison against base commit fd553bd.

@github-actions
Copy link
Copy Markdown

PyTest Results (Full)

4 032 tests  +7   4 020 ✅ +7   11m 21s ⏱️ +34s
    1 suites ±0      12 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 2c4c3bf. ± Comparison against base commit fd553bd.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants