feat(cloud): Add workspace create, delete, and rename support#1032
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This PyAirbyte VersionYou can test this version of PyAirbyte using the following: # Run PyAirbyte CLI from this branch:
uvx --from 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1777313749-workspace-create-base' pyairbyte --help
# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1777313749-workspace-create-base'PR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
📚 Show Repo GuidanceHelpful ResourcesCommunity SupportQuestions? Join the #pyairbyte channel in our Slack workspace. |
Aaron ("AJ") Steers (aaronsteers)
left a comment
There was a problem hiding this comment.
Find the "Thank you for using (Py)Airbyte" telemetry message, and replace "PyAirbyte" with "Airbyte". Since PyAirbyte is wrapped now in other tools, we should make the telemetry notice more generic (if we haven't done so already).
|
Addressed the telemetry review note by changing the one-time notice from: "Thank you for using PyAirbyte!\n"to: "Thank you for using Airbyte!\n"Also ran: uv run ruff check airbyte/_util/telemetry.py
uv run pytest -q tests/unit_tests/test_anonymous_usage_stats.pyThis is in response to the review comment about making the telemetry wording generic for wrappers around PyAirbyte. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds workspace-creation end-to-end: ChangesWorkspace Creation API
Sequence Diagram(s)sequenceDiagram
participant CloudClient
participant api_util
participant AirbyteServer
CloudClient->>api_util: create_workspace(name, organization_id?, region_id?, auth)
api_util->>AirbyteServer: POST /workspaces { WorkspaceCreateRequest }
AirbyteServer-->>api_util: WorkspaceResponse or error
api_util-->>CloudClient: WorkspaceResponse or AirbyteError
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds workspace creation support to the PyAirbyte Cloud layer, exposing the Airbyte Public API WorkspaceCreateRequest through api_util plus convenience wrappers on CloudClient and CloudWorkspace, along with unit tests to verify request forwarding and wrapper behavior.
Changes:
- Add
api_util.create_workspace()to call the public Airbyte API workspace-create endpoint. - Add
CloudClient.create_workspace()to defaultorganization_idfrom the client when not provided. - Add
CloudWorkspace.create_workspace()convenience wrapper and unit tests covering forwarding/defaulting behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
airbyte/_util/api_util.py |
Adds low-level create_workspace() API utility and error handling for non-OK responses. |
airbyte/cloud/client.py |
Adds CloudClient.create_workspace() wrapper that resolves the default organization ID. |
airbyte/cloud/workspaces.py |
Adds CloudWorkspace.create_workspace() wrapper using workspace credentials. |
tests/unit_tests/test_cloud_api_util.py |
Adds unit test ensuring WorkspaceCreateRequest is constructed/forwarded correctly. |
tests/unit_tests/test_cloud_credentials.py |
Adds unit tests for client/workspace wrapper forwarding and organization defaulting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@airbyte/_util/api_util.py`:
- Around line 304-321: The call to airbyte_instance.workspaces.create_workspace
should be wrapped in a try/except so transport/SDK exceptions are converted into
AirbyteError; surround the invocation that builds models.WorkspaceCreateRequest
and assigns response with a try block, catch Exception as exc, and raise
AirbyteError with a descriptive message and context (include request parameters
like name/organization_id/region_id and exc details), leaving the existing
status_ok(response.status_code) check and workspace_response return intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f0ff294a-5bcf-4f6b-aa02-9382c583acc6
📒 Files selected for processing (6)
airbyte/_util/api_util.pyairbyte/_util/telemetry.pyairbyte/cloud/client.pyairbyte/cloud/workspaces.pytests/unit_tests/test_cloud_api_util.pytests/unit_tests/test_cloud_credentials.py
There was a problem hiding this comment.
♻️ Duplicate comments (1)
airbyte/_util/api_util.py (1)
304-310:⚠️ Potential issue | 🟠 Major | ⚡ Quick winWrap the API call in try/except to normalize SDK errors, wdyt?
The API invocation isn't protected against SDKError exceptions. If the SDK raises a transport or authentication error, it will bypass the module's error contract instead of being normalized to AirbyteError. Other functions in this file (like
get_workspaceat lines 265-272) consistently wrap these calls.🔧 Proposed fix
def create_workspace( *, name: str, api_root: str, client_id: SecretString | None, client_secret: SecretString | None, bearer_token: SecretString | None, organization_id: str | None = None, region_id: str | None = None, ) -> models.WorkspaceResponse: """Create a workspace.""" airbyte_instance = get_airbyte_server_instance( api_root=api_root, client_id=client_id, client_secret=client_secret, bearer_token=bearer_token, ) - response = airbyte_instance.workspaces.create_workspace( - request=models.WorkspaceCreateRequest( - name=name, - organization_id=organization_id, - region_id=region_id, - ) - ) + base_context = { + "name": name, + "organization_id": organization_id, + "region_id": region_id, + "api_root": api_root, + } + try: + response = airbyte_instance.workspaces.create_workspace( + request=models.WorkspaceCreateRequest( + name=name, + organization_id=organization_id, + region_id=region_id, + ) + ) + except SDKError as e: + raise _wrap_sdk_error(e, base_context) from e if status_ok(response.status_code) and response.workspace_response: return response.workspace_response🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@airbyte/_util/api_util.py` around lines 304 - 310, The workspace creation API call (airbyte_instance.workspaces.create_workspace with models.WorkspaceCreateRequest) is not wrapped in the same try/except normalization used elsewhere (see get_workspace); update create_workspace to catch the SDKError (or the SDK's base exception) thrown by the Airbyte client and re-raise or wrap it as AirbyteError so callers see the normalized module error contract, keeping the original error details in the AirbyteError message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@airbyte/_util/api_util.py`:
- Around line 304-310: The workspace creation API call
(airbyte_instance.workspaces.create_workspace with
models.WorkspaceCreateRequest) is not wrapped in the same try/except
normalization used elsewhere (see get_workspace); update create_workspace to
catch the SDKError (or the SDK's base exception) thrown by the Airbyte client
and re-raise or wrap it as AirbyteError so callers see the normalized module
error contract, keeping the original error details in the AirbyteError message.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 8cbff4d7-dfda-4ef2-8e39-e475103aa448
📒 Files selected for processing (1)
airbyte/_util/api_util.py
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@airbyte/_util/api_util.py`:
- Around line 431-449: In permanently_delete_workspace, wrap the call to
airbyte_instance.workspaces.delete_workspace(...) in a try/except catching
SDKError and re-raise using _wrap_sdk_error(e, base_context) so SDK/transport
failures are normalized to AirbyteError like other helpers; ensure base_context
contains workspace_id and any relevant request info and keep the existing
status_ok response handling after the try block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 73880afe-d36c-4618-a920-ec04ae0ad6ae
📒 Files selected for processing (5)
airbyte/_util/api_util.pyairbyte/cloud/client.pyairbyte/cloud/workspaces.pytests/unit_tests/test_cloud_api_util.pytests/unit_tests/test_cloud_credentials.py
Summary
Asked for by AJ Steers as the base PyAirbyte layer for Airbyte Cloud workspace management.
api_util.create_workspace()using the public Airbyte APIWorkspaceCreateRequestCloudClient.create_workspace()so callers can create a workspace with the client's default organization IDapi_util.rename_workspace()andCloudClient.rename_workspace()for explicit workspace renamesapi_util.permanently_delete_workspace(),CloudClient.permanently_delete_workspace(), andCloudWorkspace.permanently_delete()for empty-workspace deletiondelete-meordeleteme, and require the workspace to have no listed connections before calling the delete endpointReview & Testing Checklist for Human
organization_id=Noneshould remain allowed for API calls that infer/default organization server-side.CloudClientis the right public creation surface and thatCloudWorkspaceshould only keep instance-scoped actions like rename/delete.delete-meempty test workspace for delete.Notes
Local validation run:
uv run ruff format --check airbyte/_util/api_util.py tests/unit_tests/test_cloud_api_util.pyuv run ruff check airbyte/_util/api_util.py tests/unit_tests/test_cloud_api_util.pyuv run pytest -q tests/unit_tests/test_cloud_api_util.pyuv run ruff format --check airbyte/cloud/workspaces.py tests/unit_tests/test_cloud_credentials.pyuv run ruff check airbyte/cloud/workspaces.py tests/unit_tests/test_cloud_credentials.pyuv run pytest -q tests/unit_tests/test_cloud_credentials.pyuv run ruff format airbyte/_util/api_util.py airbyte/cloud/client.py airbyte/cloud/workspaces.py airbyte/exceptions.py tests/unit_tests/test_cloud_api_util.pyuv run ruff check airbyte/_util/api_util.py airbyte/cloud/client.py airbyte/cloud/workspaces.py airbyte/exceptions.py tests/unit_tests/test_cloud_api_util.pyuv run pytest -q tests/unit_tests/test_cloud_api_util.py tests/unit_tests/test_cloud_credentials.pyLink to Devin session: https://app.devin.ai/sessions/a1ddc40130ad4cf09fcf4b8cd7b82354
Requested by: Aaron ("AJ") Steers (@aaronsteers)
Important
Auto-merge enabled.
This PR is set to merge automatically when all requirements are met.