1
0
mirror of synced 2025-12-25 02:09:19 -05:00

Source Stripe: Update CDK version to prepare for low-code migration (#49940)

Co-authored-by: Serhii Lazebnyi <53845333+lazebnyi@users.noreply.github.com>
Co-authored-by: Serhii Lazebnyi <serhii.lazebnyi@globallogic.com>
This commit is contained in:
Maxime Carbonneau-Leclerc
2025-02-04 08:09:01 -05:00
committed by GitHub
parent 3ba67876c1
commit 6bc2e03ff4
12 changed files with 856 additions and 437 deletions

View File

@@ -10,7 +10,7 @@ data:
connectorSubtype: api
connectorType: source
definitionId: e094cb9a-26de-4645-8761-65c0c425d1de
dockerImageTag: 5.8.3
dockerImageTag: 5.8.4
dockerRepository: airbyte/source-stripe
documentationUrl: https://docs.airbyte.com/integrations/sources/stripe
erdUrl: https://dbdocs.io/airbyteio/source-stripe?view=relationships

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
version = "5.8.3"
version = "5.8.4"
name = "source-stripe"
description = "Source implementation for Stripe."
authors = [ "Airbyte <contact@airbyte.io>",]
@@ -18,7 +18,7 @@ include = "source_stripe"
[tool.poetry.dependencies]
python = "^3.10,<3.12"
pendulum = "==2.1.2"
airbyte-cdk = "^5"
airbyte-cdk = "^6"
[tool.poetry.scripts]
source-stripe = "source_stripe.run:run"

View File

@@ -1,4 +1,4 @@
from .parent_incremental_stripe_sub_stream_error_handler import ParentIncrementalStripeSubStreamErrorHandler
from .stripe_error_handler import StripeErrorHandler
__all__ = ['StripeErrorHandler', 'ParentIncrementalStripeSubStreamErrorHandler']
__all__ = ["StripeErrorHandler", "ParentIncrementalStripeSubStreamErrorHandler"]

View File

@@ -1,3 +1,3 @@
from .parent_incremental_stripe_sub_stream_error_mapping import PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING
__all__ = ['PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING']
__all__ = ["PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING"]

View File

@@ -12,7 +12,7 @@ from typing import Any, Callable, Iterable, List, Mapping, MutableMapping, Optio
import pendulum
import requests
from airbyte_cdk import BackoffStrategy
from airbyte_cdk import BackoffStrategy, StreamSlice
from airbyte_cdk.models import SyncMode
from airbyte_cdk.sources.declarative.requesters.error_handlers.backoff_strategies import ExponentialBackoffStrategy
from airbyte_cdk.sources.streams.checkpoint import Cursor
@@ -294,7 +294,7 @@ class CreatedCursorIncrementalStripeStream(StripeStream):
if start_ts >= pendulum.now().int_timestamp:
return []
for start, end in self.chunk_dates(start_ts):
yield {"created[gte]": start, "created[lte]": end}
yield StreamSlice(partition={}, cursor_slice={"created[gte]": start, "created[lte]": end})
def get_start_timestamp(self, stream_state) -> int:
start_point = self.start_date
@@ -418,7 +418,7 @@ class UpdatedCursorIncrementalStripeStream(StripeStream):
) -> Iterable[Optional[Mapping[str, Any]]]:
# When reading from a stream, a `read_records` is called once per slice.
# We yield a single slice here because we don't want to make duplicate calls for event based incremental syncs.
yield {}
yield StreamSlice(partition={}, cursor_slice={})
def read_event_increments(
self, cursor_field: Optional[List[str]] = None, stream_state: Optional[Mapping[str, Any]] = None
@@ -562,7 +562,11 @@ class SetupAttempts(CreatedCursorIncrementalStripeStream, HttpSubStream):
)
if incremental_slices:
parent_records = HttpSubStream.stream_slices(self, sync_mode=sync_mode, cursor_field=cursor_field, stream_state=stream_state)
yield from (slice | rec for rec in parent_records for slice in incremental_slices)
yield from (
StreamSlice(partition=parent_record, cursor_slice=_slice)
for parent_record in parent_records
for _slice in incremental_slices
)
else:
yield from []
@@ -778,7 +782,7 @@ class ParentIncrementalStripeSubStream(StripeSubStream):
sync_mode=sync_mode, cursor_field=cursor_field, stream_slice=stream_slice, stream_state=stream_state
)
for record in parent_records:
yield {"parent": record}
yield StreamSlice(partition={"parent": record}, cursor_slice={})
def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]:
return {self.cursor_field: max(current_stream_state.get(self.cursor_field, 0), latest_record[self.cursor_field])}
@@ -798,6 +802,9 @@ class UpdatedCursorIncrementalStripeSubStream(UpdatedCursorIncrementalStripeStre
self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None
) -> Iterable[Optional[Mapping[str, Any]]]:
if not stream_state:
yield from HttpSubStream.stream_slices(self, sync_mode, cursor_field, stream_state)
yield from map(
lambda stream_slice: StreamSlice(partition=stream_slice, cursor_slice={}),
HttpSubStream.stream_slices(self, sync_mode, cursor_field, stream_state),
)
else:
yield from UpdatedCursorIncrementalStripeStream.stream_slices(self, sync_mode, cursor_field, stream_state)

View File

@@ -60,6 +60,14 @@ class StripeRequestBuilder:
def payouts_endpoint(cls, account_id: str, client_secret: str) -> "StripeRequestBuilder":
return cls("payouts", account_id, client_secret)
@classmethod
def setup_attempts_endpoint(cls, account_id: str, client_secret: str) -> "StripeRequestBuilder":
return cls("setup_attempts", account_id, client_secret)
@classmethod
def setup_intents_endpoint(cls, account_id: str, client_secret: str) -> "StripeRequestBuilder":
return cls("setup_intents", account_id, client_secret)
@classmethod
def persons_endpoint(
cls,
@@ -91,6 +99,7 @@ class StripeRequestBuilder:
self._limit: Optional[int] = None
self._object: Optional[str] = None
self._payout: Optional[str] = None
self._setup_intent: Optional[str] = None
self._starting_after_id: Optional[str] = None
self._types: List[str] = []
self._expands: List[str] = []
@@ -131,6 +140,10 @@ class StripeRequestBuilder:
self._payout = payout
return self
def with_setup_intent(self, setup_intent: str) -> "StripeRequestBuilder":
self._setup_intent = setup_intent
return self
def build(self) -> HttpRequest:
query_params = {}
if self._created_gte:
@@ -152,6 +165,8 @@ class StripeRequestBuilder:
query_params["payout"] = self._payout
if self._expands:
query_params["expand[]"] = self._expands
if self._setup_intent:
query_params["setup_intent"] = self._setup_intent
if self._any_query_params:
if query_params:

View File

@@ -244,7 +244,7 @@ class IncrementalTest(TestCase):
output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE)
most_recent_state = output.most_recent_state
assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME)
assert most_recent_state.stream_state == AirbyteStateBlob(created=int(_NOW.timestamp()))
assert most_recent_state.stream_state == AirbyteStateBlob(created=int(cursor_value))
@HttpMocker()
def test_given_state_when_read_then_use_state_for_query_params(self, http_mocker: HttpMocker) -> None:

View File

@@ -0,0 +1,214 @@
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
from datetime import datetime, timedelta, timezone
from typing import Any, Dict, Optional
from unittest import TestCase
import freezegun
from source_stripe import SourceStripe
from airbyte_cdk.models import AirbyteStateBlob, ConfiguredAirbyteCatalog, StreamDescriptor, SyncMode
from airbyte_cdk.sources.source import TState
from airbyte_cdk.test.catalog_builder import CatalogBuilder
from airbyte_cdk.test.entrypoint_wrapper import EntrypointOutput, read
from airbyte_cdk.test.mock_http import HttpMocker
from airbyte_cdk.test.mock_http.response_builder import (
FieldPath,
HttpResponseBuilder,
NestedPath,
RecordBuilder,
create_record_builder,
create_response_builder,
find_template,
)
from airbyte_cdk.test.state_builder import StateBuilder
from integration.config import ConfigBuilder
from integration.pagination import StripePaginationStrategy
from integration.request_builder import StripeRequestBuilder
_EVENT_TYPES = [
"setup_intent.canceled",
"setup_intent.created",
"setup_intent.requires_action",
"setup_intent.setup_failed",
"setup_intent.succeeded",
]
_DATA_FIELD = NestedPath(["data", "object"])
_STREAM_NAME = "setup_attempts"
_NOW = datetime.now(timezone.utc)
_A_START_DATE = _NOW - timedelta(days=60)
_ACCOUNT_ID = "account_id"
_CLIENT_SECRET = "client_secret"
_SETUP_INTENT_ID_1 = "setup_intent_id_1"
_SETUP_INTENT_ID_2 = "setup_intent_id_2"
_NO_STATE = StateBuilder().build()
_AVOIDING_INCLUSIVE_BOUNDARIES = timedelta(seconds=1)
def _setup_attempts_request(setup_intent: str) -> StripeRequestBuilder:
return StripeRequestBuilder.setup_attempts_endpoint(_ACCOUNT_ID, _CLIENT_SECRET).with_setup_intent(setup_intent)
def _setup_intents_request() -> StripeRequestBuilder:
return StripeRequestBuilder.setup_intents_endpoint(_ACCOUNT_ID, _CLIENT_SECRET)
def _events_request() -> StripeRequestBuilder:
return StripeRequestBuilder.events_endpoint(_ACCOUNT_ID, _CLIENT_SECRET)
def _config() -> ConfigBuilder:
return ConfigBuilder().with_start_date(_NOW - timedelta(days=75)).with_account_id(_ACCOUNT_ID).with_client_secret(_CLIENT_SECRET)
def _catalog(sync_mode: SyncMode) -> ConfiguredAirbyteCatalog:
return CatalogBuilder().with_stream(_STREAM_NAME, sync_mode).build()
def _source(catalog: ConfiguredAirbyteCatalog, config: Dict[str, Any], state: Optional[TState]) -> SourceStripe:
return SourceStripe(catalog, config, state)
def _an_event() -> RecordBuilder:
return create_record_builder(
find_template("events", __file__),
FieldPath("data"),
record_id_path=FieldPath("id"),
record_cursor_path=FieldPath("created"),
)
def _events_response() -> HttpResponseBuilder:
return create_response_builder(find_template("events", __file__), FieldPath("data"), pagination_strategy=StripePaginationStrategy())
def _a_setup_attempt() -> RecordBuilder:
return create_record_builder(
find_template(_STREAM_NAME, __file__),
FieldPath("data"),
record_id_path=FieldPath("id"),
record_cursor_path=FieldPath("created"),
)
def _setup_attempts_response() -> HttpResponseBuilder:
return create_response_builder(find_template(_STREAM_NAME, __file__), FieldPath("data"), pagination_strategy=StripePaginationStrategy())
def _a_setup_intent() -> RecordBuilder:
return create_record_builder(
find_template("setup_intents", __file__),
FieldPath("data"),
record_id_path=FieldPath("id"),
record_cursor_path=FieldPath("created"),
)
def _setup_intents_response() -> HttpResponseBuilder:
return create_response_builder(
find_template("setup_intents", __file__), FieldPath("data"), pagination_strategy=StripePaginationStrategy()
)
def _read(
config_builder: ConfigBuilder, sync_mode: SyncMode, state: Optional[Dict[str, Any]] = None, expecting_exception: bool = False
) -> EntrypointOutput:
catalog = _catalog(sync_mode)
config = config_builder.build()
return read(_source(catalog, config, state), config, catalog, state, expecting_exception)
@freezegun.freeze_time(_NOW.isoformat())
class FullRefreshTest(TestCase):
@HttpMocker()
def test_given_one_page_when_read_then_return_records(self, http_mocker: HttpMocker) -> None:
http_mocker.get(
_setup_intents_request().with_created_gte(_A_START_DATE).with_created_lte(_NOW).with_limit(100).build(),
_setup_intents_response()
.with_record(_a_setup_intent().with_id(_SETUP_INTENT_ID_1))
.with_record(_a_setup_intent().with_id(_SETUP_INTENT_ID_2))
.build(),
)
http_mocker.get(
_setup_attempts_request(_SETUP_INTENT_ID_1).with_created_gte(_A_START_DATE).with_created_lte(_NOW).with_limit(100).build(),
_setup_attempts_response().with_record(_a_setup_attempt()).build(),
)
http_mocker.get(
_setup_attempts_request(_SETUP_INTENT_ID_2).with_created_gte(_A_START_DATE).with_created_lte(_NOW).with_limit(100).build(),
_setup_attempts_response().with_record(_a_setup_attempt()).with_record(_a_setup_attempt()).build(),
)
output = self._read(_config().with_start_date(_A_START_DATE))
assert len(output.records) == 3
def _read(self, config: ConfigBuilder, expecting_exception: bool = False) -> EntrypointOutput:
return _read(config, SyncMode.full_refresh, expecting_exception=expecting_exception)
@freezegun.freeze_time(_NOW.isoformat())
class IncrementalTest(TestCase):
@HttpMocker()
def test_given_no_state_when_read_then_use_cards_endpoint(self, http_mocker: HttpMocker) -> None:
http_mocker.get(
_setup_intents_request().with_created_gte(_A_START_DATE).with_created_lte(_NOW).with_limit(100).build(),
_setup_intents_response()
.with_record(_a_setup_intent().with_id(_SETUP_INTENT_ID_1))
.with_record(_a_setup_intent().with_id(_SETUP_INTENT_ID_2))
.build(),
)
http_mocker.get(
_setup_attempts_request(_SETUP_INTENT_ID_1).with_created_gte(_A_START_DATE).with_created_lte(_NOW).with_limit(100).build(),
_setup_attempts_response().with_record(_a_setup_attempt()).build(),
)
http_mocker.get(
_setup_attempts_request(_SETUP_INTENT_ID_2).with_created_gte(_A_START_DATE).with_created_lte(_NOW).with_limit(100).build(),
_setup_attempts_response().with_record(_a_setup_attempt()).with_record(_a_setup_attempt()).build(),
)
output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE)
assert len(output.records) == 3
@HttpMocker()
def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None:
start_date = _NOW - timedelta(days=40)
state_datetime = _NOW - timedelta(days=5)
cursor_value = int(state_datetime.timestamp()) + 10
creation_datetime_of_setup_attempt = int(state_datetime.timestamp()) + 5
http_mocker.get(
_events_request()
.with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES)
.with_created_lte(_NOW)
.with_limit(100)
.with_types(_EVENT_TYPES)
.build(),
_events_response().with_record(self._a_setup_intent_event(cursor_value, _SETUP_INTENT_ID_1)).build(),
)
http_mocker.get(
_setup_attempts_request(_SETUP_INTENT_ID_1)
.with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES)
.with_created_lte(_NOW)
.with_limit(100)
.build(),
_setup_attempts_response().with_record(_a_setup_attempt().with_cursor(creation_datetime_of_setup_attempt)).build(),
)
output = self._read(
_config().with_start_date(start_date),
StateBuilder().with_stream_state(_STREAM_NAME, {"created": int(state_datetime.timestamp())}).build(),
)
assert len(output.records) == 1
most_recent_state = output.most_recent_state
assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME)
assert most_recent_state.stream_state == AirbyteStateBlob(created=creation_datetime_of_setup_attempt)
def _a_setup_intent_event(self, cursor_value: int, setup_intent_id: str) -> RecordBuilder:
return _an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_setup_intent().with_id(setup_intent_id).build())
def _read(self, config: ConfigBuilder, state: Optional[Dict[str, Any]], expecting_exception: bool = False) -> EntrypointOutput:
return _read(config, SyncMode.incremental, state, expecting_exception)

View File

@@ -0,0 +1,28 @@
{
"object": "list",
"url": "/v1/setup_attempts",
"has_more": false,
"data": [
{
"id": "setatt_1ErTsH2eZvKYlo2CI7ukcoF7",
"object": "setup_attempt",
"application": null,
"created": 1562004309,
"customer": null,
"flow_directions": null,
"livemode": false,
"on_behalf_of": null,
"payment_method": "pm_1ErTsG2eZvKYlo2CH0DNen59",
"payment_method_details": {
"card": {
"three_d_secure": null
},
"type": "card"
},
"setup_error": null,
"setup_intent": "seti_1ErTsG2eZvKYlo2CKaT8MITz",
"status": "succeeded",
"usage": "off_session"
}
]
}

View File

@@ -0,0 +1,37 @@
{
"object": "list",
"url": "/v1/setup_intents",
"has_more": false,
"data": [
{
"id": "seti_1Mm8s8LkdIwHu7ix0OXBfTRG",
"object": "setup_intent",
"application": null,
"cancellation_reason": null,
"client_secret": "seti_1Mm8s8LkdIwHu7ix0OXBfTRG_secret_NXDICkPqPeiBTAFqWmkbff09lRmSVXe",
"created": 1678942624,
"customer": null,
"description": null,
"flow_directions": null,
"last_setup_error": null,
"latest_attempt": null,
"livemode": false,
"mandate": null,
"metadata": {},
"next_action": null,
"on_behalf_of": null,
"payment_method": null,
"payment_method_options": {
"card": {
"mandate_options": null,
"network": null,
"request_three_d_secure": "automatic"
}
},
"payment_method_types": ["card"],
"single_use_mandate": null,
"status": "requires_payment_method",
"usage": "off_session"
}
]
}

View File

@@ -246,46 +246,47 @@ Each record is marked with `is_deleted` flag when the appropriate event happens
| Version | Date | Pull Request | Subject |
|:--------|:-----------|:----------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 5.8.3 | 2025-01-11 | [46832](https://github.com/airbytehq/airbyte/pull/46832) | Starting with this version, the Docker image is now rootless. Please note that this and future versions will not be compatible with Airbyte versions earlier than 0.64 |
| 5.8.2 | 2024-12-10 | [46499](https://github.com/airbytehq/airbyte/pull/46499) | Source-Stripe: Refactor Customer Balance Transactions |
| 5.8.1 | 2024-12-08 | [46499](https://github.com/airbytehq/airbyte/pull/46499) | Source-Stripe: Add new payout_balance_transactions incremental stream |
| 5.8.0 | 2024-10-12 | [46864](https://github.com/airbytehq/airbyte/pull/46864) | Add incremental stream support to `accounts` stream |
| 5.7.0 | 2024-10-01 | [45860](https://github.com/airbytehq/airbyte/pull/45860) | Add incremental stream support to `invoice_line_items` and `subscription_items` streams |
| 5.6.2 | 2024-10-05 | [43881](https://github.com/airbytehq/airbyte/pull/43881) | Update dependencies |
| 5.6.1 | 2024-10-03 | [46327](https://github.com/airbytehq/airbyte/pull/46327) | Bump the cdk to 5.10.2 to stop using PrintBuffer optimization due to record count mismatches |
| 5.6.0 | 2024-09-10 | [44891](https://github.com/airbytehq/airbyte/pull/44891) | Update `Payment Methods` stream |
| 5.5.4 | 2024-09-09 | [45348](https://github.com/airbytehq/airbyte/pull/45348) | Remove `stripe` python package |
| 5.5.3 | 2024-09-03 | [45101](https://github.com/airbytehq/airbyte/pull/45101) | Fix regression following pagination issue fix |
| 5.5.2 | 2024-08-28 | [44862](https://github.com/airbytehq/airbyte/pull/44862) | Fix RFR pagination issue |
| 5.5.1 | 2024-08-10 | [43105](https://github.com/airbytehq/airbyte/pull/43105) | Update dependencies |
| 5.5.0 | 2024-08-08 | [43302](https://github.com/airbytehq/airbyte/pull/43302) | Fix problem with state not updating and upgrade cdk 4 |
| 5.4.12 | 2024-07-31 | [41985](https://github.com/airbytehq/airbyte/pull/41985) | Expand Invoice discounts and tax rates |
| 5.4.11 | 2024-07-27 | [42623](https://github.com/airbytehq/airbyte/pull/42623) | Update dependencies |
| 5.4.10 | 2024-07-20 | [42305](https://github.com/airbytehq/airbyte/pull/42305) | Update dependencies |
| 5.4.9 | 2024-07-13 | [41760](https://github.com/airbytehq/airbyte/pull/41760) | Update dependencies |
| 5.4.8 | 2024-07-10 | [41477](https://github.com/airbytehq/airbyte/pull/41477) | Update dependencies |
| 5.4.7 | 2024-07-09 | [40869](https://github.com/airbytehq/airbyte/pull/40869) | Update dependencies |
| 5.4.6 | 2024-07-08 | [41044](https://github.com/airbytehq/airbyte/pull/41044) | Use latest `CDK` version possible |
| 5.4.5 | 2024-06-25 | [40404](https://github.com/airbytehq/airbyte/pull/40404) | Update dependencies |
| 5.4.4 | 2024-06-22 | [40040](https://github.com/airbytehq/airbyte/pull/40040) | Update dependencies |
| 5.4.3 | 2024-06-06 | [39284](https://github.com/airbytehq/airbyte/pull/39284) | [autopull] Upgrade base image to v1.2.2 |
| 5.4.2 | 2024-06-11 | [39412](https://github.com/airbytehq/airbyte/pull/39412) | Removed `invoice.upcomming` event type from (incremental sync) for `Invoices` stream |
| 5.4.1 | 2024-06-11 | [39393](https://github.com/airbytehq/airbyte/pull/39393) | Added missing `event types` (incremental sync) for `Invoices` stream |
| 5.4.0 | 2024-06-05 | [39138](https://github.com/airbytehq/airbyte/pull/39138) | Fixed the `Refunds` stream missing data for the `incremental` sync |
| 5.3.9 | 2024-05-22 | [38550](https://github.com/airbytehq/airbyte/pull/38550) | Update authenticator package |
| 5.3.8 | 2024-05-15 | [38248](https://github.com/airbytehq/airbyte/pull/38248) | Replace AirbyteLogger with logging.Logger |
| 5.3.7 | 2024-04-24 | [36663](https://github.com/airbytehq/airbyte/pull/36663) | Schema descriptions |
| 5.3.6 | 2024-04-18 | [37448](https://github.com/airbytehq/airbyte/pull/37448) | Ensure AirbyteTracedException in concurrent CDK are emitted with the right type |
| 5.3.5 | 2024-04-18 | [37418](https://github.com/airbytehq/airbyte/pull/37418) | Ensure python return code != 0 in case of error |
| 5.3.4 | 2024-04-11 | [37406](https://github.com/airbytehq/airbyte/pull/37406) | Update CDK version to have partitioned state fix |
| 5.3.3 | 2024-04-11 | [37001](https://github.com/airbytehq/airbyte/pull/37001) | Update airbyte-cdk to flush print buffer for every message |
| 5.3.2 | 2024-04-11 | [36964](https://github.com/airbytehq/airbyte/pull/36964) | Update CDK version to fix breaking change before another devs work on it |
| 5.3.1 | 2024-04-10 | [36960](https://github.com/airbytehq/airbyte/pull/36960) | Remove unused imports |
| 5.3.0 | 2024-03-12 | [35978](https://github.com/airbytehq/airbyte/pull/35978) | Upgrade CDK to start emitting record counts with state and full refresh state |
| 5.2.4 | 2024-02-12 | [35137](https://github.com/airbytehq/airbyte/pull/35137) | Fix license in `pyproject.toml` |
| 5.2.3 | 2024-02-09 | [35068](https://github.com/airbytehq/airbyte/pull/35068) | Manage dependencies with Poetry. |
| 5.2.2 | 2024-01-31 | [34619](https://github.com/airbytehq/airbyte/pull/34619) | Events stream concurrent on incremental syncs |
| 5.2.1 | 2024-01-18 | [34495](https://github.com/airbytehq/airbyte/pull/34495) | Fix deadlock issue |
| 5.8.4 | 2025-02-03 | [49940](https://github.com/airbytehq/airbyte/pull/49940) | Update CDK version |
| 5.8.3 | 2025-01-11 | [46832](https://github.com/airbytehq/airbyte/pull/46832) | Starting with this version, the Docker image is now rootless. Please note that this and future versions will not be compatible with Airbyte versions earlier than 0.64 |
| 5.8.2 | 2024-12-10 | [46499](https://github.com/airbytehq/airbyte/pull/46499) | Source-Stripe: Refactor Customer Balance Transactions |
| 5.8.1 | 2024-12-08 | [46499](https://github.com/airbytehq/airbyte/pull/46499) | Source-Stripe: Add new payout_balance_transactions incremental stream |
| 5.8.0 | 2024-10-12 | [46864](https://github.com/airbytehq/airbyte/pull/46864) | Add incremental stream support to `accounts` stream |
| 5.7.0 | 2024-10-01 | [45860](https://github.com/airbytehq/airbyte/pull/45860) | Add incremental stream support to `invoice_line_items` and `subscription_items` streams |
| 5.6.2 | 2024-10-05 | [43881](https://github.com/airbytehq/airbyte/pull/43881) | Update dependencies |
| 5.6.1 | 2024-10-03 | [46327](https://github.com/airbytehq/airbyte/pull/46327) | Bump the cdk to 5.10.2 to stop using PrintBuffer optimization due to record count mismatches |
| 5.6.0 | 2024-09-10 | [44891](https://github.com/airbytehq/airbyte/pull/44891) | Update `Payment Methods` stream |
| 5.5.4 | 2024-09-09 | [45348](https://github.com/airbytehq/airbyte/pull/45348) | Remove `stripe` python package |
| 5.5.3 | 2024-09-03 | [45101](https://github.com/airbytehq/airbyte/pull/45101) | Fix regression following pagination issue fix |
| 5.5.2 | 2024-08-28 | [44862](https://github.com/airbytehq/airbyte/pull/44862) | Fix RFR pagination issue |
| 5.5.1 | 2024-08-10 | [43105](https://github.com/airbytehq/airbyte/pull/43105) | Update dependencies |
| 5.5.0 | 2024-08-08 | [43302](https://github.com/airbytehq/airbyte/pull/43302) | Fix problem with state not updating and upgrade cdk 4 |
| 5.4.12 | 2024-07-31 | [41985](https://github.com/airbytehq/airbyte/pull/41985) | Expand Invoice discounts and tax rates |
| 5.4.11 | 2024-07-27 | [42623](https://github.com/airbytehq/airbyte/pull/42623) | Update dependencies |
| 5.4.10 | 2024-07-20 | [42305](https://github.com/airbytehq/airbyte/pull/42305) | Update dependencies |
| 5.4.9 | 2024-07-13 | [41760](https://github.com/airbytehq/airbyte/pull/41760) | Update dependencies |
| 5.4.8 | 2024-07-10 | [41477](https://github.com/airbytehq/airbyte/pull/41477) | Update dependencies |
| 5.4.7 | 2024-07-09 | [40869](https://github.com/airbytehq/airbyte/pull/40869) | Update dependencies |
| 5.4.6 | 2024-07-08 | [41044](https://github.com/airbytehq/airbyte/pull/41044) | Use latest `CDK` version possible |
| 5.4.5 | 2024-06-25 | [40404](https://github.com/airbytehq/airbyte/pull/40404) | Update dependencies |
| 5.4.4 | 2024-06-22 | [40040](https://github.com/airbytehq/airbyte/pull/40040) | Update dependencies |
| 5.4.3 | 2024-06-06 | [39284](https://github.com/airbytehq/airbyte/pull/39284) | [autopull] Upgrade base image to v1.2.2 |
| 5.4.2 | 2024-06-11 | [39412](https://github.com/airbytehq/airbyte/pull/39412) | Removed `invoice.upcomming` event type from (incremental sync) for `Invoices` stream |
| 5.4.1 | 2024-06-11 | [39393](https://github.com/airbytehq/airbyte/pull/39393) | Added missing `event types` (incremental sync) for `Invoices` stream |
| 5.4.0 | 2024-06-05 | [39138](https://github.com/airbytehq/airbyte/pull/39138) | Fixed the `Refunds` stream missing data for the `incremental` sync |
| 5.3.9 | 2024-05-22 | [38550](https://github.com/airbytehq/airbyte/pull/38550) | Update authenticator package |
| 5.3.8 | 2024-05-15 | [38248](https://github.com/airbytehq/airbyte/pull/38248) | Replace AirbyteLogger with logging.Logger |
| 5.3.7 | 2024-04-24 | [36663](https://github.com/airbytehq/airbyte/pull/36663) | Schema descriptions |
| 5.3.6 | 2024-04-18 | [37448](https://github.com/airbytehq/airbyte/pull/37448) | Ensure AirbyteTracedException in concurrent CDK are emitted with the right type |
| 5.3.5 | 2024-04-18 | [37418](https://github.com/airbytehq/airbyte/pull/37418) | Ensure python return code != 0 in case of error |
| 5.3.4 | 2024-04-11 | [37406](https://github.com/airbytehq/airbyte/pull/37406) | Update CDK version to have partitioned state fix |
| 5.3.3 | 2024-04-11 | [37001](https://github.com/airbytehq/airbyte/pull/37001) | Update airbyte-cdk to flush print buffer for every message |
| 5.3.2 | 2024-04-11 | [36964](https://github.com/airbytehq/airbyte/pull/36964) | Update CDK version to fix breaking change before another devs work on it |
| 5.3.1 | 2024-04-10 | [36960](https://github.com/airbytehq/airbyte/pull/36960) | Remove unused imports |
| 5.3.0 | 2024-03-12 | [35978](https://github.com/airbytehq/airbyte/pull/35978) | Upgrade CDK to start emitting record counts with state and full refresh state |
| 5.2.4 | 2024-02-12 | [35137](https://github.com/airbytehq/airbyte/pull/35137) | Fix license in `pyproject.toml` |
| 5.2.3 | 2024-02-09 | [35068](https://github.com/airbytehq/airbyte/pull/35068) | Manage dependencies with Poetry. |
| 5.2.2 | 2024-01-31 | [34619](https://github.com/airbytehq/airbyte/pull/34619) | Events stream concurrent on incremental syncs |
| 5.2.1 | 2024-01-18 | [34495](https://github.com/airbytehq/airbyte/pull/34495) | Fix deadlock issue |
| 5.2.0 | 2024-01-18 | [34347](https://github.com/airbytehq/airbyte/pull//34347) | Add new fields invoices and subscription streams. Upgrade the CDK for better memory usage. |
| 5.1.3 | 2023-12-18 | [33306](https://github.com/airbytehq/airbyte/pull/33306/) | Adding integration tests |
| 5.1.2 | 2024-01-04 | [33414](https://github.com/airbytehq/airbyte/pull/33414) | Prepare for airbyte-lib |