airbyte-internal-ops 0.4.2__py3-none-any.whl → 0.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/METADATA +2 -1
- {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/RECORD +21 -129
- airbyte_ops_mcp/cli/cloud.py +31 -2
- airbyte_ops_mcp/cloud_admin/api_client.py +506 -33
- airbyte_ops_mcp/cloud_admin/models.py +56 -0
- airbyte_ops_mcp/constants.py +58 -0
- airbyte_ops_mcp/{_legacy/airbyte_ci/metadata_service/docker_hub.py → docker_hub.py} +16 -10
- airbyte_ops_mcp/mcp/cloud_connector_versions.py +491 -10
- airbyte_ops_mcp/mcp/prerelease.py +5 -44
- airbyte_ops_mcp/mcp/prod_db_queries.py +128 -4
- airbyte_ops_mcp/mcp/regression_tests.py +10 -5
- airbyte_ops_mcp/{_legacy/airbyte_ci/metadata_service/validators/metadata_validator.py → metadata_validator.py} +18 -12
- airbyte_ops_mcp/prod_db_access/queries.py +51 -0
- airbyte_ops_mcp/prod_db_access/sql.py +76 -0
- airbyte_ops_mcp/regression_tests/ci_output.py +8 -4
- airbyte_ops_mcp/regression_tests/connection_fetcher.py +16 -5
- airbyte_ops_mcp/regression_tests/http_metrics.py +21 -2
- airbyte_ops_mcp/regression_tests/models.py +7 -1
- airbyte_ops_mcp/telemetry.py +162 -0
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/.gitignore +0 -1
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/README.md +0 -420
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/__init__.py +0 -2
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/__init__.py +0 -1
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/__init__.py +0 -8
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/base_backend.py +0 -16
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/duckdb_backend.py +0 -87
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/backends/file_backend.py +0 -165
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/connection_objects_retrieval.py +0 -377
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/connector_runner.py +0 -247
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/errors.py +0 -7
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/evaluation_modes.py +0 -25
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/hacks.py +0 -23
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/json_schema_helper.py +0 -384
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/mitm_addons.py +0 -37
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/models.py +0 -595
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/proxy.py +0 -207
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/secret_access.py +0 -47
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/segment_tracking.py +0 -45
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/commons/utils.py +0 -214
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/conftest.py.disabled +0 -751
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/consts.py +0 -4
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/poetry.lock +0 -4480
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/pytest.ini +0 -9
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/__init__.py +0 -1
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_check.py +0 -61
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_discover.py +0 -117
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_read.py +0 -627
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/regression_tests/test_spec.py +0 -43
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/report.py +0 -542
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/stash_keys.py +0 -38
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/templates/__init__.py +0 -0
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/templates/private_details.html.j2 +0 -305
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/templates/report.html.j2 +0 -515
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/utils.py +0 -187
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/__init__.py +0 -0
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_check.py +0 -61
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_discover.py +0 -217
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_read.py +0 -177
- airbyte_ops_mcp/_legacy/airbyte_ci/connector_live_tests/validation_tests/test_spec.py +0 -631
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/README.md +0 -91
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/bin/bundle-schemas.js +0 -48
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/bin/generate-metadata-models.sh +0 -36
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ActorDefinitionResourceRequirements.py +0 -54
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/AirbyteInternal.py +0 -22
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/AllowedHosts.py +0 -18
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorBreakingChanges.py +0 -65
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorBuildOptions.py +0 -15
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorIPCOptions.py +0 -25
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorMetadataDefinitionV0.json +0 -897
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorMetadataDefinitionV0.py +0 -478
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorMetrics.py +0 -24
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorPackageInfo.py +0 -12
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistryDestinationDefinition.py +0 -407
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistryReleases.py +0 -406
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistrySourceDefinition.py +0 -407
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorRegistryV0.py +0 -413
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorReleases.py +0 -98
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ConnectorTestSuiteOptions.py +0 -58
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/GeneratedFields.py +0 -62
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/GitInfo.py +0 -31
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/JobType.py +0 -23
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/NormalizationDestinationDefinitionConfig.py +0 -24
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/RegistryOverrides.py +0 -111
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ReleaseStage.py +0 -15
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/RemoteRegistries.py +0 -23
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/ResourceRequirements.py +0 -18
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/RolloutConfiguration.py +0 -29
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/Secret.py +0 -34
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SecretStore.py +0 -22
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SourceFileInfo.py +0 -16
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SuggestedStreams.py +0 -18
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/SupportLevel.py +0 -15
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/TestConnections.py +0 -14
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/__init__.py +0 -31
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/generated/airbyte-connector-metadata-schema.json +0 -0
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ActorDefinitionResourceRequirements.yaml +0 -30
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/AirbyteInternal.yaml +0 -32
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/AllowedHosts.yaml +0 -13
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorBreakingChanges.yaml +0 -65
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorBuildOptions.yaml +0 -10
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorIPCOptions.yaml +0 -29
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorMetadataDefinitionV0.yaml +0 -172
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorMetrics.yaml +0 -30
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorPackageInfo.yaml +0 -9
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistryDestinationDefinition.yaml +0 -90
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistryReleases.yaml +0 -35
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistrySourceDefinition.yaml +0 -92
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorRegistryV0.yaml +0 -18
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorReleases.yaml +0 -16
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ConnectorTestSuiteOptions.yaml +0 -28
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/GeneratedFields.yaml +0 -16
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/GitInfo.yaml +0 -21
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/JobType.yaml +0 -14
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/NormalizationDestinationDefinitionConfig.yaml +0 -21
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/RegistryOverrides.yaml +0 -38
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ReleaseStage.yaml +0 -11
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/RemoteRegistries.yaml +0 -25
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/ResourceRequirements.yaml +0 -16
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/RolloutConfiguration.yaml +0 -29
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/Secret.yaml +0 -19
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SecretStore.yaml +0 -16
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SourceFileInfo.yaml +0 -17
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SuggestedStreams.yaml +0 -13
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/SupportLevel.yaml +0 -10
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/models/TestConnections.yaml +0 -17
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/package-lock.json +0 -62
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/package.json +0 -12
- airbyte_ops_mcp/_legacy/airbyte_ci/metadata_models/transform.py +0 -71
- {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/WHEEL +0 -0
- {airbyte_internal_ops-0.4.2.dist-info → airbyte_internal_ops-0.5.1.dist-info}/entry_points.txt +0 -0
|
@@ -25,8 +25,11 @@ from airbyte_ops_mcp.cloud_admin.auth import (
|
|
|
25
25
|
)
|
|
26
26
|
from airbyte_ops_mcp.cloud_admin.models import (
|
|
27
27
|
ConnectorVersionInfo,
|
|
28
|
+
OrganizationVersionOverrideResult,
|
|
28
29
|
VersionOverrideOperationResult,
|
|
30
|
+
WorkspaceVersionOverrideResult,
|
|
29
31
|
)
|
|
32
|
+
from airbyte_ops_mcp.constants import WorkspaceAliasEnum
|
|
30
33
|
from airbyte_ops_mcp.github_api import (
|
|
31
34
|
GitHubAPIError,
|
|
32
35
|
GitHubCommentParseError,
|
|
@@ -95,8 +98,11 @@ def _resolve_cloud_auth() -> _ResolvedCloudAuth:
|
|
|
95
98
|
)
|
|
96
99
|
def get_cloud_connector_version(
|
|
97
100
|
workspace_id: Annotated[
|
|
98
|
-
str,
|
|
99
|
-
Field(
|
|
101
|
+
str | WorkspaceAliasEnum,
|
|
102
|
+
Field(
|
|
103
|
+
description="The Airbyte Cloud workspace ID (UUID) or alias. "
|
|
104
|
+
"Accepts '@devin-ai-sandbox' as an alias for the Devin AI sandbox workspace."
|
|
105
|
+
),
|
|
100
106
|
],
|
|
101
107
|
actor_id: Annotated[
|
|
102
108
|
str, "The ID of the deployed connector (source or destination)"
|
|
@@ -116,6 +122,9 @@ def get_cloud_connector_version(
|
|
|
116
122
|
2. HTTP headers: X-Airbyte-Cloud-Client-Id, X-Airbyte-Cloud-Client-Secret
|
|
117
123
|
3. Environment variables: AIRBYTE_CLOUD_CLIENT_ID, AIRBYTE_CLOUD_CLIENT_SECRET
|
|
118
124
|
"""
|
|
125
|
+
# Resolve workspace ID alias
|
|
126
|
+
resolved_workspace_id = WorkspaceAliasEnum.resolve(workspace_id)
|
|
127
|
+
|
|
119
128
|
try:
|
|
120
129
|
auth = _resolve_cloud_auth()
|
|
121
130
|
|
|
@@ -125,11 +134,11 @@ def get_cloud_connector_version(
|
|
|
125
134
|
version_data = api_client.get_connector_version(
|
|
126
135
|
connector_id=actor_id,
|
|
127
136
|
connector_type=actor_type,
|
|
128
|
-
|
|
137
|
+
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
129
138
|
client_id=auth.client_id,
|
|
130
139
|
client_secret=auth.client_secret,
|
|
131
140
|
bearer_token=auth.bearer_token,
|
|
132
|
-
workspace_id=
|
|
141
|
+
workspace_id=resolved_workspace_id,
|
|
133
142
|
)
|
|
134
143
|
|
|
135
144
|
# Determine if version is pinned from scoped config context (more reliable)
|
|
@@ -170,8 +179,11 @@ def get_cloud_connector_version(
|
|
|
170
179
|
)
|
|
171
180
|
def set_cloud_connector_version_override(
|
|
172
181
|
workspace_id: Annotated[
|
|
173
|
-
str,
|
|
174
|
-
Field(
|
|
182
|
+
str | WorkspaceAliasEnum,
|
|
183
|
+
Field(
|
|
184
|
+
description="The Airbyte Cloud workspace ID (UUID) or alias. "
|
|
185
|
+
"Accepts '@devin-ai-sandbox' as an alias for the Devin AI sandbox workspace."
|
|
186
|
+
),
|
|
175
187
|
],
|
|
176
188
|
actor_id: Annotated[
|
|
177
189
|
str, "The ID of the deployed connector (source or destination)"
|
|
@@ -262,6 +274,10 @@ def set_cloud_connector_version_override(
|
|
|
262
274
|
2. HTTP headers: X-Airbyte-Cloud-Client-Id, X-Airbyte-Cloud-Client-Secret
|
|
263
275
|
3. Environment variables: AIRBYTE_CLOUD_CLIENT_ID, AIRBYTE_CLOUD_CLIENT_SECRET
|
|
264
276
|
"""
|
|
277
|
+
# Resolve workspace ID alias (workspace_id is required, so resolved value is never None)
|
|
278
|
+
resolved_workspace_id = WorkspaceAliasEnum.resolve(workspace_id)
|
|
279
|
+
assert resolved_workspace_id is not None # Type narrowing: workspace_id is required
|
|
280
|
+
|
|
265
281
|
# Validate admin access (check env var flag)
|
|
266
282
|
try:
|
|
267
283
|
require_internal_admin_flag_only()
|
|
@@ -349,7 +365,7 @@ def set_cloud_connector_version_override(
|
|
|
349
365
|
current_version_data = api_client.get_connector_version(
|
|
350
366
|
connector_id=actor_id,
|
|
351
367
|
connector_type=actor_type,
|
|
352
|
-
|
|
368
|
+
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
353
369
|
client_id=auth.client_id,
|
|
354
370
|
client_secret=auth.client_secret,
|
|
355
371
|
bearer_token=auth.bearer_token,
|
|
@@ -370,10 +386,10 @@ def set_cloud_connector_version_override(
|
|
|
370
386
|
result = api_client.set_connector_version_override(
|
|
371
387
|
connector_id=actor_id,
|
|
372
388
|
connector_type=actor_type,
|
|
373
|
-
|
|
389
|
+
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
374
390
|
client_id=auth.client_id,
|
|
375
391
|
client_secret=auth.client_secret,
|
|
376
|
-
workspace_id=
|
|
392
|
+
workspace_id=resolved_workspace_id,
|
|
377
393
|
version=version,
|
|
378
394
|
unset=unset,
|
|
379
395
|
override_reason=enhanced_override_reason,
|
|
@@ -386,7 +402,7 @@ def set_cloud_connector_version_override(
|
|
|
386
402
|
updated_version_data = api_client.get_connector_version(
|
|
387
403
|
connector_id=actor_id,
|
|
388
404
|
connector_type=actor_type,
|
|
389
|
-
|
|
405
|
+
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
390
406
|
client_id=auth.client_id,
|
|
391
407
|
client_secret=auth.client_secret,
|
|
392
408
|
bearer_token=auth.bearer_token,
|
|
@@ -434,6 +450,471 @@ def set_cloud_connector_version_override(
|
|
|
434
450
|
)
|
|
435
451
|
|
|
436
452
|
|
|
453
|
+
@mcp_tool(
|
|
454
|
+
destructive=True,
|
|
455
|
+
idempotent=False,
|
|
456
|
+
open_world=True,
|
|
457
|
+
)
|
|
458
|
+
def set_workspace_connector_version_override(
|
|
459
|
+
workspace_id: Annotated[
|
|
460
|
+
str | WorkspaceAliasEnum,
|
|
461
|
+
Field(
|
|
462
|
+
description="The Airbyte Cloud workspace ID (UUID) or alias. "
|
|
463
|
+
"Accepts '@devin-ai-sandbox' as an alias for the Devin AI sandbox workspace."
|
|
464
|
+
),
|
|
465
|
+
],
|
|
466
|
+
connector_name: Annotated[
|
|
467
|
+
str,
|
|
468
|
+
Field(
|
|
469
|
+
description="The connector name (e.g., 'source-github', 'destination-bigquery')."
|
|
470
|
+
),
|
|
471
|
+
],
|
|
472
|
+
connector_type: Annotated[
|
|
473
|
+
Literal["source", "destination"],
|
|
474
|
+
"The type of connector (source or destination)",
|
|
475
|
+
],
|
|
476
|
+
approval_comment_url: Annotated[
|
|
477
|
+
str,
|
|
478
|
+
Field(
|
|
479
|
+
description="URL to a GitHub comment where the admin has explicitly "
|
|
480
|
+
"requested or authorized this deployment. Must be a valid GitHub comment URL. "
|
|
481
|
+
"Required for authorization. The admin email is automatically derived from "
|
|
482
|
+
"the comment author's GitHub profile.",
|
|
483
|
+
),
|
|
484
|
+
],
|
|
485
|
+
version: Annotated[
|
|
486
|
+
str | None,
|
|
487
|
+
Field(
|
|
488
|
+
description="The semver version string to pin to (e.g., '0.1.0'). "
|
|
489
|
+
"Must be None if unset is True.",
|
|
490
|
+
default=None,
|
|
491
|
+
),
|
|
492
|
+
],
|
|
493
|
+
unset: Annotated[
|
|
494
|
+
bool,
|
|
495
|
+
Field(
|
|
496
|
+
description="If True, removes any existing version override. "
|
|
497
|
+
"Cannot be True if version is provided.",
|
|
498
|
+
default=False,
|
|
499
|
+
),
|
|
500
|
+
],
|
|
501
|
+
override_reason: Annotated[
|
|
502
|
+
str | None,
|
|
503
|
+
Field(
|
|
504
|
+
description="Required when setting a version. "
|
|
505
|
+
"Explanation for the override (min 10 characters).",
|
|
506
|
+
default=None,
|
|
507
|
+
),
|
|
508
|
+
],
|
|
509
|
+
override_reason_reference_url: Annotated[
|
|
510
|
+
str | None,
|
|
511
|
+
Field(
|
|
512
|
+
description="Optional URL with more context (e.g., issue link).",
|
|
513
|
+
default=None,
|
|
514
|
+
),
|
|
515
|
+
],
|
|
516
|
+
issue_url: Annotated[
|
|
517
|
+
str | None,
|
|
518
|
+
Field(
|
|
519
|
+
description="URL to the GitHub issue providing context for this operation. "
|
|
520
|
+
"Must be a valid GitHub URL (https://github.com/...). Required for authorization.",
|
|
521
|
+
default=None,
|
|
522
|
+
),
|
|
523
|
+
],
|
|
524
|
+
ai_agent_session_url: Annotated[
|
|
525
|
+
str | None,
|
|
526
|
+
Field(
|
|
527
|
+
description="URL to the AI agent session driving this operation, if applicable. "
|
|
528
|
+
"Provides additional auditability for AI-driven operations.",
|
|
529
|
+
default=None,
|
|
530
|
+
),
|
|
531
|
+
],
|
|
532
|
+
) -> WorkspaceVersionOverrideResult:
|
|
533
|
+
"""Set or clear a workspace-level version override for a connector type.
|
|
534
|
+
|
|
535
|
+
This pins ALL instances of a connector type within a workspace to a specific version.
|
|
536
|
+
For example, pinning 'source-github' at workspace level means all GitHub sources
|
|
537
|
+
in that workspace will use the pinned version.
|
|
538
|
+
|
|
539
|
+
**Admin-only operation** - Requires:
|
|
540
|
+
- AIRBYTE_INTERNAL_ADMIN_FLAG=airbyte.io environment variable
|
|
541
|
+
- issue_url parameter (GitHub issue URL for context)
|
|
542
|
+
- approval_comment_url parameter (GitHub comment URL with approval from an @airbyte.io user)
|
|
543
|
+
|
|
544
|
+
You must specify EXACTLY ONE of `version` OR `unset=True`, but not both.
|
|
545
|
+
When setting a version, `override_reason` is required.
|
|
546
|
+
"""
|
|
547
|
+
# Resolve workspace ID alias (workspace_id is required, so resolved value is never None)
|
|
548
|
+
resolved_workspace_id = WorkspaceAliasEnum.resolve(workspace_id)
|
|
549
|
+
assert resolved_workspace_id is not None # Type narrowing: workspace_id is required
|
|
550
|
+
|
|
551
|
+
# Validate admin access (check env var flag)
|
|
552
|
+
try:
|
|
553
|
+
require_internal_admin_flag_only()
|
|
554
|
+
except CloudAuthError as e:
|
|
555
|
+
return WorkspaceVersionOverrideResult(
|
|
556
|
+
success=False,
|
|
557
|
+
message=f"Admin authentication failed: {e}",
|
|
558
|
+
workspace_id=resolved_workspace_id,
|
|
559
|
+
connector_name=connector_name,
|
|
560
|
+
connector_type=connector_type,
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
# Validate authorization parameters
|
|
564
|
+
validation_errors: list[str] = []
|
|
565
|
+
|
|
566
|
+
if not issue_url:
|
|
567
|
+
validation_errors.append(
|
|
568
|
+
"issue_url is required for authorization (GitHub issue URL)"
|
|
569
|
+
)
|
|
570
|
+
elif not issue_url.startswith("https://github.com/"):
|
|
571
|
+
validation_errors.append(
|
|
572
|
+
f"issue_url must be a valid GitHub URL (https://github.com/...), got: {issue_url}"
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
if not approval_comment_url.startswith("https://github.com/"):
|
|
576
|
+
validation_errors.append(
|
|
577
|
+
f"approval_comment_url must be a valid GitHub URL, got: {approval_comment_url}"
|
|
578
|
+
)
|
|
579
|
+
elif (
|
|
580
|
+
"#issuecomment-" not in approval_comment_url
|
|
581
|
+
and "#discussion_r" not in approval_comment_url
|
|
582
|
+
):
|
|
583
|
+
validation_errors.append(
|
|
584
|
+
"approval_comment_url must be a GitHub comment URL "
|
|
585
|
+
"(containing #issuecomment- or #discussion_r)"
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
if validation_errors:
|
|
589
|
+
return WorkspaceVersionOverrideResult(
|
|
590
|
+
success=False,
|
|
591
|
+
message="Authorization validation failed: " + "; ".join(validation_errors),
|
|
592
|
+
workspace_id=resolved_workspace_id,
|
|
593
|
+
connector_name=connector_name,
|
|
594
|
+
connector_type=connector_type,
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
# Derive admin email from approval comment URL
|
|
598
|
+
try:
|
|
599
|
+
admin_user_email = get_admin_email_from_approval_comment(approval_comment_url)
|
|
600
|
+
except GitHubCommentParseError as e:
|
|
601
|
+
return WorkspaceVersionOverrideResult(
|
|
602
|
+
success=False,
|
|
603
|
+
message=f"Failed to parse approval comment URL: {e}",
|
|
604
|
+
workspace_id=resolved_workspace_id,
|
|
605
|
+
connector_name=connector_name,
|
|
606
|
+
connector_type=connector_type,
|
|
607
|
+
)
|
|
608
|
+
except GitHubAPIError as e:
|
|
609
|
+
return WorkspaceVersionOverrideResult(
|
|
610
|
+
success=False,
|
|
611
|
+
message=f"Failed to fetch approval comment from GitHub: {e}",
|
|
612
|
+
workspace_id=resolved_workspace_id,
|
|
613
|
+
connector_name=connector_name,
|
|
614
|
+
connector_type=connector_type,
|
|
615
|
+
)
|
|
616
|
+
except GitHubUserEmailNotFoundError as e:
|
|
617
|
+
return WorkspaceVersionOverrideResult(
|
|
618
|
+
success=False,
|
|
619
|
+
message=str(e),
|
|
620
|
+
workspace_id=resolved_workspace_id,
|
|
621
|
+
connector_name=connector_name,
|
|
622
|
+
connector_type=connector_type,
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# Build enhanced override reason with audit fields (only for 'set' operations)
|
|
626
|
+
enhanced_override_reason = override_reason
|
|
627
|
+
if not unset and override_reason:
|
|
628
|
+
audit_parts = [override_reason]
|
|
629
|
+
audit_parts.append(f"Issue: {issue_url}")
|
|
630
|
+
audit_parts.append(f"Approval: {approval_comment_url}")
|
|
631
|
+
if ai_agent_session_url:
|
|
632
|
+
audit_parts.append(f"AI Session: {ai_agent_session_url}")
|
|
633
|
+
enhanced_override_reason = " | ".join(audit_parts)
|
|
634
|
+
|
|
635
|
+
# Resolve auth and call API client
|
|
636
|
+
try:
|
|
637
|
+
auth = _resolve_cloud_auth()
|
|
638
|
+
|
|
639
|
+
result = api_client.set_workspace_connector_version_override(
|
|
640
|
+
workspace_id=resolved_workspace_id,
|
|
641
|
+
connector_name=connector_name,
|
|
642
|
+
connector_type=connector_type,
|
|
643
|
+
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
644
|
+
client_id=auth.client_id,
|
|
645
|
+
client_secret=auth.client_secret,
|
|
646
|
+
bearer_token=auth.bearer_token,
|
|
647
|
+
version=version,
|
|
648
|
+
unset=unset,
|
|
649
|
+
override_reason=enhanced_override_reason,
|
|
650
|
+
override_reason_reference_url=override_reason_reference_url,
|
|
651
|
+
user_email=admin_user_email,
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
if unset:
|
|
655
|
+
if result:
|
|
656
|
+
message = f"Successfully cleared workspace-level version override for {connector_name}."
|
|
657
|
+
else:
|
|
658
|
+
message = f"No workspace-level version override was active for {connector_name} (nothing to clear)"
|
|
659
|
+
else:
|
|
660
|
+
message = f"Successfully pinned {connector_name} to version {version} at workspace level."
|
|
661
|
+
|
|
662
|
+
return WorkspaceVersionOverrideResult(
|
|
663
|
+
success=True,
|
|
664
|
+
message=message,
|
|
665
|
+
workspace_id=resolved_workspace_id,
|
|
666
|
+
connector_name=connector_name,
|
|
667
|
+
connector_type=connector_type,
|
|
668
|
+
version=version if not unset else None,
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
except PyAirbyteInputError as e:
|
|
672
|
+
return WorkspaceVersionOverrideResult(
|
|
673
|
+
success=False,
|
|
674
|
+
message=str(e),
|
|
675
|
+
workspace_id=resolved_workspace_id,
|
|
676
|
+
connector_name=connector_name,
|
|
677
|
+
connector_type=connector_type,
|
|
678
|
+
)
|
|
679
|
+
except CloudAuthError as e:
|
|
680
|
+
return WorkspaceVersionOverrideResult(
|
|
681
|
+
success=False,
|
|
682
|
+
message=f"Authentication failed: {e}",
|
|
683
|
+
workspace_id=resolved_workspace_id,
|
|
684
|
+
connector_name=connector_name,
|
|
685
|
+
connector_type=connector_type,
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
@mcp_tool(
|
|
690
|
+
destructive=True,
|
|
691
|
+
idempotent=False,
|
|
692
|
+
open_world=True,
|
|
693
|
+
)
|
|
694
|
+
def set_organization_connector_version_override(
|
|
695
|
+
organization_id: Annotated[
|
|
696
|
+
str,
|
|
697
|
+
Field(description="The Airbyte Cloud organization ID."),
|
|
698
|
+
],
|
|
699
|
+
connector_name: Annotated[
|
|
700
|
+
str,
|
|
701
|
+
Field(
|
|
702
|
+
description="The connector name (e.g., 'source-github', 'destination-bigquery')."
|
|
703
|
+
),
|
|
704
|
+
],
|
|
705
|
+
connector_type: Annotated[
|
|
706
|
+
Literal["source", "destination"],
|
|
707
|
+
"The type of connector (source or destination)",
|
|
708
|
+
],
|
|
709
|
+
approval_comment_url: Annotated[
|
|
710
|
+
str,
|
|
711
|
+
Field(
|
|
712
|
+
description="URL to a GitHub comment where the admin has explicitly "
|
|
713
|
+
"requested or authorized this deployment. Must be a valid GitHub comment URL. "
|
|
714
|
+
"Required for authorization. The admin email is automatically derived from "
|
|
715
|
+
"the comment author's GitHub profile.",
|
|
716
|
+
),
|
|
717
|
+
],
|
|
718
|
+
version: Annotated[
|
|
719
|
+
str | None,
|
|
720
|
+
Field(
|
|
721
|
+
description="The semver version string to pin to (e.g., '0.1.0'). "
|
|
722
|
+
"Must be None if unset is True.",
|
|
723
|
+
default=None,
|
|
724
|
+
),
|
|
725
|
+
],
|
|
726
|
+
unset: Annotated[
|
|
727
|
+
bool,
|
|
728
|
+
Field(
|
|
729
|
+
description="If True, removes any existing version override. "
|
|
730
|
+
"Cannot be True if version is provided.",
|
|
731
|
+
default=False,
|
|
732
|
+
),
|
|
733
|
+
],
|
|
734
|
+
override_reason: Annotated[
|
|
735
|
+
str | None,
|
|
736
|
+
Field(
|
|
737
|
+
description="Required when setting a version. "
|
|
738
|
+
"Explanation for the override (min 10 characters).",
|
|
739
|
+
default=None,
|
|
740
|
+
),
|
|
741
|
+
],
|
|
742
|
+
override_reason_reference_url: Annotated[
|
|
743
|
+
str | None,
|
|
744
|
+
Field(
|
|
745
|
+
description="Optional URL with more context (e.g., issue link).",
|
|
746
|
+
default=None,
|
|
747
|
+
),
|
|
748
|
+
],
|
|
749
|
+
issue_url: Annotated[
|
|
750
|
+
str | None,
|
|
751
|
+
Field(
|
|
752
|
+
description="URL to the GitHub issue providing context for this operation. "
|
|
753
|
+
"Must be a valid GitHub URL (https://github.com/...). Required for authorization.",
|
|
754
|
+
default=None,
|
|
755
|
+
),
|
|
756
|
+
],
|
|
757
|
+
ai_agent_session_url: Annotated[
|
|
758
|
+
str | None,
|
|
759
|
+
Field(
|
|
760
|
+
description="URL to the AI agent session driving this operation, if applicable. "
|
|
761
|
+
"Provides additional auditability for AI-driven operations.",
|
|
762
|
+
default=None,
|
|
763
|
+
),
|
|
764
|
+
],
|
|
765
|
+
) -> OrganizationVersionOverrideResult:
|
|
766
|
+
"""Set or clear an organization-level version override for a connector type.
|
|
767
|
+
|
|
768
|
+
This pins ALL instances of a connector type across an entire organization to a
|
|
769
|
+
specific version. For example, pinning 'source-github' at organization level means
|
|
770
|
+
all GitHub sources in all workspaces within that organization will use the pinned version.
|
|
771
|
+
|
|
772
|
+
**Admin-only operation** - Requires:
|
|
773
|
+
- AIRBYTE_INTERNAL_ADMIN_FLAG=airbyte.io environment variable
|
|
774
|
+
- issue_url parameter (GitHub issue URL for context)
|
|
775
|
+
- approval_comment_url parameter (GitHub comment URL with approval from an @airbyte.io user)
|
|
776
|
+
|
|
777
|
+
You must specify EXACTLY ONE of `version` OR `unset=True`, but not both.
|
|
778
|
+
When setting a version, `override_reason` is required.
|
|
779
|
+
"""
|
|
780
|
+
# Validate admin access (check env var flag)
|
|
781
|
+
try:
|
|
782
|
+
require_internal_admin_flag_only()
|
|
783
|
+
except CloudAuthError as e:
|
|
784
|
+
return OrganizationVersionOverrideResult(
|
|
785
|
+
success=False,
|
|
786
|
+
message=f"Admin authentication failed: {e}",
|
|
787
|
+
organization_id=organization_id,
|
|
788
|
+
connector_name=connector_name,
|
|
789
|
+
connector_type=connector_type,
|
|
790
|
+
)
|
|
791
|
+
|
|
792
|
+
# Validate authorization parameters
|
|
793
|
+
validation_errors: list[str] = []
|
|
794
|
+
|
|
795
|
+
if not issue_url:
|
|
796
|
+
validation_errors.append(
|
|
797
|
+
"issue_url is required for authorization (GitHub issue URL)"
|
|
798
|
+
)
|
|
799
|
+
elif not issue_url.startswith("https://github.com/"):
|
|
800
|
+
validation_errors.append(
|
|
801
|
+
f"issue_url must be a valid GitHub URL (https://github.com/...), got: {issue_url}"
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
if not approval_comment_url.startswith("https://github.com/"):
|
|
805
|
+
validation_errors.append(
|
|
806
|
+
f"approval_comment_url must be a valid GitHub URL, got: {approval_comment_url}"
|
|
807
|
+
)
|
|
808
|
+
elif (
|
|
809
|
+
"#issuecomment-" not in approval_comment_url
|
|
810
|
+
and "#discussion_r" not in approval_comment_url
|
|
811
|
+
):
|
|
812
|
+
validation_errors.append(
|
|
813
|
+
"approval_comment_url must be a GitHub comment URL "
|
|
814
|
+
"(containing #issuecomment- or #discussion_r)"
|
|
815
|
+
)
|
|
816
|
+
|
|
817
|
+
if validation_errors:
|
|
818
|
+
return OrganizationVersionOverrideResult(
|
|
819
|
+
success=False,
|
|
820
|
+
message="Authorization validation failed: " + "; ".join(validation_errors),
|
|
821
|
+
organization_id=organization_id,
|
|
822
|
+
connector_name=connector_name,
|
|
823
|
+
connector_type=connector_type,
|
|
824
|
+
)
|
|
825
|
+
|
|
826
|
+
# Derive admin email from approval comment URL
|
|
827
|
+
try:
|
|
828
|
+
admin_user_email = get_admin_email_from_approval_comment(approval_comment_url)
|
|
829
|
+
except GitHubCommentParseError as e:
|
|
830
|
+
return OrganizationVersionOverrideResult(
|
|
831
|
+
success=False,
|
|
832
|
+
message=f"Failed to parse approval comment URL: {e}",
|
|
833
|
+
organization_id=organization_id,
|
|
834
|
+
connector_name=connector_name,
|
|
835
|
+
connector_type=connector_type,
|
|
836
|
+
)
|
|
837
|
+
except GitHubAPIError as e:
|
|
838
|
+
return OrganizationVersionOverrideResult(
|
|
839
|
+
success=False,
|
|
840
|
+
message=f"Failed to fetch approval comment from GitHub: {e}",
|
|
841
|
+
organization_id=organization_id,
|
|
842
|
+
connector_name=connector_name,
|
|
843
|
+
connector_type=connector_type,
|
|
844
|
+
)
|
|
845
|
+
except GitHubUserEmailNotFoundError as e:
|
|
846
|
+
return OrganizationVersionOverrideResult(
|
|
847
|
+
success=False,
|
|
848
|
+
message=str(e),
|
|
849
|
+
organization_id=organization_id,
|
|
850
|
+
connector_name=connector_name,
|
|
851
|
+
connector_type=connector_type,
|
|
852
|
+
)
|
|
853
|
+
|
|
854
|
+
# Build enhanced override reason with audit fields (only for 'set' operations)
|
|
855
|
+
enhanced_override_reason = override_reason
|
|
856
|
+
if not unset and override_reason:
|
|
857
|
+
audit_parts = [override_reason]
|
|
858
|
+
audit_parts.append(f"Issue: {issue_url}")
|
|
859
|
+
audit_parts.append(f"Approval: {approval_comment_url}")
|
|
860
|
+
if ai_agent_session_url:
|
|
861
|
+
audit_parts.append(f"AI Session: {ai_agent_session_url}")
|
|
862
|
+
enhanced_override_reason = " | ".join(audit_parts)
|
|
863
|
+
|
|
864
|
+
# Resolve auth and call API client
|
|
865
|
+
try:
|
|
866
|
+
auth = _resolve_cloud_auth()
|
|
867
|
+
|
|
868
|
+
result = api_client.set_organization_connector_version_override(
|
|
869
|
+
organization_id=organization_id,
|
|
870
|
+
connector_name=connector_name,
|
|
871
|
+
connector_type=connector_type,
|
|
872
|
+
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
873
|
+
client_id=auth.client_id,
|
|
874
|
+
client_secret=auth.client_secret,
|
|
875
|
+
bearer_token=auth.bearer_token,
|
|
876
|
+
version=version,
|
|
877
|
+
unset=unset,
|
|
878
|
+
override_reason=enhanced_override_reason,
|
|
879
|
+
override_reason_reference_url=override_reason_reference_url,
|
|
880
|
+
user_email=admin_user_email,
|
|
881
|
+
)
|
|
882
|
+
|
|
883
|
+
if unset:
|
|
884
|
+
if result:
|
|
885
|
+
message = f"Successfully cleared organization-level version override for {connector_name}."
|
|
886
|
+
else:
|
|
887
|
+
message = f"No organization-level version override was active for {connector_name} (nothing to clear)"
|
|
888
|
+
else:
|
|
889
|
+
message = f"Successfully pinned {connector_name} to version {version} at organization level."
|
|
890
|
+
|
|
891
|
+
return OrganizationVersionOverrideResult(
|
|
892
|
+
success=True,
|
|
893
|
+
message=message,
|
|
894
|
+
organization_id=organization_id,
|
|
895
|
+
connector_name=connector_name,
|
|
896
|
+
connector_type=connector_type,
|
|
897
|
+
version=version if not unset else None,
|
|
898
|
+
)
|
|
899
|
+
|
|
900
|
+
except PyAirbyteInputError as e:
|
|
901
|
+
return OrganizationVersionOverrideResult(
|
|
902
|
+
success=False,
|
|
903
|
+
message=str(e),
|
|
904
|
+
organization_id=organization_id,
|
|
905
|
+
connector_name=connector_name,
|
|
906
|
+
connector_type=connector_type,
|
|
907
|
+
)
|
|
908
|
+
except CloudAuthError as e:
|
|
909
|
+
return OrganizationVersionOverrideResult(
|
|
910
|
+
success=False,
|
|
911
|
+
message=f"Authentication failed: {e}",
|
|
912
|
+
organization_id=organization_id,
|
|
913
|
+
connector_name=connector_name,
|
|
914
|
+
connector_type=connector_type,
|
|
915
|
+
)
|
|
916
|
+
|
|
917
|
+
|
|
437
918
|
def register_cloud_connector_version_tools(app: FastMCP) -> None:
|
|
438
919
|
"""Register cloud connector version management tools with the FastMCP app.
|
|
439
920
|
|
|
@@ -18,6 +18,7 @@ import yaml
|
|
|
18
18
|
from fastmcp import FastMCP
|
|
19
19
|
from pydantic import BaseModel, Field
|
|
20
20
|
|
|
21
|
+
from airbyte_ops_mcp.github_actions import trigger_workflow_dispatch
|
|
21
22
|
from airbyte_ops_mcp.github_api import (
|
|
22
23
|
GITHUB_API_BASE,
|
|
23
24
|
get_pr_head_ref,
|
|
@@ -149,49 +150,6 @@ def _get_connector_metadata(
|
|
|
149
150
|
return yaml.safe_load(content)
|
|
150
151
|
|
|
151
152
|
|
|
152
|
-
def _trigger_workflow_dispatch(
|
|
153
|
-
owner: str,
|
|
154
|
-
repo: str,
|
|
155
|
-
workflow_file: str,
|
|
156
|
-
ref: str,
|
|
157
|
-
inputs: dict,
|
|
158
|
-
token: str,
|
|
159
|
-
) -> str:
|
|
160
|
-
"""Trigger a GitHub Actions workflow via workflow_dispatch.
|
|
161
|
-
|
|
162
|
-
Args:
|
|
163
|
-
owner: Repository owner (e.g., "airbytehq")
|
|
164
|
-
repo: Repository name (e.g., "airbyte")
|
|
165
|
-
workflow_file: Workflow file name (e.g., "publish-connectors-prerelease-command.yml")
|
|
166
|
-
ref: Git ref to run the workflow on (branch name)
|
|
167
|
-
inputs: Workflow inputs dictionary
|
|
168
|
-
token: GitHub API token
|
|
169
|
-
|
|
170
|
-
Returns:
|
|
171
|
-
URL to view workflow runs.
|
|
172
|
-
|
|
173
|
-
Raises:
|
|
174
|
-
requests.HTTPError: If API request fails.
|
|
175
|
-
"""
|
|
176
|
-
url = f"{GITHUB_API_BASE}/repos/{owner}/{repo}/actions/workflows/{workflow_file}/dispatches"
|
|
177
|
-
headers = {
|
|
178
|
-
"Authorization": f"Bearer {token}",
|
|
179
|
-
"Accept": "application/vnd.github+json",
|
|
180
|
-
"X-GitHub-Api-Version": "2022-11-28",
|
|
181
|
-
}
|
|
182
|
-
payload = {
|
|
183
|
-
"ref": ref,
|
|
184
|
-
"inputs": inputs,
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
response = requests.post(url, headers=headers, json=payload, timeout=30)
|
|
188
|
-
response.raise_for_status()
|
|
189
|
-
|
|
190
|
-
# workflow_dispatch returns 204 No Content on success
|
|
191
|
-
# Return URL to view workflow runs
|
|
192
|
-
return f"https://github.com/{owner}/{repo}/actions/workflows/{workflow_file}"
|
|
193
|
-
|
|
194
|
-
|
|
195
153
|
@mcp_tool(
|
|
196
154
|
read_only=False,
|
|
197
155
|
destructive=False,
|
|
@@ -271,14 +229,17 @@ def publish_connector_to_airbyte_registry(
|
|
|
271
229
|
|
|
272
230
|
# Trigger the workflow on the default branch
|
|
273
231
|
# The workflow will checkout the PR branch via inputs.gitref
|
|
274
|
-
|
|
232
|
+
dispatch_result = trigger_workflow_dispatch(
|
|
275
233
|
owner=DEFAULT_REPO_OWNER,
|
|
276
234
|
repo=target_repo_name,
|
|
277
235
|
workflow_file=target_workflow,
|
|
278
236
|
ref=target_branch,
|
|
279
237
|
inputs=workflow_inputs,
|
|
280
238
|
token=token,
|
|
239
|
+
find_run=True,
|
|
281
240
|
)
|
|
241
|
+
# Use the specific run URL if found, otherwise fall back to the workflow URL
|
|
242
|
+
workflow_url = dispatch_result.run_url or dispatch_result.workflow_url
|
|
282
243
|
|
|
283
244
|
# Try to compute docker_image and docker_image_tag from connector metadata
|
|
284
245
|
docker_image: str | None = None
|