Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ data:
connectorSubtype: api
connectorType: source
definitionId: eb4c9e00-db83-4d63-a386-39cfa91012a8
dockerImageTag: 1.5.15
dockerImageTag: 1.5.16-rc.1
dockerRepository: airbyte/source-google-search-console
documentationUrl: https://docs.airbyte.com/integrations/sources/google-search-console
erdUrl: https://dbdocs.io/airbyteio/source-google-search-console?view=relationships
Expand All @@ -28,6 +28,9 @@ data:
enabled: true
oss:
enabled: true
releases:
rolloutConfiguration:
enableProgressiveRollout: true
releaseStage: generally_available
suggestedStreams:
streams:
Expand Down
1,527 changes: 1,213 additions & 314 deletions airbyte-integrations/connectors/source-google-search-console/poetry.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
version = "1.5.15"
version = "1.5.16-rc.1"
name = "source-google-search-console"
description = "Source implementation for Google Search Console."
authors = [ "Airbyte <contact@airbyte.io>",]
Expand All @@ -16,18 +16,19 @@ repository = "https://github.com/airbytehq/airbyte"
include = "source_google_search_console"

[tool.poetry.dependencies]
python = "^3.9,<3.12"
python = ">=3.10,<3.12"
google-api-python-client = "==2.105.0"
airbyte-cdk = "^1"
airbyte-cdk = "^6"
google-auth = "==2.23.3"
pendulum = "^3.1.0"

[tool.poetry.scripts]
source-google-search-console = "source_google_search_console.run:run"

[tool.poetry.group.dev.dependencies]
requests-mock = "^1.11.0"
pytest-lazy-fixture = "^0.6.3"
pytest = "^8.0.0"
pytest = "^7.4.0"
Copy link
Contributor Author

@ChristoGrab Christo Grabowski (ChristoGrab) Apr 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted because pytest 8.0 does not play nice with the pytest-lazy-fixture dependency which is used in unit tests. Guessing there's a decent chance that unit tests will have to be adjusted anyway as we're migrating streams, so maybe we can rip out this dependency soon, but feels out of scope for this PR.

pytest-mock = "^3.6.1"


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import logging
from typing import Any, List, Mapping

import orjson

from airbyte_cdk.config_observation import create_connector_config_control_message
from airbyte_cdk.entrypoint import AirbyteEntrypoint
from airbyte_cdk.models import AirbyteMessageSerializer
from airbyte_cdk.sources import Source
from airbyte_cdk.sources.message import InMemoryMessageRepository, MessageRepository

Expand Down Expand Up @@ -77,7 +80,7 @@ def emit_control_message(cls, migrated_config: Mapping[str, Any]) -> None:
cls.message_repository.emit_message(create_connector_config_control_message(migrated_config))
# emit the Airbyte Control Message from message queue to stdout
for message in cls.message_repository._message_queue:
print(message.json(exclude_unset=True))
print(orjson.dumps(AirbyteMessageSerializer.dump(message)).decode())

@classmethod
def migrate(cls, args: List[str], source: Source) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def should_retry(self, response: requests.Response) -> bool:
self.logger.error(f"Stream `{self.name}`. {error.get('message')}. Trying with `aggregationType = auto` instead.")
self.aggregation_type = QueryAggregationType.auto
setattr(self, "raise_on_http_errors", False)
return super().should_retry(response)
return response.status_code == 429 or 500 <= response.status_code < 600


class Sites(GoogleSearchConsole):
Expand All @@ -90,6 +90,7 @@ class Sites(GoogleSearchConsole):
"""

primary_key = None
is_resumable = False

def path(
self,
Expand All @@ -107,6 +108,7 @@ class Sitemaps(GoogleSearchConsole):

primary_key = None
data_field = "sitemap"
is_resumable = False

def path(
self,
Expand Down Expand Up @@ -384,7 +386,7 @@ class SearchByKeyword(SearchAnalytics):
def stream_slices(
self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None
) -> Iterable[Optional[Mapping[str, Any]]]:
search_appearance_stream = SearchAppearance(self._session.auth, self._site_urls, self._start_date, self._end_date)
search_appearance_stream = SearchAppearance(self._http_client._session.auth, self._site_urls, self._start_date, self._end_date)

for stream_slice in super().stream_slices(sync_mode, cursor_field, stream_state):
keywords_records = search_appearance_stream.read_records(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@


import json
import os
import shutil
from pathlib import Path
from typing import Any, Mapping

from source_google_search_console.config_migrations import MigrateCustomReports
Expand All @@ -16,6 +19,7 @@
# BASE ARGS
CMD = "check"
TEST_CONFIG_PATH = "unit_tests/test_migrations/test_config.json"
BACKUP_CONFIG_PATH = str(Path(__file__).parent / "test_config.json.bak")
NEW_TEST_CONFIG_PATH = "unit_tests/test_migrations/test_new_config.json"
SOURCE_INPUT_ARGS = [CMD, "--config", TEST_CONFIG_PATH]
SOURCE: Source = SourceGoogleSearchConsole()
Expand All @@ -27,45 +31,53 @@ def load_config(config_path: str = TEST_CONFIG_PATH) -> Mapping[str, Any]:
return json.load(config)


def revert_migration(config_path: str = TEST_CONFIG_PATH) -> None:
with open(config_path, "r") as test_config:
config = json.load(test_config)
config.pop("custom_reports_array")
with open(config_path, "w") as updated_config:
config = json.dumps(config)
updated_config.write(config)
def backup_config():
Copy link
Contributor Author

@ChristoGrab Christo Grabowski (ChristoGrab) Apr 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The revert_migration test function was reformatting the local test_config.json file on each run, leading to formatting issues with our current pre-commit hooks. Not a big deal, but could be annoying for local dev work. Switching to a backup/restore of the original file fixed the issue for me.

"""Create a backup of the original test config file"""
shutil.copyfile(TEST_CONFIG_PATH, BACKUP_CONFIG_PATH)


def restore_config():
"""Restore the original test config from backup"""
if os.path.exists(BACKUP_CONFIG_PATH):
shutil.copyfile(BACKUP_CONFIG_PATH, TEST_CONFIG_PATH)
os.remove(BACKUP_CONFIG_PATH)


def test_migrate_config():
migration_instance = MigrateCustomReports()
original_config = load_config()
# migrate the test_config
migration_instance.migrate(SOURCE_INPUT_ARGS, SOURCE)
# load the updated config
test_migrated_config = load_config()
# check migrated property
assert "custom_reports_array" in test_migrated_config
assert isinstance(test_migrated_config["custom_reports_array"], list)
# check the old property is in place
assert "custom_reports" in test_migrated_config
assert isinstance(test_migrated_config["custom_reports"], str)
# check the migration should be skipped, once already done
assert not migration_instance.should_migrate(test_migrated_config)
# load the old custom reports VS migrated
assert json.loads(original_config["custom_reports"]) == test_migrated_config["custom_reports_array"]
# test CONTROL MESSAGE was emitted
control_msg = migration_instance.message_repository._message_queue[0]
assert control_msg.type == Type.CONTROL
assert control_msg.control.type == OrchestratorType.CONNECTOR_CONFIG
# old custom_reports are stil type(str)
assert isinstance(control_msg.control.connectorConfig.config["custom_reports"], str)
# new custom_reports are type(list)
assert isinstance(control_msg.control.connectorConfig.config["custom_reports_array"], list)
# check the migrated values
assert control_msg.control.connectorConfig.config["custom_reports_array"][0]["name"] == "custom_dimensions"
assert control_msg.control.connectorConfig.config["custom_reports_array"][0]["dimensions"] == ["date", "country", "device"]
# revert the test_config to the starting point
revert_migration()
# Create a backup of the original config
backup_config()

try:
migration_instance = MigrateCustomReports()
original_config = load_config()
# migrate the test_config
migration_instance.migrate(SOURCE_INPUT_ARGS, SOURCE)
# load the updated config
test_migrated_config = load_config()
# check migrated property
assert "custom_reports_array" in test_migrated_config
assert isinstance(test_migrated_config["custom_reports_array"], list)
# check the old property is in place
assert "custom_reports" in test_migrated_config
assert isinstance(test_migrated_config["custom_reports"], str)
# check the migration should be skipped, once already done
assert not migration_instance.should_migrate(test_migrated_config)
# load the old custom reports VS migrated
assert json.loads(original_config["custom_reports"]) == test_migrated_config["custom_reports_array"]
# test CONTROL MESSAGE was emitted
control_msg = migration_instance.message_repository._message_queue[0]
assert control_msg.type == Type.CONTROL
assert control_msg.control.type == OrchestratorType.CONNECTOR_CONFIG
# old custom_reports are stil type(str)
assert isinstance(control_msg.control.connectorConfig.config["custom_reports"], str)
# new custom_reports are type(list)
assert isinstance(control_msg.control.connectorConfig.config["custom_reports_array"], list)
# check the migrated values
assert control_msg.control.connectorConfig.config["custom_reports_array"][0]["name"] == "custom_dimensions"
assert control_msg.control.connectorConfig.config["custom_reports_array"][0]["dimensions"] == ["date", "country", "device"]
finally:
# Always restore the original config file
restore_config()


def test_config_is_reverted():
Expand Down
1 change: 1 addition & 0 deletions docs/integrations/sources/google-search-console.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ Google Search Console only retains data for websites from the last 16 months. An

| Version | Date | Pull Request | Subject |
|:--------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|
| 1.5.16-rc.1 | 2025-05-02 | [59140](https://github.com/airbytehq/airbyte/pull/59140) | Migrate to CDK V6 |
| 1.5.15 | 2025-02-22 | [54426](https://github.com/airbytehq/airbyte/pull/54426) | Update dependencies |
| 1.5.14 | 2025-02-15 | [53781](https://github.com/airbytehq/airbyte/pull/53781) | Update dependencies |
| 1.5.13 | 2025-02-01 | [52854](https://github.com/airbytehq/airbyte/pull/52854) | Update dependencies |
Expand Down
Loading