diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a69c2e7..e4988ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,15 +2,15 @@ name: CI on: push: branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + - "generated" + - "codegen/**" + - "integrated/**" + - "stl-preview-head/**" + - "stl-preview-base/**" pull_request: branches-ignore: - - 'stl-preview-head/**' - - 'stl-preview-base/**' + - "stl-preview-head/**" + - "stl-preview-base/**" jobs: lint: @@ -19,15 +19,15 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/gitpod-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: '0.44.0' - RYE_INSTALL_OPTION: '--yes' + RYE_VERSION: "0.44.0" + RYE_INSTALL_OPTION: "--yes" - name: Install dependencies run: rye sync --all-features @@ -44,15 +44,15 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/gitpod-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: '0.44.0' - RYE_INSTALL_OPTION: '--yes' + RYE_VERSION: "0.44.0" + RYE_INSTALL_OPTION: "--yes" - name: Install dependencies run: rye sync --all-features @@ -81,15 +81,15 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/gitpod-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: '0.44.0' - RYE_INSTALL_OPTION: '--yes' + RYE_VERSION: "0.44.0" + RYE_INSTALL_OPTION: "--yes" - name: Bootstrap run: ./scripts/bootstrap diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 3343ab6..0c20e7d 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -17,19 +17,19 @@ jobs: id-token: write steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Install Rye uses: eifinger/setup-rye@c694239a43768373e87d0103d7f547027a23f3c8 # v4 with: version: '0.44.0' - + - name: Sync dependencies run: rye sync - name: Build package run: rye build --clean - + - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1 with: diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4208b5c..1b77f50 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.0" + ".": "0.7.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index e42a5ca..886c83c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 160 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-3935e467f9c15925790aada293124db82bb5d6840eeac52d81fbac6a9b0fd154.yml -openapi_spec_hash: b417d7f10ea430216e9b70e4468a3212 -config_hash: d3267594264bfb76d2ee7e881d5f8a5a +configured_endpoints: 170 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-2423c089f280cdf34a987d40531692097a69f4aa971c6adf9aeec4fd7984cec2.yml +openapi_spec_hash: 24037c3ab9ceca689150d07ecec7aa80 +config_hash: d726afb2a92132197e4eae04303e8041 diff --git a/CHANGELOG.md b/CHANGELOG.md index e6b615d..9d5779c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## 0.7.0 (2026-01-21) + +Full Changelog: [v0.6.0...v0.7.0](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.6.0...v0.7.0) + +### Features + +* [api] Introduce RPCs to share resources with individual users ([df1cf39](https://github.com/gitpod-io/gitpod-sdk-python/commit/df1cf39a9c1b387c9e9313bfec68a97759762e0b)) +* [api] sorting for `ListMembers` ([838e74c](https://github.com/gitpod-io/gitpod-sdk-python/commit/838e74c4da4b57590a6dd0af19bdd20faf7d2805)) +* [backend] Adding direct_share field to groups ([78c0bdd](https://github.com/gitpod-io/gitpod-sdk-python/commit/78c0bddc838e217007729d723283f9e9cd04d9a2)) +* [backend] Introduce role and member status filtering for `ListMembers` ([34fb372](https://github.com/gitpod-io/gitpod-sdk-python/commit/34fb372aef655ae57fc99d5b37e152c75d831af5)) +* **agent:** add spec mode for planning before interactive implementation ([de6bee5](https://github.com/gitpod-io/gitpod-sdk-python/commit/de6bee5d7d337456f1a19de0659cd6957c7c1a9b)) +* API for SCIM configuration management ([70becd4](https://github.com/gitpod-io/gitpod-sdk-python/commit/70becd4cd142fac4fc839018d52fb4cb93e17834)) +* **api:** add CheckRepositoryAccess API for repository access validation ([b34ed1b](https://github.com/gitpod-io/gitpod-sdk-python/commit/b34ed1b8ecd39343ed02c5f376e9495775912140)) +* **api:** add draft and state fields to PullRequest proto ([e0023da](https://github.com/gitpod-io/gitpod-sdk-python/commit/e0023da5a30344c2fc87ebce55e26101c4ad40b5)) +* **api:** add inputs array to UserInputBlock proto ([8262825](https://github.com/gitpod-io/gitpod-sdk-python/commit/8262825c21be1de663b9a3aad29e9f9fe1cf219d)) +* **api:** add ListSCMOrganizations endpoint ([9c8f7ea](https://github.com/gitpod-io/gitpod-sdk-python/commit/9c8f7eadd38bc0326ecf1be48706003fa258257c)) +* **api:** add search, creator, and status filters to ListWorkflows ([ddd18c0](https://github.com/gitpod-io/gitpod-sdk-python/commit/ddd18c09beb0f24e076818783d2dae09ca9b9f8b)) +* **api:** improve SearchRepositories pagination with next_page and total_count ([2847a10](https://github.com/gitpod-io/gitpod-sdk-python/commit/2847a10e6cbb09be83b012e8a6fcabd32f49e019)) +* **automations:** add before_snapshot trigger type ([9cd272f](https://github.com/gitpod-io/gitpod-sdk-python/commit/9cd272f98f2215b834a841ca34c52ce04fd2898e)) +* **client:** add support for binary request streaming ([be5a823](https://github.com/gitpod-io/gitpod-sdk-python/commit/be5a8235224ff1ecf25464e716191fbf3c7c7fb1)) +* **dashboard:** show tier badge in org selector ([89fd8fe](https://github.com/gitpod-io/gitpod-sdk-python/commit/89fd8fef7f9de200e4aecd563c965d4209427052)) +* Define SCIMConfiguration database schema ([03bd185](https://github.com/gitpod-io/gitpod-sdk-python/commit/03bd1858ec2aefbd4c20a71c206135c441afa99c)) +* move agent mode from Spec to Status, add AgentModeChange signals ([a55115b](https://github.com/gitpod-io/gitpod-sdk-python/commit/a55115ba054078dcb689222cc150b2b1f56077bf)) +* **secrets:** add ServiceAccountSecret entity with full support ([30e17c5](https://github.com/gitpod-io/gitpod-sdk-python/commit/30e17c55b991286527f64c8857b04dd9b5a2ba7b)) + + +### Chores + +* **internal:** update `actions/checkout` version ([53dcf30](https://github.com/gitpod-io/gitpod-sdk-python/commit/53dcf30cb41a6cbf30ce510b0b2d46cdd5895008)) + ## 0.6.0 (2026-01-09) Full Changelog: [v0.5.2...v0.6.0](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.5.2...v0.6.0) diff --git a/api.md b/api.md index 29f93a4..0b70b7b 100644 --- a/api.md +++ b/api.md @@ -10,11 +10,14 @@ from gitpod.types import ( FieldValue, Gateway, OrganizationRole, + OrganizationTier, Principal, ProjectEnvironmentClass, + ResourceRole, ResourceType, RunsOn, SecretRef, + State, Subject, Task, TaskExecution, @@ -300,7 +303,7 @@ Methods: Types: ```python -from gitpod.types.groups import ResourceRole, RoleAssignment, RoleAssignmentCreateResponse +from gitpod.types.groups import RoleAssignment, RoleAssignmentCreateResponse ``` Methods: @@ -309,6 +312,13 @@ Methods: - client.groups.role_assignments.list(\*\*params) -> SyncAssignmentsPage[RoleAssignment] - client.groups.role_assignments.delete(\*\*params) -> object +## Shares + +Methods: + +- client.groups.shares.create(\*\*params) -> object +- client.groups.shares.delete(\*\*params) -> object + # Identity Types: @@ -337,7 +347,6 @@ from gitpod.types import ( InviteDomains, Organization, OrganizationMember, - OrganizationTier, OrganizationCreateResponse, OrganizationRetrieveResponse, OrganizationUpdateResponse, @@ -437,6 +446,29 @@ Methods: - client.organizations.policies.retrieve(\*\*params) -> PolicyRetrieveResponse - client.organizations.policies.update(\*\*params) -> object +## ScimConfigurations + +Types: + +```python +from gitpod.types.organizations import ( + ScimConfiguration, + ScimConfigurationCreateResponse, + ScimConfigurationRetrieveResponse, + ScimConfigurationUpdateResponse, + ScimConfigurationRegenerateTokenResponse, +) +``` + +Methods: + +- client.organizations.scim_configurations.create(\*\*params) -> ScimConfigurationCreateResponse +- client.organizations.scim_configurations.retrieve(\*\*params) -> ScimConfigurationRetrieveResponse +- client.organizations.scim_configurations.update(\*\*params) -> ScimConfigurationUpdateResponse +- client.organizations.scim_configurations.list(\*\*params) -> SyncScimConfigurationsPage[ScimConfiguration] +- client.organizations.scim_configurations.delete(\*\*params) -> object +- client.organizations.scim_configurations.regenerate_token(\*\*params) -> ScimConfigurationRegenerateTokenResponse + ## SSOConfigurations Types: @@ -565,8 +597,10 @@ from gitpod.types import ( RunnerCreateResponse, RunnerRetrieveResponse, RunnerCheckAuthenticationForHostResponse, + RunnerCheckRepositoryAccessResponse, RunnerCreateLogsTokenResponse, RunnerCreateRunnerTokenResponse, + RunnerListScmOrganizationsResponse, RunnerParseContextURLResponse, RunnerSearchRepositoriesResponse, ) @@ -580,8 +614,10 @@ Methods: - client.runners.list(\*\*params) -> SyncRunnersPage[Runner] - client.runners.delete(\*\*params) -> object - client.runners.check_authentication_for_host(\*\*params) -> RunnerCheckAuthenticationForHostResponse +- client.runners.check_repository_access(\*\*params) -> RunnerCheckRepositoryAccessResponse - client.runners.create_logs_token(\*\*params) -> RunnerCreateLogsTokenResponse - client.runners.create_runner_token(\*\*params) -> RunnerCreateRunnerTokenResponse +- client.runners.list_scm_organizations(\*\*params) -> RunnerListScmOrganizationsResponse - client.runners.parse_context_url(\*\*params) -> RunnerParseContextURLResponse - client.runners.search_repositories(\*\*params) -> RunnerSearchRepositoriesResponse diff --git a/pyproject.toml b/pyproject.toml index 6136eaf..4f4d826 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "gitpod-sdk" -version = "0.6.0" +version = "0.7.0" description = "The official Python library for the gitpod API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/gitpod/_base_client.py b/src/gitpod/_base_client.py index 1613979..e6ccedf 100644 --- a/src/gitpod/_base_client.py +++ b/src/gitpod/_base_client.py @@ -9,6 +9,7 @@ import inspect import logging import platform +import warnings import email.utils from types import TracebackType from random import random @@ -51,9 +52,11 @@ ResponseT, AnyMapping, PostParser, + BinaryTypes, RequestFiles, HttpxSendArgs, RequestOptions, + AsyncBinaryTypes, HttpxRequestFiles, ModelBuilderProtocol, not_given, @@ -477,8 +480,19 @@ def _build_request( retries_taken: int = 0, ) -> httpx.Request: if log.isEnabledFor(logging.DEBUG): - log.debug("Request options: %s", model_dump(options, exclude_unset=True)) - + log.debug( + "Request options: %s", + model_dump( + options, + exclude_unset=True, + # Pydantic v1 can't dump every type we support in content, so we exclude it for now. + exclude={ + "content", + } + if PYDANTIC_V1 + else {}, + ), + ) kwargs: dict[str, Any] = {} json_data = options.json_data @@ -532,7 +546,13 @@ def _build_request( is_body_allowed = options.method.lower() != "get" if is_body_allowed: - if isinstance(json_data, bytes): + if options.content is not None and json_data is not None: + raise TypeError("Passing both `content` and `json_data` is not supported") + if options.content is not None and files is not None: + raise TypeError("Passing both `content` and `files` is not supported") + if options.content is not None: + kwargs["content"] = options.content + elif isinstance(json_data, bytes): kwargs["content"] = json_data else: kwargs["json"] = json_data if is_given(json_data) else None @@ -1194,6 +1214,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[False] = False, @@ -1206,6 +1227,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[True], @@ -1219,6 +1241,7 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool, @@ -1231,13 +1254,25 @@ def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, files: RequestFiles | None = None, stream: bool = False, stream_cls: type[_StreamT] | None = None, ) -> ResponseT | _StreamT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="post", url=path, json_data=body, files=to_httpx_files(files), **options + method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)) @@ -1247,11 +1282,23 @@ def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return self.request(cast_to, opts) @@ -1261,11 +1308,23 @@ def put( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="put", url=path, json_data=body, files=to_httpx_files(files), **options + method="put", url=path, json_data=body, content=content, files=to_httpx_files(files), **options ) return self.request(cast_to, opts) @@ -1275,9 +1334,19 @@ def delete( *, cast_to: Type[ResponseT], body: Body | None = None, + content: BinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return self.request(cast_to, opts) def get_api_list( @@ -1717,6 +1786,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[False] = False, @@ -1729,6 +1799,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[True], @@ -1742,6 +1813,7 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool, @@ -1754,13 +1826,25 @@ async def post( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, stream: bool = False, stream_cls: type[_AsyncStreamT] | None = None, ) -> ResponseT | _AsyncStreamT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="post", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) @@ -1770,11 +1854,28 @@ async def patch( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="patch", + url=path, + json_data=body, + content=content, + files=await async_to_httpx_files(files), + **options, ) return await self.request(cast_to, opts) @@ -1784,11 +1885,23 @@ async def put( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, files: RequestFiles | None = None, options: RequestOptions = {}, ) -> ResponseT: + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if files is not None and content is not None: + raise TypeError("Passing both `files` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) opts = FinalRequestOptions.construct( - method="put", url=path, json_data=body, files=await async_to_httpx_files(files), **options + method="put", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts) @@ -1798,9 +1911,19 @@ async def delete( *, cast_to: Type[ResponseT], body: Body | None = None, + content: AsyncBinaryTypes | None = None, options: RequestOptions = {}, ) -> ResponseT: - opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options) + if body is not None and content is not None: + raise TypeError("Passing both `body` and `content` is not supported") + if isinstance(body, bytes): + warnings.warn( + "Passing raw bytes as `body` is deprecated and will be removed in a future version. " + "Please pass raw bytes via the `content` parameter instead.", + DeprecationWarning, + stacklevel=2, + ) + opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options) return await self.request(cast_to, opts) def get_api_list( diff --git a/src/gitpod/_models.py b/src/gitpod/_models.py index ca9500b..29070e0 100644 --- a/src/gitpod/_models.py +++ b/src/gitpod/_models.py @@ -3,7 +3,20 @@ import os import inspect import weakref -from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast +from typing import ( + IO, + TYPE_CHECKING, + Any, + Type, + Union, + Generic, + TypeVar, + Callable, + Iterable, + Optional, + AsyncIterable, + cast, +) from datetime import date, datetime from typing_extensions import ( List, @@ -787,6 +800,7 @@ class FinalRequestOptionsInput(TypedDict, total=False): timeout: float | Timeout | None files: HttpxRequestFiles | None idempotency_key: str + content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] json_data: Body extra_json: AnyMapping follow_redirects: bool @@ -805,6 +819,7 @@ class FinalRequestOptions(pydantic.BaseModel): post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() follow_redirects: Union[bool, None] = None + content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None # It should be noted that we cannot use `json` here as that would override # a BaseModel method in an incompatible fashion. json_data: Union[Body, None] = None diff --git a/src/gitpod/_types.py b/src/gitpod/_types.py index ab7cbe2..dbebac0 100644 --- a/src/gitpod/_types.py +++ b/src/gitpod/_types.py @@ -13,9 +13,11 @@ Mapping, TypeVar, Callable, + Iterable, Iterator, Optional, Sequence, + AsyncIterable, ) from typing_extensions import ( Set, @@ -56,6 +58,13 @@ else: Base64FileInput = Union[IO[bytes], PathLike] FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8. + + +# Used for sending raw binary data / streaming data in request bodies +# e.g. for file uploads without multipart encoding +BinaryTypes = Union[bytes, bytearray, IO[bytes], Iterable[bytes]] +AsyncBinaryTypes = Union[bytes, bytearray, IO[bytes], AsyncIterable[bytes]] + FileTypes = Union[ # file (or bytes) FileContent, diff --git a/src/gitpod/_version.py b/src/gitpod/_version.py index 850eb95..88739dd 100644 --- a/src/gitpod/_version.py +++ b/src/gitpod/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "gitpod" -__version__ = "0.6.0" # x-release-please-version +__version__ = "0.7.0" # x-release-please-version diff --git a/src/gitpod/pagination.py b/src/gitpod/pagination.py index c8d007f..0ffd69d 100644 --- a/src/gitpod/pagination.py +++ b/src/gitpod/pagination.py @@ -78,6 +78,9 @@ "RunnersPagePagination", "SyncRunnersPage", "AsyncRunnersPage", + "ScimConfigurationsPagePagination", + "SyncScimConfigurationsPage", + "AsyncScimConfigurationsPage", "SecretsPagePagination", "SyncSecretsPage", "AsyncSecretsPage", @@ -1251,6 +1254,56 @@ def next_page_info(self) -> Optional[PageInfo]: return PageInfo(params={"token": next_token}) +class ScimConfigurationsPagePagination(BaseModel): + next_token: Optional[str] = FieldInfo(alias="nextToken", default=None) + + +class SyncScimConfigurationsPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]): + pagination: Optional[ScimConfigurationsPagePagination] = None + scim_configurations: List[_T] = FieldInfo(alias="scimConfigurations") + + @override + def _get_page_items(self) -> List[_T]: + scim_configurations = self.scim_configurations + if not scim_configurations: + return [] + return scim_configurations + + @override + def next_page_info(self) -> Optional[PageInfo]: + next_token = None + if self.pagination is not None: + if self.pagination.next_token is not None: + next_token = self.pagination.next_token + if not next_token: + return None + + return PageInfo(params={"token": next_token}) + + +class AsyncScimConfigurationsPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): + pagination: Optional[ScimConfigurationsPagePagination] = None + scim_configurations: List[_T] = FieldInfo(alias="scimConfigurations") + + @override + def _get_page_items(self) -> List[_T]: + scim_configurations = self.scim_configurations + if not scim_configurations: + return [] + return scim_configurations + + @override + def next_page_info(self) -> Optional[PageInfo]: + next_token = None + if self.pagination is not None: + if self.pagination.next_token is not None: + next_token = self.pagination.next_token + if not next_token: + return None + + return PageInfo(params={"token": next_token}) + + class SecretsPagePagination(BaseModel): next_token: Optional[str] = FieldInfo(alias="nextToken", default=None) diff --git a/src/gitpod/resources/groups/__init__.py b/src/gitpod/resources/groups/__init__.py index 83c3111..363f4ea 100644 --- a/src/gitpod/resources/groups/__init__.py +++ b/src/gitpod/resources/groups/__init__.py @@ -8,6 +8,14 @@ GroupsResourceWithStreamingResponse, AsyncGroupsResourceWithStreamingResponse, ) +from .shares import ( + SharesResource, + AsyncSharesResource, + SharesResourceWithRawResponse, + AsyncSharesResourceWithRawResponse, + SharesResourceWithStreamingResponse, + AsyncSharesResourceWithStreamingResponse, +) from .memberships import ( MembershipsResource, AsyncMembershipsResource, @@ -38,6 +46,12 @@ "AsyncRoleAssignmentsResourceWithRawResponse", "RoleAssignmentsResourceWithStreamingResponse", "AsyncRoleAssignmentsResourceWithStreamingResponse", + "SharesResource", + "AsyncSharesResource", + "SharesResourceWithRawResponse", + "AsyncSharesResourceWithRawResponse", + "SharesResourceWithStreamingResponse", + "AsyncSharesResourceWithStreamingResponse", "GroupsResource", "AsyncGroupsResource", "GroupsResourceWithRawResponse", diff --git a/src/gitpod/resources/groups/groups.py b/src/gitpod/resources/groups/groups.py index 4a57994..bebd369 100644 --- a/src/gitpod/resources/groups/groups.py +++ b/src/gitpod/resources/groups/groups.py @@ -4,6 +4,14 @@ import httpx +from .shares import ( + SharesResource, + AsyncSharesResource, + SharesResourceWithRawResponse, + AsyncSharesResourceWithRawResponse, + SharesResourceWithStreamingResponse, + AsyncSharesResourceWithStreamingResponse, +) from ...types import ( group_list_params, group_create_params, @@ -56,6 +64,10 @@ def memberships(self) -> MembershipsResource: def role_assignments(self) -> RoleAssignmentsResource: return RoleAssignmentsResource(self._client) + @cached_property + def shares(self) -> SharesResource: + return SharesResource(self._client) + @cached_property def with_raw_response(self) -> GroupsResourceWithRawResponse: """ @@ -396,6 +408,10 @@ def memberships(self) -> AsyncMembershipsResource: def role_assignments(self) -> AsyncRoleAssignmentsResource: return AsyncRoleAssignmentsResource(self._client) + @cached_property + def shares(self) -> AsyncSharesResource: + return AsyncSharesResource(self._client) + @cached_property def with_raw_response(self) -> AsyncGroupsResourceWithRawResponse: """ @@ -755,6 +771,10 @@ def memberships(self) -> MembershipsResourceWithRawResponse: def role_assignments(self) -> RoleAssignmentsResourceWithRawResponse: return RoleAssignmentsResourceWithRawResponse(self._groups.role_assignments) + @cached_property + def shares(self) -> SharesResourceWithRawResponse: + return SharesResourceWithRawResponse(self._groups.shares) + class AsyncGroupsResourceWithRawResponse: def __init__(self, groups: AsyncGroupsResource) -> None: @@ -784,6 +804,10 @@ def memberships(self) -> AsyncMembershipsResourceWithRawResponse: def role_assignments(self) -> AsyncRoleAssignmentsResourceWithRawResponse: return AsyncRoleAssignmentsResourceWithRawResponse(self._groups.role_assignments) + @cached_property + def shares(self) -> AsyncSharesResourceWithRawResponse: + return AsyncSharesResourceWithRawResponse(self._groups.shares) + class GroupsResourceWithStreamingResponse: def __init__(self, groups: GroupsResource) -> None: @@ -813,6 +837,10 @@ def memberships(self) -> MembershipsResourceWithStreamingResponse: def role_assignments(self) -> RoleAssignmentsResourceWithStreamingResponse: return RoleAssignmentsResourceWithStreamingResponse(self._groups.role_assignments) + @cached_property + def shares(self) -> SharesResourceWithStreamingResponse: + return SharesResourceWithStreamingResponse(self._groups.shares) + class AsyncGroupsResourceWithStreamingResponse: def __init__(self, groups: AsyncGroupsResource) -> None: @@ -841,3 +869,7 @@ def memberships(self) -> AsyncMembershipsResourceWithStreamingResponse: @cached_property def role_assignments(self) -> AsyncRoleAssignmentsResourceWithStreamingResponse: return AsyncRoleAssignmentsResourceWithStreamingResponse(self._groups.role_assignments) + + @cached_property + def shares(self) -> AsyncSharesResourceWithStreamingResponse: + return AsyncSharesResourceWithStreamingResponse(self._groups.shares) diff --git a/src/gitpod/resources/groups/role_assignments.py b/src/gitpod/resources/groups/role_assignments.py index 754dad3..0dde1df 100644 --- a/src/gitpod/resources/groups/role_assignments.py +++ b/src/gitpod/resources/groups/role_assignments.py @@ -16,13 +16,8 @@ ) from ...pagination import SyncAssignmentsPage, AsyncAssignmentsPage from ..._base_client import AsyncPaginator, make_request_options -from ...types.groups import ( - ResourceRole, - role_assignment_list_params, - role_assignment_create_params, - role_assignment_delete_params, -) -from ...types.groups.resource_role import ResourceRole +from ...types.groups import role_assignment_list_params, role_assignment_create_params, role_assignment_delete_params +from ...types.shared.resource_role import ResourceRole from ...types.shared.resource_type import ResourceType from ...types.groups.role_assignment import RoleAssignment from ...types.groups.role_assignment_create_response import RoleAssignmentCreateResponse diff --git a/src/gitpod/resources/groups/shares.py b/src/gitpod/resources/groups/shares.py new file mode 100644 index 0000000..fc0c308 --- /dev/null +++ b/src/gitpod/resources/groups/shares.py @@ -0,0 +1,441 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.groups import share_create_params, share_delete_params +from ...types.shared.principal import Principal +from ...types.shared.resource_role import ResourceRole +from ...types.shared.resource_type import ResourceType + +__all__ = ["SharesResource", "AsyncSharesResource"] + + +class SharesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> SharesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#accessing-raw-response-data-eg-headers + """ + return SharesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> SharesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#with_streaming_response + """ + return SharesResourceWithStreamingResponse(self) + + def create( + self, + *, + principal: Principal | Omit = omit, + principal_id: str | Omit = omit, + resource_id: str | Omit = omit, + resource_type: ResourceType | Omit = omit, + role: ResourceRole | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """ + Shares a resource directly with a principal (user or service account). + + Use this method to: + + - Grant a user or service account direct access to a runner, project, or other + resource + - Share resources without creating and managing groups manually + + ### Examples + + - Share a runner with a user: + + Grants admin access to a runner for a specific user. + + ```yaml + resourceType: RESOURCE_TYPE_RUNNER + resourceId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + principal: PRINCIPAL_USER + principalId: "f53d2330-3795-4c5d-a1f3-453121af9c60" + role: RESOURCE_ROLE_RUNNER_ADMIN + ``` + + - Share a runner with a service account: + + Grants user access to a runner for a service account. + + ```yaml + resourceType: RESOURCE_TYPE_RUNNER + resourceId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + principal: PRINCIPAL_SERVICE_ACCOUNT + principalId: "a1b2c3d4-5678-90ab-cdef-1234567890ab" + role: RESOURCE_ROLE_RUNNER_USER + ``` + + ### Authorization + + Requires admin role on the specific resource. + + Args: + principal: Type of principal to share with (user or service account) + + principal_id: ID of the principal (user or service account) to share with + + resource_id: ID of the resource to share + + resource_type: Type of resource to share (runner, project, etc.) + + role: Role to grant the principal on the resource + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.GroupService/ShareResourceWithPrincipal", + body=maybe_transform( + { + "principal": principal, + "principal_id": principal_id, + "resource_id": resource_id, + "resource_type": resource_type, + "role": role, + }, + share_create_params.ShareCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def delete( + self, + *, + principal: Principal | Omit = omit, + principal_id: str | Omit = omit, + resource_id: str | Omit = omit, + resource_type: ResourceType | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """ + Removes direct access for a principal (user or service account) from a resource. + + Use this method to: + + - Revoke a principal's direct access to a resource + - Remove sharing without affecting group-based access + + ### Examples + + - Remove user access from a runner: + + Revokes a user's direct access to a runner. + + ```yaml + resourceType: RESOURCE_TYPE_RUNNER + resourceId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + principal: PRINCIPAL_USER + principalId: "f53d2330-3795-4c5d-a1f3-453121af9c60" + ``` + + ### Authorization + + Requires admin role on the specific resource. + + Args: + principal: Type of principal to remove access from (user or service account) + + principal_id: ID of the principal (user or service account) to remove access from + + resource_id: ID of the resource to unshare + + resource_type: Type of resource to unshare + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.GroupService/UnshareResourceWithPrincipal", + body=maybe_transform( + { + "principal": principal, + "principal_id": principal_id, + "resource_id": resource_id, + "resource_type": resource_type, + }, + share_delete_params.ShareDeleteParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class AsyncSharesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncSharesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncSharesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncSharesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#with_streaming_response + """ + return AsyncSharesResourceWithStreamingResponse(self) + + async def create( + self, + *, + principal: Principal | Omit = omit, + principal_id: str | Omit = omit, + resource_id: str | Omit = omit, + resource_type: ResourceType | Omit = omit, + role: ResourceRole | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """ + Shares a resource directly with a principal (user or service account). + + Use this method to: + + - Grant a user or service account direct access to a runner, project, or other + resource + - Share resources without creating and managing groups manually + + ### Examples + + - Share a runner with a user: + + Grants admin access to a runner for a specific user. + + ```yaml + resourceType: RESOURCE_TYPE_RUNNER + resourceId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + principal: PRINCIPAL_USER + principalId: "f53d2330-3795-4c5d-a1f3-453121af9c60" + role: RESOURCE_ROLE_RUNNER_ADMIN + ``` + + - Share a runner with a service account: + + Grants user access to a runner for a service account. + + ```yaml + resourceType: RESOURCE_TYPE_RUNNER + resourceId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + principal: PRINCIPAL_SERVICE_ACCOUNT + principalId: "a1b2c3d4-5678-90ab-cdef-1234567890ab" + role: RESOURCE_ROLE_RUNNER_USER + ``` + + ### Authorization + + Requires admin role on the specific resource. + + Args: + principal: Type of principal to share with (user or service account) + + principal_id: ID of the principal (user or service account) to share with + + resource_id: ID of the resource to share + + resource_type: Type of resource to share (runner, project, etc.) + + role: Role to grant the principal on the resource + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.GroupService/ShareResourceWithPrincipal", + body=await async_maybe_transform( + { + "principal": principal, + "principal_id": principal_id, + "resource_id": resource_id, + "resource_type": resource_type, + "role": role, + }, + share_create_params.ShareCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def delete( + self, + *, + principal: Principal | Omit = omit, + principal_id: str | Omit = omit, + resource_id: str | Omit = omit, + resource_type: ResourceType | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """ + Removes direct access for a principal (user or service account) from a resource. + + Use this method to: + + - Revoke a principal's direct access to a resource + - Remove sharing without affecting group-based access + + ### Examples + + - Remove user access from a runner: + + Revokes a user's direct access to a runner. + + ```yaml + resourceType: RESOURCE_TYPE_RUNNER + resourceId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + principal: PRINCIPAL_USER + principalId: "f53d2330-3795-4c5d-a1f3-453121af9c60" + ``` + + ### Authorization + + Requires admin role on the specific resource. + + Args: + principal: Type of principal to remove access from (user or service account) + + principal_id: ID of the principal (user or service account) to remove access from + + resource_id: ID of the resource to unshare + + resource_type: Type of resource to unshare + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.GroupService/UnshareResourceWithPrincipal", + body=await async_maybe_transform( + { + "principal": principal, + "principal_id": principal_id, + "resource_id": resource_id, + "resource_type": resource_type, + }, + share_delete_params.ShareDeleteParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + +class SharesResourceWithRawResponse: + def __init__(self, shares: SharesResource) -> None: + self._shares = shares + + self.create = to_raw_response_wrapper( + shares.create, + ) + self.delete = to_raw_response_wrapper( + shares.delete, + ) + + +class AsyncSharesResourceWithRawResponse: + def __init__(self, shares: AsyncSharesResource) -> None: + self._shares = shares + + self.create = async_to_raw_response_wrapper( + shares.create, + ) + self.delete = async_to_raw_response_wrapper( + shares.delete, + ) + + +class SharesResourceWithStreamingResponse: + def __init__(self, shares: SharesResource) -> None: + self._shares = shares + + self.create = to_streamed_response_wrapper( + shares.create, + ) + self.delete = to_streamed_response_wrapper( + shares.delete, + ) + + +class AsyncSharesResourceWithStreamingResponse: + def __init__(self, shares: AsyncSharesResource) -> None: + self._shares = shares + + self.create = async_to_streamed_response_wrapper( + shares.create, + ) + self.delete = async_to_streamed_response_wrapper( + shares.delete, + ) diff --git a/src/gitpod/resources/organizations/__init__.py b/src/gitpod/resources/organizations/__init__.py index 84d6bde..21debec 100644 --- a/src/gitpod/resources/organizations/__init__.py +++ b/src/gitpod/resources/organizations/__init__.py @@ -40,6 +40,14 @@ SSOConfigurationsResourceWithStreamingResponse, AsyncSSOConfigurationsResourceWithStreamingResponse, ) +from .scim_configurations import ( + ScimConfigurationsResource, + AsyncScimConfigurationsResource, + ScimConfigurationsResourceWithRawResponse, + AsyncScimConfigurationsResourceWithRawResponse, + ScimConfigurationsResourceWithStreamingResponse, + AsyncScimConfigurationsResourceWithStreamingResponse, +) from .domain_verifications import ( DomainVerificationsResource, AsyncDomainVerificationsResource, @@ -74,6 +82,12 @@ "AsyncPoliciesResourceWithRawResponse", "PoliciesResourceWithStreamingResponse", "AsyncPoliciesResourceWithStreamingResponse", + "ScimConfigurationsResource", + "AsyncScimConfigurationsResource", + "ScimConfigurationsResourceWithRawResponse", + "AsyncScimConfigurationsResourceWithRawResponse", + "ScimConfigurationsResourceWithStreamingResponse", + "AsyncScimConfigurationsResourceWithStreamingResponse", "SSOConfigurationsResource", "AsyncSSOConfigurationsResource", "SSOConfigurationsResourceWithRawResponse", diff --git a/src/gitpod/resources/organizations/organizations.py b/src/gitpod/resources/organizations/organizations.py index c1ec57e..c45b8a5 100644 --- a/src/gitpod/resources/organizations/organizations.py +++ b/src/gitpod/resources/organizations/organizations.py @@ -60,6 +60,14 @@ SSOConfigurationsResourceWithStreamingResponse, AsyncSSOConfigurationsResourceWithStreamingResponse, ) +from .scim_configurations import ( + ScimConfigurationsResource, + AsyncScimConfigurationsResource, + ScimConfigurationsResourceWithRawResponse, + AsyncScimConfigurationsResourceWithRawResponse, + ScimConfigurationsResourceWithStreamingResponse, + AsyncScimConfigurationsResourceWithStreamingResponse, +) from .domain_verifications import ( DomainVerificationsResource, AsyncDomainVerificationsResource, @@ -96,6 +104,10 @@ def invites(self) -> InvitesResource: def policies(self) -> PoliciesResource: return PoliciesResource(self._client) + @cached_property + def scim_configurations(self) -> ScimConfigurationsResource: + return ScimConfigurationsResource(self._client) + @cached_property def sso_configurations(self) -> SSOConfigurationsResource: return SSOConfigurationsResource(self._client) @@ -507,6 +519,7 @@ def list_members( page_size: int | Omit = omit, filter: organization_list_members_params.Filter | Omit = omit, pagination: organization_list_members_params.Pagination | Omit = omit, + sort: organization_list_members_params.Sort | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -551,6 +564,11 @@ def list_members( pagination: pagination contains the pagination options for listing members + sort: sort specifies the order of results. When unspecified, the authenticated user is + returned first, followed by other members sorted by name ascending. When an + explicit sort is specified, results are sorted purely by the requested field + without any special handling for the authenticated user. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -567,6 +585,7 @@ def list_members( "organization_id": organization_id, "filter": filter, "pagination": pagination, + "sort": sort, }, organization_list_members_params.OrganizationListMembersParams, ), @@ -675,6 +694,10 @@ def invites(self) -> AsyncInvitesResource: def policies(self) -> AsyncPoliciesResource: return AsyncPoliciesResource(self._client) + @cached_property + def scim_configurations(self) -> AsyncScimConfigurationsResource: + return AsyncScimConfigurationsResource(self._client) + @cached_property def sso_configurations(self) -> AsyncSSOConfigurationsResource: return AsyncSSOConfigurationsResource(self._client) @@ -1086,6 +1109,7 @@ def list_members( page_size: int | Omit = omit, filter: organization_list_members_params.Filter | Omit = omit, pagination: organization_list_members_params.Pagination | Omit = omit, + sort: organization_list_members_params.Sort | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1130,6 +1154,11 @@ def list_members( pagination: pagination contains the pagination options for listing members + sort: sort specifies the order of results. When unspecified, the authenticated user is + returned first, followed by other members sorted by name ascending. When an + explicit sort is specified, results are sorted purely by the requested field + without any special handling for the authenticated user. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1146,6 +1175,7 @@ def list_members( "organization_id": organization_id, "filter": filter, "pagination": pagination, + "sort": sort, }, organization_list_members_params.OrganizationListMembersParams, ), @@ -1282,6 +1312,10 @@ def invites(self) -> InvitesResourceWithRawResponse: def policies(self) -> PoliciesResourceWithRawResponse: return PoliciesResourceWithRawResponse(self._organizations.policies) + @cached_property + def scim_configurations(self) -> ScimConfigurationsResourceWithRawResponse: + return ScimConfigurationsResourceWithRawResponse(self._organizations.scim_configurations) + @cached_property def sso_configurations(self) -> SSOConfigurationsResourceWithRawResponse: return SSOConfigurationsResourceWithRawResponse(self._organizations.sso_configurations) @@ -1332,6 +1366,10 @@ def invites(self) -> AsyncInvitesResourceWithRawResponse: def policies(self) -> AsyncPoliciesResourceWithRawResponse: return AsyncPoliciesResourceWithRawResponse(self._organizations.policies) + @cached_property + def scim_configurations(self) -> AsyncScimConfigurationsResourceWithRawResponse: + return AsyncScimConfigurationsResourceWithRawResponse(self._organizations.scim_configurations) + @cached_property def sso_configurations(self) -> AsyncSSOConfigurationsResourceWithRawResponse: return AsyncSSOConfigurationsResourceWithRawResponse(self._organizations.sso_configurations) @@ -1382,6 +1420,10 @@ def invites(self) -> InvitesResourceWithStreamingResponse: def policies(self) -> PoliciesResourceWithStreamingResponse: return PoliciesResourceWithStreamingResponse(self._organizations.policies) + @cached_property + def scim_configurations(self) -> ScimConfigurationsResourceWithStreamingResponse: + return ScimConfigurationsResourceWithStreamingResponse(self._organizations.scim_configurations) + @cached_property def sso_configurations(self) -> SSOConfigurationsResourceWithStreamingResponse: return SSOConfigurationsResourceWithStreamingResponse(self._organizations.sso_configurations) @@ -1432,6 +1474,10 @@ def invites(self) -> AsyncInvitesResourceWithStreamingResponse: def policies(self) -> AsyncPoliciesResourceWithStreamingResponse: return AsyncPoliciesResourceWithStreamingResponse(self._organizations.policies) + @cached_property + def scim_configurations(self) -> AsyncScimConfigurationsResourceWithStreamingResponse: + return AsyncScimConfigurationsResourceWithStreamingResponse(self._organizations.scim_configurations) + @cached_property def sso_configurations(self) -> AsyncSSOConfigurationsResourceWithStreamingResponse: return AsyncSSOConfigurationsResourceWithStreamingResponse(self._organizations.sso_configurations) diff --git a/src/gitpod/resources/organizations/scim_configurations.py b/src/gitpod/resources/organizations/scim_configurations.py new file mode 100644 index 0000000..529ae16 --- /dev/null +++ b/src/gitpod/resources/organizations/scim_configurations.py @@ -0,0 +1,909 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...pagination import SyncScimConfigurationsPage, AsyncScimConfigurationsPage +from ..._base_client import AsyncPaginator, make_request_options +from ...types.organizations import ( + scim_configuration_list_params, + scim_configuration_create_params, + scim_configuration_delete_params, + scim_configuration_update_params, + scim_configuration_retrieve_params, + scim_configuration_regenerate_token_params, +) +from ...types.organizations.scim_configuration import ScimConfiguration +from ...types.organizations.scim_configuration_create_response import ScimConfigurationCreateResponse +from ...types.organizations.scim_configuration_update_response import ScimConfigurationUpdateResponse +from ...types.organizations.scim_configuration_retrieve_response import ScimConfigurationRetrieveResponse +from ...types.organizations.scim_configuration_regenerate_token_response import ScimConfigurationRegenerateTokenResponse + +__all__ = ["ScimConfigurationsResource", "AsyncScimConfigurationsResource"] + + +class ScimConfigurationsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ScimConfigurationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#accessing-raw-response-data-eg-headers + """ + return ScimConfigurationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ScimConfigurationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#with_streaming_response + """ + return ScimConfigurationsResourceWithStreamingResponse(self) + + def create( + self, + *, + organization_id: str, + sso_configuration_id: str, + name: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationCreateResponse: + """ + Creates a new SCIM configuration for automated user provisioning. + + Use this method to: + + - Set up SCIM 2.0 provisioning from an identity provider + - Generate a bearer token for SCIM API authentication + - Link SCIM provisioning to an existing SSO configuration + + ### Examples + + - Create basic SCIM configuration: + + Creates a SCIM configuration linked to an SSO provider. + + ```yaml + organizationId: "b0e12f6c-4c67-429d-a4a6-d9838b5da047" + ssoConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + organization_id: organization_id is the ID of the organization to create the SCIM configuration + for + + sso_configuration_id: sso_configuration_id is the SSO configuration to link (required for user + provisioning) + + name: name is a human-readable name for the SCIM configuration + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.OrganizationService/CreateSCIMConfiguration", + body=maybe_transform( + { + "organization_id": organization_id, + "sso_configuration_id": sso_configuration_id, + "name": name, + }, + scim_configuration_create_params.ScimConfigurationCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationCreateResponse, + ) + + def retrieve( + self, + *, + scim_configuration_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationRetrieveResponse: + """ + Retrieves a specific SCIM configuration. + + Use this method to: + + - View SCIM configuration details + - Check if SCIM is enabled + - Verify SSO linkage + + ### Examples + + - Get SCIM configuration: + + Retrieves details of a specific SCIM configuration. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to get + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.OrganizationService/GetSCIMConfiguration", + body=maybe_transform( + {"scim_configuration_id": scim_configuration_id}, + scim_configuration_retrieve_params.ScimConfigurationRetrieveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationRetrieveResponse, + ) + + def update( + self, + *, + scim_configuration_id: str, + enabled: Optional[bool] | Omit = omit, + name: Optional[str] | Omit = omit, + sso_configuration_id: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationUpdateResponse: + """ + Updates a SCIM configuration. + + Use this method to: + + - Enable or disable SCIM provisioning + - Link or unlink SSO configuration + - Update configuration name + + ### Examples + + - Disable SCIM: + + Disables SCIM provisioning. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + enabled: false + ``` + + - Link to SSO: + + Links SCIM configuration to an SSO provider. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ssoConfigurationId: "f53d2330-3795-4c5d-a1f3-453121af9c60" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to update + + enabled: enabled controls whether SCIM provisioning is active + + name: name is a human-readable name for the SCIM configuration + + sso_configuration_id: sso_configuration_id is the SSO configuration to link + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.OrganizationService/UpdateSCIMConfiguration", + body=maybe_transform( + { + "scim_configuration_id": scim_configuration_id, + "enabled": enabled, + "name": name, + "sso_configuration_id": sso_configuration_id, + }, + scim_configuration_update_params.ScimConfigurationUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationUpdateResponse, + ) + + def list( + self, + *, + token: str | Omit = omit, + page_size: int | Omit = omit, + pagination: scim_configuration_list_params.Pagination | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncScimConfigurationsPage[ScimConfiguration]: + """ + Lists SCIM configurations for an organization. + + Use this method to: + + - View all SCIM configurations + - Monitor provisioning status + - Audit SCIM settings + + ### Examples + + - List SCIM configurations: + + Shows all SCIM configurations for an organization. + + ```yaml + pagination: + pageSize: 20 + ``` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/gitpod.v1.OrganizationService/ListSCIMConfigurations", + page=SyncScimConfigurationsPage[ScimConfiguration], + body=maybe_transform( + {"pagination": pagination}, scim_configuration_list_params.ScimConfigurationListParams + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "token": token, + "page_size": page_size, + }, + scim_configuration_list_params.ScimConfigurationListParams, + ), + ), + model=ScimConfiguration, + method="post", + ) + + def delete( + self, + *, + scim_configuration_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """ + Removes a SCIM configuration from an organization. + + Use this method to: + + - Disable SCIM provisioning completely + - Remove unused configurations + - Clean up after migration + + ### Examples + + - Delete SCIM configuration: + + Removes a specific SCIM configuration. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to delete + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.OrganizationService/DeleteSCIMConfiguration", + body=maybe_transform( + {"scim_configuration_id": scim_configuration_id}, + scim_configuration_delete_params.ScimConfigurationDeleteParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + def regenerate_token( + self, + *, + scim_configuration_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationRegenerateTokenResponse: + """ + Regenerates the bearer token for a SCIM configuration. + + Use this method to: + + - Rotate SCIM credentials + - Recover from token compromise + - Update IdP configuration + + ### Examples + + - Regenerate token: + + Creates a new bearer token, invalidating the old one. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to regenerate token + for + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.OrganizationService/RegenerateSCIMToken", + body=maybe_transform( + {"scim_configuration_id": scim_configuration_id}, + scim_configuration_regenerate_token_params.ScimConfigurationRegenerateTokenParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationRegenerateTokenResponse, + ) + + +class AsyncScimConfigurationsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncScimConfigurationsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncScimConfigurationsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncScimConfigurationsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/gitpod-io/gitpod-sdk-python#with_streaming_response + """ + return AsyncScimConfigurationsResourceWithStreamingResponse(self) + + async def create( + self, + *, + organization_id: str, + sso_configuration_id: str, + name: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationCreateResponse: + """ + Creates a new SCIM configuration for automated user provisioning. + + Use this method to: + + - Set up SCIM 2.0 provisioning from an identity provider + - Generate a bearer token for SCIM API authentication + - Link SCIM provisioning to an existing SSO configuration + + ### Examples + + - Create basic SCIM configuration: + + Creates a SCIM configuration linked to an SSO provider. + + ```yaml + organizationId: "b0e12f6c-4c67-429d-a4a6-d9838b5da047" + ssoConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + organization_id: organization_id is the ID of the organization to create the SCIM configuration + for + + sso_configuration_id: sso_configuration_id is the SSO configuration to link (required for user + provisioning) + + name: name is a human-readable name for the SCIM configuration + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.OrganizationService/CreateSCIMConfiguration", + body=await async_maybe_transform( + { + "organization_id": organization_id, + "sso_configuration_id": sso_configuration_id, + "name": name, + }, + scim_configuration_create_params.ScimConfigurationCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationCreateResponse, + ) + + async def retrieve( + self, + *, + scim_configuration_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationRetrieveResponse: + """ + Retrieves a specific SCIM configuration. + + Use this method to: + + - View SCIM configuration details + - Check if SCIM is enabled + - Verify SSO linkage + + ### Examples + + - Get SCIM configuration: + + Retrieves details of a specific SCIM configuration. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to get + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.OrganizationService/GetSCIMConfiguration", + body=await async_maybe_transform( + {"scim_configuration_id": scim_configuration_id}, + scim_configuration_retrieve_params.ScimConfigurationRetrieveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationRetrieveResponse, + ) + + async def update( + self, + *, + scim_configuration_id: str, + enabled: Optional[bool] | Omit = omit, + name: Optional[str] | Omit = omit, + sso_configuration_id: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationUpdateResponse: + """ + Updates a SCIM configuration. + + Use this method to: + + - Enable or disable SCIM provisioning + - Link or unlink SSO configuration + - Update configuration name + + ### Examples + + - Disable SCIM: + + Disables SCIM provisioning. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + enabled: false + ``` + + - Link to SSO: + + Links SCIM configuration to an SSO provider. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ssoConfigurationId: "f53d2330-3795-4c5d-a1f3-453121af9c60" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to update + + enabled: enabled controls whether SCIM provisioning is active + + name: name is a human-readable name for the SCIM configuration + + sso_configuration_id: sso_configuration_id is the SSO configuration to link + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.OrganizationService/UpdateSCIMConfiguration", + body=await async_maybe_transform( + { + "scim_configuration_id": scim_configuration_id, + "enabled": enabled, + "name": name, + "sso_configuration_id": sso_configuration_id, + }, + scim_configuration_update_params.ScimConfigurationUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationUpdateResponse, + ) + + def list( + self, + *, + token: str | Omit = omit, + page_size: int | Omit = omit, + pagination: scim_configuration_list_params.Pagination | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[ScimConfiguration, AsyncScimConfigurationsPage[ScimConfiguration]]: + """ + Lists SCIM configurations for an organization. + + Use this method to: + + - View all SCIM configurations + - Monitor provisioning status + - Audit SCIM settings + + ### Examples + + - List SCIM configurations: + + Shows all SCIM configurations for an organization. + + ```yaml + pagination: + pageSize: 20 + ``` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/gitpod.v1.OrganizationService/ListSCIMConfigurations", + page=AsyncScimConfigurationsPage[ScimConfiguration], + body=maybe_transform( + {"pagination": pagination}, scim_configuration_list_params.ScimConfigurationListParams + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "token": token, + "page_size": page_size, + }, + scim_configuration_list_params.ScimConfigurationListParams, + ), + ), + model=ScimConfiguration, + method="post", + ) + + async def delete( + self, + *, + scim_configuration_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> object: + """ + Removes a SCIM configuration from an organization. + + Use this method to: + + - Disable SCIM provisioning completely + - Remove unused configurations + - Clean up after migration + + ### Examples + + - Delete SCIM configuration: + + Removes a specific SCIM configuration. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to delete + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.OrganizationService/DeleteSCIMConfiguration", + body=await async_maybe_transform( + {"scim_configuration_id": scim_configuration_id}, + scim_configuration_delete_params.ScimConfigurationDeleteParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=object, + ) + + async def regenerate_token( + self, + *, + scim_configuration_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScimConfigurationRegenerateTokenResponse: + """ + Regenerates the bearer token for a SCIM configuration. + + Use this method to: + + - Rotate SCIM credentials + - Recover from token compromise + - Update IdP configuration + + ### Examples + + - Regenerate token: + + Creates a new bearer token, invalidating the old one. + + ```yaml + scimConfigurationId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + ``` + + Args: + scim_configuration_id: scim_configuration_id is the ID of the SCIM configuration to regenerate token + for + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.OrganizationService/RegenerateSCIMToken", + body=await async_maybe_transform( + {"scim_configuration_id": scim_configuration_id}, + scim_configuration_regenerate_token_params.ScimConfigurationRegenerateTokenParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScimConfigurationRegenerateTokenResponse, + ) + + +class ScimConfigurationsResourceWithRawResponse: + def __init__(self, scim_configurations: ScimConfigurationsResource) -> None: + self._scim_configurations = scim_configurations + + self.create = to_raw_response_wrapper( + scim_configurations.create, + ) + self.retrieve = to_raw_response_wrapper( + scim_configurations.retrieve, + ) + self.update = to_raw_response_wrapper( + scim_configurations.update, + ) + self.list = to_raw_response_wrapper( + scim_configurations.list, + ) + self.delete = to_raw_response_wrapper( + scim_configurations.delete, + ) + self.regenerate_token = to_raw_response_wrapper( + scim_configurations.regenerate_token, + ) + + +class AsyncScimConfigurationsResourceWithRawResponse: + def __init__(self, scim_configurations: AsyncScimConfigurationsResource) -> None: + self._scim_configurations = scim_configurations + + self.create = async_to_raw_response_wrapper( + scim_configurations.create, + ) + self.retrieve = async_to_raw_response_wrapper( + scim_configurations.retrieve, + ) + self.update = async_to_raw_response_wrapper( + scim_configurations.update, + ) + self.list = async_to_raw_response_wrapper( + scim_configurations.list, + ) + self.delete = async_to_raw_response_wrapper( + scim_configurations.delete, + ) + self.regenerate_token = async_to_raw_response_wrapper( + scim_configurations.regenerate_token, + ) + + +class ScimConfigurationsResourceWithStreamingResponse: + def __init__(self, scim_configurations: ScimConfigurationsResource) -> None: + self._scim_configurations = scim_configurations + + self.create = to_streamed_response_wrapper( + scim_configurations.create, + ) + self.retrieve = to_streamed_response_wrapper( + scim_configurations.retrieve, + ) + self.update = to_streamed_response_wrapper( + scim_configurations.update, + ) + self.list = to_streamed_response_wrapper( + scim_configurations.list, + ) + self.delete = to_streamed_response_wrapper( + scim_configurations.delete, + ) + self.regenerate_token = to_streamed_response_wrapper( + scim_configurations.regenerate_token, + ) + + +class AsyncScimConfigurationsResourceWithStreamingResponse: + def __init__(self, scim_configurations: AsyncScimConfigurationsResource) -> None: + self._scim_configurations = scim_configurations + + self.create = async_to_streamed_response_wrapper( + scim_configurations.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + scim_configurations.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + scim_configurations.update, + ) + self.list = async_to_streamed_response_wrapper( + scim_configurations.list, + ) + self.delete = async_to_streamed_response_wrapper( + scim_configurations.delete, + ) + self.regenerate_token = async_to_streamed_response_wrapper( + scim_configurations.regenerate_token, + ) diff --git a/src/gitpod/resources/runners/runners.py b/src/gitpod/resources/runners/runners.py index 1c445f8..5a0ee2e 100644 --- a/src/gitpod/resources/runners/runners.py +++ b/src/gitpod/resources/runners/runners.py @@ -19,6 +19,8 @@ runner_parse_context_url_params, runner_create_runner_token_params, runner_search_repositories_params, + runner_list_scm_organizations_params, + runner_check_repository_access_params, runner_check_authentication_for_host_params, ) from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given @@ -60,6 +62,8 @@ from ...types.runner_parse_context_url_response import RunnerParseContextURLResponse from ...types.runner_create_runner_token_response import RunnerCreateRunnerTokenResponse from ...types.runner_search_repositories_response import RunnerSearchRepositoriesResponse +from ...types.runner_list_scm_organizations_response import RunnerListScmOrganizationsResponse +from ...types.runner_check_repository_access_response import RunnerCheckRepositoryAccessResponse from ...types.runner_check_authentication_for_host_response import RunnerCheckAuthenticationForHostResponse __all__ = ["RunnersResource", "AsyncRunnersResource"] @@ -508,6 +512,70 @@ def check_authentication_for_host( cast_to=RunnerCheckAuthenticationForHostResponse, ) + def check_repository_access( + self, + *, + repository_url: str | Omit = omit, + runner_id: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunnerCheckRepositoryAccessResponse: + """ + Checks if a principal has read access to a repository. + + Use this method to: + + - Validate repository access before workflow execution + - Verify executor credentials for automation bindings + + Returns: + + - has_access: true if the principal can read the repository + - FAILED_PRECONDITION if authentication is required + - INVALID_ARGUMENT if the repository URL is invalid + + ### Examples + + - Check access: + + Verifies read access to a repository. + + ```yaml + runnerId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + repositoryUrl: "https://github.com/org/repo" + ``` + + Args: + repository_url: repository_url is the URL of the repository to check access for. Can be a clone + URL (https://github.com/org/repo.git) or web URL (https://github.com/org/repo). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.RunnerService/CheckRepositoryAccess", + body=maybe_transform( + { + "repository_url": repository_url, + "runner_id": runner_id, + }, + runner_check_repository_access_params.RunnerCheckRepositoryAccessParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RunnerCheckRepositoryAccessResponse, + ) + def create_logs_token( self, *, @@ -608,6 +676,75 @@ def create_runner_token( cast_to=RunnerCreateRunnerTokenResponse, ) + def list_scm_organizations( + self, + *, + token: str | Omit = omit, + page_size: int | Omit = omit, + runner_id: str | Omit = omit, + scm_host: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunnerListScmOrganizationsResponse: + """ + Lists SCM organizations the user belongs to. + + Use this method to: + + - Get all organizations for a user on a specific SCM host + - Check organization admin permissions for webhook creation + + ### Examples + + - List GitHub organizations: + + Lists all organizations the user belongs to on GitHub. + + ```yaml + runnerId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + scmHost: "github.com" + ``` + + Args: + scm_host: The SCM host to list organizations from (e.g., "github.com", "gitlab.com") + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/gitpod.v1.RunnerService/ListSCMOrganizations", + body=maybe_transform( + { + "runner_id": runner_id, + "scm_host": scm_host, + }, + runner_list_scm_organizations_params.RunnerListScmOrganizationsParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "token": token, + "page_size": page_size, + }, + runner_list_scm_organizations_params.RunnerListScmOrganizationsParams, + ), + ), + cast_to=RunnerListScmOrganizationsResponse, + ) + def parse_context_url( self, *, @@ -1202,6 +1339,70 @@ async def check_authentication_for_host( cast_to=RunnerCheckAuthenticationForHostResponse, ) + async def check_repository_access( + self, + *, + repository_url: str | Omit = omit, + runner_id: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunnerCheckRepositoryAccessResponse: + """ + Checks if a principal has read access to a repository. + + Use this method to: + + - Validate repository access before workflow execution + - Verify executor credentials for automation bindings + + Returns: + + - has_access: true if the principal can read the repository + - FAILED_PRECONDITION if authentication is required + - INVALID_ARGUMENT if the repository URL is invalid + + ### Examples + + - Check access: + + Verifies read access to a repository. + + ```yaml + runnerId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + repositoryUrl: "https://github.com/org/repo" + ``` + + Args: + repository_url: repository_url is the URL of the repository to check access for. Can be a clone + URL (https://github.com/org/repo.git) or web URL (https://github.com/org/repo). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.RunnerService/CheckRepositoryAccess", + body=await async_maybe_transform( + { + "repository_url": repository_url, + "runner_id": runner_id, + }, + runner_check_repository_access_params.RunnerCheckRepositoryAccessParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RunnerCheckRepositoryAccessResponse, + ) + async def create_logs_token( self, *, @@ -1304,6 +1505,75 @@ async def create_runner_token( cast_to=RunnerCreateRunnerTokenResponse, ) + async def list_scm_organizations( + self, + *, + token: str | Omit = omit, + page_size: int | Omit = omit, + runner_id: str | Omit = omit, + scm_host: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> RunnerListScmOrganizationsResponse: + """ + Lists SCM organizations the user belongs to. + + Use this method to: + + - Get all organizations for a user on a specific SCM host + - Check organization admin permissions for webhook creation + + ### Examples + + - List GitHub organizations: + + Lists all organizations the user belongs to on GitHub. + + ```yaml + runnerId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + scmHost: "github.com" + ``` + + Args: + scm_host: The SCM host to list organizations from (e.g., "github.com", "gitlab.com") + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/gitpod.v1.RunnerService/ListSCMOrganizations", + body=await async_maybe_transform( + { + "runner_id": runner_id, + "scm_host": scm_host, + }, + runner_list_scm_organizations_params.RunnerListScmOrganizationsParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "token": token, + "page_size": page_size, + }, + runner_list_scm_organizations_params.RunnerListScmOrganizationsParams, + ), + ), + cast_to=RunnerListScmOrganizationsResponse, + ) + async def parse_context_url( self, *, @@ -1477,12 +1747,18 @@ def __init__(self, runners: RunnersResource) -> None: self.check_authentication_for_host = to_raw_response_wrapper( runners.check_authentication_for_host, ) + self.check_repository_access = to_raw_response_wrapper( + runners.check_repository_access, + ) self.create_logs_token = to_raw_response_wrapper( runners.create_logs_token, ) self.create_runner_token = to_raw_response_wrapper( runners.create_runner_token, ) + self.list_scm_organizations = to_raw_response_wrapper( + runners.list_scm_organizations, + ) self.parse_context_url = to_raw_response_wrapper( runners.parse_context_url, ) @@ -1521,12 +1797,18 @@ def __init__(self, runners: AsyncRunnersResource) -> None: self.check_authentication_for_host = async_to_raw_response_wrapper( runners.check_authentication_for_host, ) + self.check_repository_access = async_to_raw_response_wrapper( + runners.check_repository_access, + ) self.create_logs_token = async_to_raw_response_wrapper( runners.create_logs_token, ) self.create_runner_token = async_to_raw_response_wrapper( runners.create_runner_token, ) + self.list_scm_organizations = async_to_raw_response_wrapper( + runners.list_scm_organizations, + ) self.parse_context_url = async_to_raw_response_wrapper( runners.parse_context_url, ) @@ -1565,12 +1847,18 @@ def __init__(self, runners: RunnersResource) -> None: self.check_authentication_for_host = to_streamed_response_wrapper( runners.check_authentication_for_host, ) + self.check_repository_access = to_streamed_response_wrapper( + runners.check_repository_access, + ) self.create_logs_token = to_streamed_response_wrapper( runners.create_logs_token, ) self.create_runner_token = to_streamed_response_wrapper( runners.create_runner_token, ) + self.list_scm_organizations = to_streamed_response_wrapper( + runners.list_scm_organizations, + ) self.parse_context_url = to_streamed_response_wrapper( runners.parse_context_url, ) @@ -1609,12 +1897,18 @@ def __init__(self, runners: AsyncRunnersResource) -> None: self.check_authentication_for_host = async_to_streamed_response_wrapper( runners.check_authentication_for_host, ) + self.check_repository_access = async_to_streamed_response_wrapper( + runners.check_repository_access, + ) self.create_logs_token = async_to_streamed_response_wrapper( runners.create_logs_token, ) self.create_runner_token = async_to_streamed_response_wrapper( runners.create_runner_token, ) + self.list_scm_organizations = async_to_streamed_response_wrapper( + runners.list_scm_organizations, + ) self.parse_context_url = async_to_streamed_response_wrapper( runners.parse_context_url, ) diff --git a/src/gitpod/types/__init__.py b/src/gitpod/types/__init__.py index bd85a24..4b195c7 100644 --- a/src/gitpod/types/__init__.py +++ b/src/gitpod/types/__init__.py @@ -10,6 +10,7 @@ from .secret import Secret as Secret from .shared import ( Task as Task, + State as State, RunsOn as RunsOn, Gateway as Gateway, Subject as Subject, @@ -19,11 +20,13 @@ SecretRef as SecretRef, FieldValue as FieldValue, UserStatus as UserStatus, + ResourceRole as ResourceRole, ResourceType as ResourceType, TaskMetadata as TaskMetadata, TaskExecution as TaskExecution, EnvironmentClass as EnvironmentClass, OrganizationRole as OrganizationRole, + OrganizationTier as OrganizationTier, AutomationTrigger as AutomationTrigger, TaskExecutionSpec as TaskExecutionSpec, TaskExecutionPhase as TaskExecutionPhase, @@ -71,7 +74,6 @@ from .error_event_param import ErrorEventParam as ErrorEventParam from .event_list_params import EventListParams as EventListParams from .group_list_params import GroupListParams as GroupListParams -from .organization_tier import OrganizationTier as OrganizationTier from .prebuild_metadata import PrebuildMetadata as PrebuildMetadata from .runner_capability import RunnerCapability as RunnerCapability from .runner_spec_param import RunnerSpecParam as RunnerSpecParam @@ -220,7 +222,11 @@ from .runner_search_repositories_response import RunnerSearchRepositoriesResponse as RunnerSearchRepositoriesResponse from .environment_create_logs_token_params import EnvironmentCreateLogsTokenParams as EnvironmentCreateLogsTokenParams from .project_prebuild_configuration_param import ProjectPrebuildConfigurationParam as ProjectPrebuildConfigurationParam +from .runner_list_scm_organizations_params import RunnerListScmOrganizationsParams as RunnerListScmOrganizationsParams from .user_get_authenticated_user_response import UserGetAuthenticatedUserResponse as UserGetAuthenticatedUserResponse +from .runner_check_repository_access_params import ( + RunnerCheckRepositoryAccessParams as RunnerCheckRepositoryAccessParams, +) from .environment_create_from_project_params import ( EnvironmentCreateFromProjectParams as EnvironmentCreateFromProjectParams, ) @@ -230,6 +236,12 @@ from .project_create_from_environment_params import ( ProjectCreateFromEnvironmentParams as ProjectCreateFromEnvironmentParams, ) +from .runner_list_scm_organizations_response import ( + RunnerListScmOrganizationsResponse as RunnerListScmOrganizationsResponse, +) +from .runner_check_repository_access_response import ( + RunnerCheckRepositoryAccessResponse as RunnerCheckRepositoryAccessResponse, +) from .environment_create_from_project_response import ( EnvironmentCreateFromProjectResponse as EnvironmentCreateFromProjectResponse, ) diff --git a/src/gitpod/types/account_membership.py b/src/gitpod/types/account_membership.py index 10f2603..6f443a8 100644 --- a/src/gitpod/types/account_membership.py +++ b/src/gitpod/types/account_membership.py @@ -6,6 +6,7 @@ from .._models import BaseModel from .shared.organization_role import OrganizationRole +from .shared.organization_tier import OrganizationTier __all__ = ["AccountMembership"] @@ -25,6 +26,9 @@ class AccountMembership(BaseModel): organization_member_count: Optional[int] = FieldInfo(alias="organizationMemberCount", default=None) """ - organization_name is the member count of the organization the user is a member - of + organization_member_count is the member count of the organization the user is a + member of """ + + organization_tier: Optional[OrganizationTier] = FieldInfo(alias="organizationTier", default=None) + """organization_tier is the tier of the organization (Free, Core, Enterprise)""" diff --git a/src/gitpod/types/agent_code_context.py b/src/gitpod/types/agent_code_context.py index 05c1832..ece7309 100644 --- a/src/gitpod/types/agent_code_context.py +++ b/src/gitpod/types/agent_code_context.py @@ -5,6 +5,7 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .shared.state import State __all__ = ["AgentCodeContext", "ContextURL", "PullRequest", "PullRequestRepository"] @@ -40,12 +41,18 @@ class PullRequest(BaseModel): author: Optional[str] = None """Author name as provided by the SCM system""" + draft: Optional[bool] = None + """Whether this is a draft pull request""" + from_branch: Optional[str] = FieldInfo(alias="fromBranch", default=None) """Source branch name (the branch being merged from)""" repository: Optional[PullRequestRepository] = None """Repository information""" + state: Optional[State] = None + """Current state of the pull request""" + title: Optional[str] = None """Pull request title""" diff --git a/src/gitpod/types/agent_code_context_param.py b/src/gitpod/types/agent_code_context_param.py index 8080145..821f296 100644 --- a/src/gitpod/types/agent_code_context_param.py +++ b/src/gitpod/types/agent_code_context_param.py @@ -6,6 +6,7 @@ from typing_extensions import Annotated, TypedDict from .._utils import PropertyInfo +from .shared.state import State __all__ = ["AgentCodeContextParam", "ContextURL", "PullRequest", "PullRequestRepository"] @@ -41,12 +42,18 @@ class PullRequest(TypedDict, total=False): author: str """Author name as provided by the SCM system""" + draft: bool + """Whether this is a draft pull request""" + from_branch: Annotated[str, PropertyInfo(alias="fromBranch")] """Source branch name (the branch being merged from)""" repository: PullRequestRepository """Repository information""" + state: State + """Current state of the pull request""" + title: str """Pull request title""" diff --git a/src/gitpod/types/agent_execution.py b/src/gitpod/types/agent_execution.py index 384da90..ad11938 100644 --- a/src/gitpod/types/agent_execution.py +++ b/src/gitpod/types/agent_execution.py @@ -259,9 +259,6 @@ class Spec(BaseModel): limits: Optional[SpecLimits] = None - mode: Optional[AgentMode] = None - """mode is the operational mode for this agent execution""" - session: Optional[str] = None spec_version: Optional[str] = FieldInfo(alias="specVersion", default=None) @@ -355,6 +352,12 @@ class Status(BaseModel): judgement: Optional[str] = None """judgement is the judgement of the agent run produced by the judgement prompt.""" + mode: Optional[AgentMode] = None + """ + mode is the current operational mode of the agent execution. This is set by the + agent when entering different modes (e.g., Ralph mode via /ona:ralph command). + """ + outputs: Optional[Dict[str, StatusOutputs]] = None """ outputs is a map of key-value pairs that can be set by the agent during diff --git a/src/gitpod/types/agent_mode.py b/src/gitpod/types/agent_mode.py index de414c7..a58c379 100644 --- a/src/gitpod/types/agent_mode.py +++ b/src/gitpod/types/agent_mode.py @@ -4,4 +4,6 @@ __all__ = ["AgentMode"] -AgentMode: TypeAlias = Literal["AGENT_MODE_UNSPECIFIED", "AGENT_MODE_EXECUTION", "AGENT_MODE_PLANNING"] +AgentMode: TypeAlias = Literal[ + "AGENT_MODE_UNSPECIFIED", "AGENT_MODE_EXECUTION", "AGENT_MODE_PLANNING", "AGENT_MODE_RALPH", "AGENT_MODE_SPEC" +] diff --git a/src/gitpod/types/group.py b/src/gitpod/types/group.py index ac727d0..1b70f57 100644 --- a/src/gitpod/types/group.py +++ b/src/gitpod/types/group.py @@ -107,6 +107,12 @@ class Group(BaseModel): description: Optional[str] = None + direct_share: Optional[bool] = FieldInfo(alias="directShare", default=None) + """ + direct_share indicates that this group is used for direct user sharing on + resources. These groups are hidden from regular group listings. + """ + member_count: Optional[int] = FieldInfo(alias="memberCount", default=None) """member_count is the total number of members in this group""" diff --git a/src/gitpod/types/groups/__init__.py b/src/gitpod/types/groups/__init__.py index abbe99f..384b0a7 100644 --- a/src/gitpod/types/groups/__init__.py +++ b/src/gitpod/types/groups/__init__.py @@ -2,9 +2,10 @@ from __future__ import annotations -from .resource_role import ResourceRole as ResourceRole from .role_assignment import RoleAssignment as RoleAssignment from .group_membership import GroupMembership as GroupMembership +from .share_create_params import ShareCreateParams as ShareCreateParams +from .share_delete_params import ShareDeleteParams as ShareDeleteParams from .membership_list_params import MembershipListParams as MembershipListParams from .membership_create_params import MembershipCreateParams as MembershipCreateParams from .membership_delete_params import MembershipDeleteParams as MembershipDeleteParams diff --git a/src/gitpod/types/groups/role_assignment.py b/src/gitpod/types/groups/role_assignment.py index 38e30ea..39512d0 100644 --- a/src/gitpod/types/groups/role_assignment.py +++ b/src/gitpod/types/groups/role_assignment.py @@ -5,7 +5,7 @@ from pydantic import Field as FieldInfo from ..._models import BaseModel -from .resource_role import ResourceRole +from ..shared.resource_role import ResourceRole from ..shared.resource_type import ResourceType __all__ = ["RoleAssignment"] diff --git a/src/gitpod/types/groups/role_assignment_create_params.py b/src/gitpod/types/groups/role_assignment_create_params.py index d036e80..deee188 100644 --- a/src/gitpod/types/groups/role_assignment_create_params.py +++ b/src/gitpod/types/groups/role_assignment_create_params.py @@ -5,7 +5,7 @@ from typing_extensions import Annotated, TypedDict from ..._utils import PropertyInfo -from .resource_role import ResourceRole +from ..shared.resource_role import ResourceRole from ..shared.resource_type import ResourceType __all__ = ["RoleAssignmentCreateParams"] diff --git a/src/gitpod/types/groups/role_assignment_list_params.py b/src/gitpod/types/groups/role_assignment_list_params.py index 23c236b..63b97bd 100644 --- a/src/gitpod/types/groups/role_assignment_list_params.py +++ b/src/gitpod/types/groups/role_assignment_list_params.py @@ -6,7 +6,7 @@ from typing_extensions import Annotated, TypedDict from ..._utils import PropertyInfo -from .resource_role import ResourceRole +from ..shared.resource_role import ResourceRole from ..shared.resource_type import ResourceType __all__ = ["RoleAssignmentListParams", "Filter", "Pagination"] diff --git a/src/gitpod/types/groups/share_create_params.py b/src/gitpod/types/groups/share_create_params.py new file mode 100644 index 0000000..3aba19d --- /dev/null +++ b/src/gitpod/types/groups/share_create_params.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ..._utils import PropertyInfo +from ..shared.principal import Principal +from ..shared.resource_role import ResourceRole +from ..shared.resource_type import ResourceType + +__all__ = ["ShareCreateParams"] + + +class ShareCreateParams(TypedDict, total=False): + principal: Principal + """Type of principal to share with (user or service account)""" + + principal_id: Annotated[str, PropertyInfo(alias="principalId")] + """ID of the principal (user or service account) to share with""" + + resource_id: Annotated[str, PropertyInfo(alias="resourceId")] + """ID of the resource to share""" + + resource_type: Annotated[ResourceType, PropertyInfo(alias="resourceType")] + """Type of resource to share (runner, project, etc.)""" + + role: ResourceRole + """Role to grant the principal on the resource""" diff --git a/src/gitpod/types/groups/share_delete_params.py b/src/gitpod/types/groups/share_delete_params.py new file mode 100644 index 0000000..e855a21 --- /dev/null +++ b/src/gitpod/types/groups/share_delete_params.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ..._utils import PropertyInfo +from ..shared.principal import Principal +from ..shared.resource_type import ResourceType + +__all__ = ["ShareDeleteParams"] + + +class ShareDeleteParams(TypedDict, total=False): + principal: Principal + """Type of principal to remove access from (user or service account)""" + + principal_id: Annotated[str, PropertyInfo(alias="principalId")] + """ID of the principal (user or service account) to remove access from""" + + resource_id: Annotated[str, PropertyInfo(alias="resourceId")] + """ID of the resource to unshare""" + + resource_type: Annotated[ResourceType, PropertyInfo(alias="resourceType")] + """Type of resource to unshare""" diff --git a/src/gitpod/types/organization.py b/src/gitpod/types/organization.py index edf88f1..e833b09 100644 --- a/src/gitpod/types/organization.py +++ b/src/gitpod/types/organization.py @@ -7,7 +7,7 @@ from .._models import BaseModel from .invite_domains import InviteDomains -from .organization_tier import OrganizationTier +from .shared.organization_tier import OrganizationTier __all__ = ["Organization"] diff --git a/src/gitpod/types/organization_list_members_params.py b/src/gitpod/types/organization_list_members_params.py index 06c529e..2e5f87e 100644 --- a/src/gitpod/types/organization_list_members_params.py +++ b/src/gitpod/types/organization_list_members_params.py @@ -2,11 +2,14 @@ from __future__ import annotations -from typing_extensions import Required, Annotated, TypedDict +from typing import List +from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo +from .shared.user_status import UserStatus +from .shared.organization_role import OrganizationRole -__all__ = ["OrganizationListMembersParams", "Filter", "Pagination"] +__all__ = ["OrganizationListMembersParams", "Filter", "Pagination", "Sort"] class OrganizationListMembersParams(TypedDict, total=False): @@ -22,11 +25,26 @@ class OrganizationListMembersParams(TypedDict, total=False): pagination: Pagination """pagination contains the pagination options for listing members""" + sort: Sort + """sort specifies the order of results. + + When unspecified, the authenticated user is returned first, followed by other + members sorted by name ascending. When an explicit sort is specified, results + are sorted purely by the requested field without any special handling for the + authenticated user. + """ + class Filter(TypedDict, total=False): + roles: List[OrganizationRole] + """roles filters members by their organization role""" + search: str """search performs case-insensitive search across member name and email""" + statuses: List[UserStatus] + """status filters members by their user status""" + class Pagination(TypedDict, total=False): """pagination contains the pagination options for listing members""" @@ -42,3 +60,17 @@ class Pagination(TypedDict, total=False): Maximum 100. """ + + +class Sort(TypedDict, total=False): + """sort specifies the order of results. + + When unspecified, the authenticated user is + returned first, followed by other members sorted by name ascending. When an explicit + sort is specified, results are sorted purely by the requested field without any + special handling for the authenticated user. + """ + + field: Literal["SORT_FIELD_UNSPECIFIED", "SORT_FIELD_NAME", "SORT_FIELD_DATE_JOINED"] + + order: Literal["SORT_ORDER_UNSPECIFIED", "SORT_ORDER_ASC", "SORT_ORDER_DESC"] diff --git a/src/gitpod/types/organizations/__init__.py b/src/gitpod/types/organizations/__init__.py index ba4b2b5..60c60eb 100644 --- a/src/gitpod/types/organizations/__init__.py +++ b/src/gitpod/types/organizations/__init__.py @@ -6,6 +6,7 @@ from .custom_domain import CustomDomain as CustomDomain from .provider_type import ProviderType as ProviderType from .sso_configuration import SSOConfiguration as SSOConfiguration +from .scim_configuration import ScimConfiguration as ScimConfiguration from .crowd_strike_config import CrowdStrikeConfig as CrowdStrikeConfig from .domain_verification import DomainVerification as DomainVerification from .organization_invite import OrganizationInvite as OrganizationInvite @@ -30,20 +31,34 @@ from .custom_domain_retrieve_params import CustomDomainRetrieveParams as CustomDomainRetrieveParams from .custom_domain_update_response import CustomDomainUpdateResponse as CustomDomainUpdateResponse from .sso_configuration_list_params import SSOConfigurationListParams as SSOConfigurationListParams +from .scim_configuration_list_params import ScimConfigurationListParams as ScimConfigurationListParams from .custom_domain_retrieve_response import CustomDomainRetrieveResponse as CustomDomainRetrieveResponse from .domain_verification_list_params import DomainVerificationListParams as DomainVerificationListParams from .sso_configuration_create_params import SSOConfigurationCreateParams as SSOConfigurationCreateParams from .sso_configuration_delete_params import SSOConfigurationDeleteParams as SSOConfigurationDeleteParams from .sso_configuration_update_params import SSOConfigurationUpdateParams as SSOConfigurationUpdateParams +from .scim_configuration_create_params import ScimConfigurationCreateParams as ScimConfigurationCreateParams +from .scim_configuration_delete_params import ScimConfigurationDeleteParams as ScimConfigurationDeleteParams +from .scim_configuration_update_params import ScimConfigurationUpdateParams as ScimConfigurationUpdateParams from .domain_verification_create_params import DomainVerificationCreateParams as DomainVerificationCreateParams from .domain_verification_delete_params import DomainVerificationDeleteParams as DomainVerificationDeleteParams from .domain_verification_verify_params import DomainVerificationVerifyParams as DomainVerificationVerifyParams from .sso_configuration_create_response import SSOConfigurationCreateResponse as SSOConfigurationCreateResponse from .sso_configuration_retrieve_params import SSOConfigurationRetrieveParams as SSOConfigurationRetrieveParams +from .scim_configuration_create_response import ScimConfigurationCreateResponse as ScimConfigurationCreateResponse +from .scim_configuration_retrieve_params import ScimConfigurationRetrieveParams as ScimConfigurationRetrieveParams +from .scim_configuration_update_response import ScimConfigurationUpdateResponse as ScimConfigurationUpdateResponse from .domain_verification_create_response import DomainVerificationCreateResponse as DomainVerificationCreateResponse from .domain_verification_retrieve_params import DomainVerificationRetrieveParams as DomainVerificationRetrieveParams from .domain_verification_verify_response import DomainVerificationVerifyResponse as DomainVerificationVerifyResponse from .sso_configuration_retrieve_response import SSOConfigurationRetrieveResponse as SSOConfigurationRetrieveResponse +from .scim_configuration_retrieve_response import ScimConfigurationRetrieveResponse as ScimConfigurationRetrieveResponse from .domain_verification_retrieve_response import ( DomainVerificationRetrieveResponse as DomainVerificationRetrieveResponse, ) +from .scim_configuration_regenerate_token_params import ( + ScimConfigurationRegenerateTokenParams as ScimConfigurationRegenerateTokenParams, +) +from .scim_configuration_regenerate_token_response import ( + ScimConfigurationRegenerateTokenResponse as ScimConfigurationRegenerateTokenResponse, +) diff --git a/src/gitpod/types/organizations/scim_configuration.py b/src/gitpod/types/organizations/scim_configuration.py new file mode 100644 index 0000000..289db0f --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ScimConfiguration"] + + +class ScimConfiguration(BaseModel): + """SCIMConfiguration represents a SCIM 2.0 provisioning configuration""" + + id: str + """id is the unique identifier of the SCIM configuration""" + + created_at: datetime = FieldInfo(alias="createdAt") + """created_at is when the SCIM configuration was created""" + + organization_id: str = FieldInfo(alias="organizationId") + """ + organization_id is the ID of the organization this SCIM configuration belongs to + """ + + updated_at: datetime = FieldInfo(alias="updatedAt") + """updated_at is when the SCIM configuration was last updated""" + + enabled: Optional[bool] = None + """enabled indicates if SCIM provisioning is active""" + + name: Optional[str] = None + """name is a human-readable name for the SCIM configuration""" + + sso_configuration_id: Optional[str] = FieldInfo(alias="ssoConfigurationId", default=None) + """sso_configuration_id is the linked SSO configuration (optional)""" diff --git a/src/gitpod/types/organizations/scim_configuration_create_params.py b/src/gitpod/types/organizations/scim_configuration_create_params.py new file mode 100644 index 0000000..fae3380 --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_create_params.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ScimConfigurationCreateParams"] + + +class ScimConfigurationCreateParams(TypedDict, total=False): + organization_id: Required[Annotated[str, PropertyInfo(alias="organizationId")]] + """ + organization_id is the ID of the organization to create the SCIM configuration + for + """ + + sso_configuration_id: Required[Annotated[str, PropertyInfo(alias="ssoConfigurationId")]] + """ + sso_configuration_id is the SSO configuration to link (required for user + provisioning) + """ + + name: Optional[str] + """name is a human-readable name for the SCIM configuration""" diff --git a/src/gitpod/types/organizations/scim_configuration_create_response.py b/src/gitpod/types/organizations/scim_configuration_create_response.py new file mode 100644 index 0000000..95ba89b --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_create_response.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from .scim_configuration import ScimConfiguration + +__all__ = ["ScimConfigurationCreateResponse"] + + +class ScimConfigurationCreateResponse(BaseModel): + token: str + """ + token is the bearer token for SCIM API authentication. This is only returned + once during creation - store it securely. + """ + + scim_configuration: ScimConfiguration = FieldInfo(alias="scimConfiguration") + """scim_configuration is the created SCIM configuration""" diff --git a/src/gitpod/types/organizations/scim_configuration_delete_params.py b/src/gitpod/types/organizations/scim_configuration_delete_params.py new file mode 100644 index 0000000..51972cb --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_delete_params.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ScimConfigurationDeleteParams"] + + +class ScimConfigurationDeleteParams(TypedDict, total=False): + scim_configuration_id: Required[Annotated[str, PropertyInfo(alias="scimConfigurationId")]] + """scim_configuration_id is the ID of the SCIM configuration to delete""" diff --git a/src/gitpod/types/organizations/scim_configuration_list_params.py b/src/gitpod/types/organizations/scim_configuration_list_params.py new file mode 100644 index 0000000..199d3d3 --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_list_params.py @@ -0,0 +1,31 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ScimConfigurationListParams", "Pagination"] + + +class ScimConfigurationListParams(TypedDict, total=False): + token: str + + page_size: Annotated[int, PropertyInfo(alias="pageSize")] + + pagination: Pagination + + +class Pagination(TypedDict, total=False): + token: str + """ + Token for the next set of results that was returned as next_token of a + PaginationResponse + """ + + page_size: Annotated[int, PropertyInfo(alias="pageSize")] + """Page size is the maximum number of results to retrieve per page. Defaults to 25. + + Maximum 100. + """ diff --git a/src/gitpod/types/organizations/scim_configuration_regenerate_token_params.py b/src/gitpod/types/organizations/scim_configuration_regenerate_token_params.py new file mode 100644 index 0000000..b6cedad --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_regenerate_token_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ScimConfigurationRegenerateTokenParams"] + + +class ScimConfigurationRegenerateTokenParams(TypedDict, total=False): + scim_configuration_id: Required[Annotated[str, PropertyInfo(alias="scimConfigurationId")]] + """ + scim_configuration_id is the ID of the SCIM configuration to regenerate token + for + """ diff --git a/src/gitpod/types/organizations/scim_configuration_regenerate_token_response.py b/src/gitpod/types/organizations/scim_configuration_regenerate_token_response.py new file mode 100644 index 0000000..0af03b1 --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_regenerate_token_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["ScimConfigurationRegenerateTokenResponse"] + + +class ScimConfigurationRegenerateTokenResponse(BaseModel): + token: str + """ + token is the new bearer token for SCIM API authentication. This invalidates the + previous token - store it securely. + """ diff --git a/src/gitpod/types/organizations/scim_configuration_retrieve_params.py b/src/gitpod/types/organizations/scim_configuration_retrieve_params.py new file mode 100644 index 0000000..f020f21 --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_retrieve_params.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ScimConfigurationRetrieveParams"] + + +class ScimConfigurationRetrieveParams(TypedDict, total=False): + scim_configuration_id: Required[Annotated[str, PropertyInfo(alias="scimConfigurationId")]] + """scim_configuration_id is the ID of the SCIM configuration to get""" diff --git a/src/gitpod/types/organizations/scim_configuration_retrieve_response.py b/src/gitpod/types/organizations/scim_configuration_retrieve_response.py new file mode 100644 index 0000000..55bb90a --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_retrieve_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from .scim_configuration import ScimConfiguration + +__all__ = ["ScimConfigurationRetrieveResponse"] + + +class ScimConfigurationRetrieveResponse(BaseModel): + scim_configuration: ScimConfiguration = FieldInfo(alias="scimConfiguration") + """scim_configuration is the SCIM configuration identified by the ID""" diff --git a/src/gitpod/types/organizations/scim_configuration_update_params.py b/src/gitpod/types/organizations/scim_configuration_update_params.py new file mode 100644 index 0000000..da91917 --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_update_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["ScimConfigurationUpdateParams"] + + +class ScimConfigurationUpdateParams(TypedDict, total=False): + scim_configuration_id: Required[Annotated[str, PropertyInfo(alias="scimConfigurationId")]] + """scim_configuration_id is the ID of the SCIM configuration to update""" + + enabled: Optional[bool] + """enabled controls whether SCIM provisioning is active""" + + name: Optional[str] + """name is a human-readable name for the SCIM configuration""" + + sso_configuration_id: Annotated[Optional[str], PropertyInfo(alias="ssoConfigurationId")] + """sso_configuration_id is the SSO configuration to link""" diff --git a/src/gitpod/types/organizations/scim_configuration_update_response.py b/src/gitpod/types/organizations/scim_configuration_update_response.py new file mode 100644 index 0000000..4c4d0ac --- /dev/null +++ b/src/gitpod/types/organizations/scim_configuration_update_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from .scim_configuration import ScimConfiguration + +__all__ = ["ScimConfigurationUpdateResponse"] + + +class ScimConfigurationUpdateResponse(BaseModel): + scim_configuration: ScimConfiguration = FieldInfo(alias="scimConfiguration") + """scim_configuration is the updated SCIM configuration""" diff --git a/src/gitpod/types/runner_capability.py b/src/gitpod/types/runner_capability.py index b63ac78..36bb1f9 100644 --- a/src/gitpod/types/runner_capability.py +++ b/src/gitpod/types/runner_capability.py @@ -12,4 +12,5 @@ "RUNNER_CAPABILITY_ALLOW_ENV_TOKEN_POPULATION", "RUNNER_CAPABILITY_DEFAULT_DEV_CONTAINER_IMAGE", "RUNNER_CAPABILITY_ENVIRONMENT_SNAPSHOT", + "RUNNER_CAPABILITY_PREBUILDS_BEFORE_SNAPSHOT_TRIGGER", ] diff --git a/src/gitpod/types/runner_check_repository_access_params.py b/src/gitpod/types/runner_check_repository_access_params.py new file mode 100644 index 0000000..d118429 --- /dev/null +++ b/src/gitpod/types/runner_check_repository_access_params.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["RunnerCheckRepositoryAccessParams"] + + +class RunnerCheckRepositoryAccessParams(TypedDict, total=False): + repository_url: Annotated[str, PropertyInfo(alias="repositoryUrl")] + """ + repository_url is the URL of the repository to check access for. Can be a clone + URL (https://github.com/org/repo.git) or web URL (https://github.com/org/repo). + """ + + runner_id: Annotated[str, PropertyInfo(alias="runnerId")] diff --git a/src/gitpod/types/runner_check_repository_access_response.py b/src/gitpod/types/runner_check_repository_access_response.py new file mode 100644 index 0000000..11b7536 --- /dev/null +++ b/src/gitpod/types/runner_check_repository_access_response.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["RunnerCheckRepositoryAccessResponse"] + + +class RunnerCheckRepositoryAccessResponse(BaseModel): + error_message: Optional[str] = FieldInfo(alias="errorMessage", default=None) + """ + error_message provides details when access check fails. Empty when has_access is + true. + """ + + has_access: Optional[bool] = FieldInfo(alias="hasAccess", default=None) + """has_access indicates whether the principal has read access to the repository.""" diff --git a/src/gitpod/types/runner_list_scm_organizations_params.py b/src/gitpod/types/runner_list_scm_organizations_params.py new file mode 100644 index 0000000..bd1f788 --- /dev/null +++ b/src/gitpod/types/runner_list_scm_organizations_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["RunnerListScmOrganizationsParams"] + + +class RunnerListScmOrganizationsParams(TypedDict, total=False): + token: str + + page_size: Annotated[int, PropertyInfo(alias="pageSize")] + + runner_id: Annotated[str, PropertyInfo(alias="runnerId")] + + scm_host: Annotated[str, PropertyInfo(alias="scmHost")] + """The SCM host to list organizations from (e.g., "github.com", "gitlab.com")""" diff --git a/src/gitpod/types/runner_list_scm_organizations_response.py b/src/gitpod/types/runner_list_scm_organizations_response.py new file mode 100644 index 0000000..8e9db07 --- /dev/null +++ b/src/gitpod/types/runner_list_scm_organizations_response.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["RunnerListScmOrganizationsResponse", "Organization"] + + +class Organization(BaseModel): + is_admin: Optional[bool] = FieldInfo(alias="isAdmin", default=None) + """ + Whether the user has admin permissions in this organization. Admin permissions + typically allow creating organization-level webhooks. + """ + + name: Optional[str] = None + """Organization name/slug (e.g., "gitpod-io")""" + + url: Optional[str] = None + """Organization URL (e.g., "https://github.com/gitpod-io")""" + + +class RunnerListScmOrganizationsResponse(BaseModel): + organizations: Optional[List[Organization]] = None + """List of organizations the user belongs to""" diff --git a/src/gitpod/types/runner_parse_context_url_response.py b/src/gitpod/types/runner_parse_context_url_response.py index c712e40..c18fd7d 100644 --- a/src/gitpod/types/runner_parse_context_url_response.py +++ b/src/gitpod/types/runner_parse_context_url_response.py @@ -5,6 +5,7 @@ from pydantic import Field as FieldInfo from .._models import BaseModel +from .shared.state import State __all__ = ["RunnerParseContextURLResponse", "Git", "Issue", "Pr", "PullRequest", "PullRequestRepository"] @@ -71,12 +72,18 @@ class PullRequest(BaseModel): author: Optional[str] = None """Author name as provided by the SCM system""" + draft: Optional[bool] = None + """Whether this is a draft pull request""" + from_branch: Optional[str] = FieldInfo(alias="fromBranch", default=None) """Source branch name (the branch being merged from)""" repository: Optional[PullRequestRepository] = None """Repository information""" + state: Optional[State] = None + """Current state of the pull request""" + title: Optional[str] = None """Pull request title""" diff --git a/src/gitpod/types/runner_search_repositories_response.py b/src/gitpod/types/runner_search_repositories_response.py index 65597de..e4f7350 100644 --- a/src/gitpod/types/runner_search_repositories_response.py +++ b/src/gitpod/types/runner_search_repositories_response.py @@ -10,7 +10,12 @@ class Pagination(BaseModel): - """Pagination information for the response""" + """ + Pagination information for the response. + Token format: "NEXT_PAGE/TOTAL_PAGES/TOTAL_COUNT" (e.g., "2/40/1000"). + Use -1 for unknown values (e.g., "2/-1/-1" when totals unavailable). + Empty token means no more pages. + """ next_token: Optional[str] = FieldInfo(alias="nextToken", default=None) """Token passed for retrieving the next set of results. @@ -29,10 +34,18 @@ class Repository(BaseModel): class RunnerSearchRepositoriesResponse(BaseModel): last_page: Optional[int] = FieldInfo(alias="lastPage", default=None) - """Last page in the responses""" + """Deprecated: Use pagination token instead. + + Total pages can be extracted from token. + """ pagination: Optional[Pagination] = None - """Pagination information for the response""" + """ + Pagination information for the response. Token format: + "NEXT_PAGE/TOTAL_PAGES/TOTAL_COUNT" (e.g., "2/40/1000"). Use -1 for unknown + values (e.g., "2/-1/-1" when totals unavailable). Empty token means no more + pages. + """ repositories: Optional[List[Repository]] = None """List of repositories matching the search criteria""" diff --git a/src/gitpod/types/secret_scope.py b/src/gitpod/types/secret_scope.py index f66b672..1d01cb3 100644 --- a/src/gitpod/types/secret_scope.py +++ b/src/gitpod/types/secret_scope.py @@ -16,5 +16,8 @@ class SecretScope(BaseModel): project_id: Optional[str] = FieldInfo(alias="projectId", default=None) """project_id is the Project ID this Secret belongs to""" + service_account_id: Optional[str] = FieldInfo(alias="serviceAccountId", default=None) + """service_account_id is the Service Account ID this Secret belongs to""" + user_id: Optional[str] = FieldInfo(alias="userId", default=None) """user_id is the User ID this Secret belongs to""" diff --git a/src/gitpod/types/secret_scope_param.py b/src/gitpod/types/secret_scope_param.py index d68e56b..b7cf4f4 100644 --- a/src/gitpod/types/secret_scope_param.py +++ b/src/gitpod/types/secret_scope_param.py @@ -16,5 +16,8 @@ class SecretScopeParam(TypedDict, total=False): project_id: Annotated[str, PropertyInfo(alias="projectId")] """project_id is the Project ID this Secret belongs to""" + service_account_id: Annotated[str, PropertyInfo(alias="serviceAccountId")] + """service_account_id is the Service Account ID this Secret belongs to""" + user_id: Annotated[str, PropertyInfo(alias="userId")] """user_id is the User ID this Secret belongs to""" diff --git a/src/gitpod/types/shared/__init__.py b/src/gitpod/types/shared/__init__.py index 50c1315..04e206d 100644 --- a/src/gitpod/types/shared/__init__.py +++ b/src/gitpod/types/shared/__init__.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .task import Task as Task +from .state import State as State from .gateway import Gateway as Gateway from .runs_on import RunsOn as RunsOn from .subject import Subject as Subject @@ -10,11 +11,13 @@ from .secret_ref import SecretRef as SecretRef from .field_value import FieldValue as FieldValue from .user_status import UserStatus as UserStatus +from .resource_role import ResourceRole as ResourceRole from .resource_type import ResourceType as ResourceType from .task_metadata import TaskMetadata as TaskMetadata from .task_execution import TaskExecution as TaskExecution from .environment_class import EnvironmentClass as EnvironmentClass from .organization_role import OrganizationRole as OrganizationRole +from .organization_tier import OrganizationTier as OrganizationTier from .automation_trigger import AutomationTrigger as AutomationTrigger from .task_execution_spec import TaskExecutionSpec as TaskExecutionSpec from .task_execution_phase import TaskExecutionPhase as TaskExecutionPhase diff --git a/src/gitpod/types/shared/automation_trigger.py b/src/gitpod/types/shared/automation_trigger.py index c21e923..8ffd732 100644 --- a/src/gitpod/types/shared/automation_trigger.py +++ b/src/gitpod/types/shared/automation_trigger.py @@ -18,9 +18,13 @@ class AutomationTrigger(BaseModel): The `post_environment_start` field indicates that the automation should be triggered after the environment has started (devcontainer ready). The `post_devcontainer_start` field indicates that the automation should be triggered after the dev container has started. The `prebuild` field starts the automation during a prebuild of an environment. This phase does not have user secrets available. - Note: The prebuild trigger can only be used with tasks, not services. + The `before_snapshot` field triggers the automation after all prebuild tasks complete but before the snapshot is taken. + This is used for tasks that need to run last during prebuilds, such as IDE warmup. + Note: The prebuild and before_snapshot triggers can only be used with tasks, not services. """ + before_snapshot: Optional[bool] = FieldInfo(alias="beforeSnapshot", default=None) + manual: Optional[bool] = None post_devcontainer_start: Optional[bool] = FieldInfo(alias="postDevcontainerStart", default=None) diff --git a/src/gitpod/types/organization_tier.py b/src/gitpod/types/shared/organization_tier.py similarity index 100% rename from src/gitpod/types/organization_tier.py rename to src/gitpod/types/shared/organization_tier.py diff --git a/src/gitpod/types/groups/resource_role.py b/src/gitpod/types/shared/resource_role.py similarity index 98% rename from src/gitpod/types/groups/resource_role.py rename to src/gitpod/types/shared/resource_role.py index cd2e164..33ecbb7 100644 --- a/src/gitpod/types/groups/resource_role.py +++ b/src/gitpod/types/shared/resource_role.py @@ -8,6 +8,7 @@ "RESOURCE_ROLE_UNSPECIFIED", "RESOURCE_ROLE_ORG_ADMIN", "RESOURCE_ROLE_ORG_MEMBER", + "RESOURCE_ROLE_ORG_RUNNERS_ADMIN", "RESOURCE_ROLE_GROUP_ADMIN", "RESOURCE_ROLE_GROUP_VIEWER", "RESOURCE_ROLE_USER_IDENTITY", diff --git a/src/gitpod/types/shared/resource_type.py b/src/gitpod/types/shared/resource_type.py index 1a18f4e..599108b 100644 --- a/src/gitpod/types/shared/resource_type.py +++ b/src/gitpod/types/shared/resource_type.py @@ -48,4 +48,6 @@ "RESOURCE_TYPE_ROLE_ASSIGNMENT_CHANGED", "RESOURCE_TYPE_GROUP_MEMBERSHIP_CHANGED", "RESOURCE_TYPE_WEBHOOK", + "RESOURCE_TYPE_SCIM_CONFIGURATION", + "RESOURCE_TYPE_SERVICE_ACCOUNT_SECRET", ] diff --git a/src/gitpod/types/shared/state.py b/src/gitpod/types/shared/state.py new file mode 100644 index 0000000..92aa0de --- /dev/null +++ b/src/gitpod/types/shared/state.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["State"] + +State: TypeAlias = Literal["STATE_UNSPECIFIED", "STATE_OPEN", "STATE_CLOSED", "STATE_MERGED"] diff --git a/src/gitpod/types/shared_params/__init__.py b/src/gitpod/types/shared_params/__init__.py index 4673c76..1d82ded 100644 --- a/src/gitpod/types/shared_params/__init__.py +++ b/src/gitpod/types/shared_params/__init__.py @@ -1,11 +1,14 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .state import State as State from .runs_on import RunsOn as RunsOn from .subject import Subject as Subject from .principal import Principal as Principal from .task_spec import TaskSpec as TaskSpec from .secret_ref import SecretRef as SecretRef from .field_value import FieldValue as FieldValue +from .user_status import UserStatus as UserStatus +from .resource_role import ResourceRole as ResourceRole from .resource_type import ResourceType as ResourceType from .task_metadata import TaskMetadata as TaskMetadata from .environment_class import EnvironmentClass as EnvironmentClass diff --git a/src/gitpod/types/shared_params/automation_trigger.py b/src/gitpod/types/shared_params/automation_trigger.py index 0c840fe..27dc462 100644 --- a/src/gitpod/types/shared_params/automation_trigger.py +++ b/src/gitpod/types/shared_params/automation_trigger.py @@ -18,9 +18,13 @@ class AutomationTrigger(TypedDict, total=False): The `post_environment_start` field indicates that the automation should be triggered after the environment has started (devcontainer ready). The `post_devcontainer_start` field indicates that the automation should be triggered after the dev container has started. The `prebuild` field starts the automation during a prebuild of an environment. This phase does not have user secrets available. - Note: The prebuild trigger can only be used with tasks, not services. + The `before_snapshot` field triggers the automation after all prebuild tasks complete but before the snapshot is taken. + This is used for tasks that need to run last during prebuilds, such as IDE warmup. + Note: The prebuild and before_snapshot triggers can only be used with tasks, not services. """ + before_snapshot: Annotated[bool, PropertyInfo(alias="beforeSnapshot")] + manual: bool post_devcontainer_start: Annotated[bool, PropertyInfo(alias="postDevcontainerStart")] diff --git a/src/gitpod/types/shared_params/resource_role.py b/src/gitpod/types/shared_params/resource_role.py new file mode 100644 index 0000000..053e954 --- /dev/null +++ b/src/gitpod/types/shared_params/resource_role.py @@ -0,0 +1,61 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["ResourceRole"] + +ResourceRole: TypeAlias = Literal[ + "RESOURCE_ROLE_UNSPECIFIED", + "RESOURCE_ROLE_ORG_ADMIN", + "RESOURCE_ROLE_ORG_MEMBER", + "RESOURCE_ROLE_ORG_RUNNERS_ADMIN", + "RESOURCE_ROLE_GROUP_ADMIN", + "RESOURCE_ROLE_GROUP_VIEWER", + "RESOURCE_ROLE_USER_IDENTITY", + "RESOURCE_ROLE_USER_VIEWER", + "RESOURCE_ROLE_USER_ADMIN", + "RESOURCE_ROLE_ENVIRONMENT_IDENTITY", + "RESOURCE_ROLE_ENVIRONMENT_ADMIN", + "RESOURCE_ROLE_ENVIRONMENT_USER", + "RESOURCE_ROLE_ENVIRONMENT_VIEWER", + "RESOURCE_ROLE_ENVIRONMENT_RUNNER", + "RESOURCE_ROLE_RUNNER_IDENTITY", + "RESOURCE_ROLE_RUNNER_ADMIN", + "RESOURCE_ROLE_RUNNER_LOCAL_ADMIN", + "RESOURCE_ROLE_RUNNER_MANAGED_ADMIN", + "RESOURCE_ROLE_RUNNER_USER", + "RESOURCE_ROLE_RUNNER_CONFIGURATION_READER", + "RESOURCE_ROLE_HOST_AUTHENTICATION_TOKEN_ADMIN", + "RESOURCE_ROLE_HOST_AUTHENTICATION_TOKEN_UPDATER", + "RESOURCE_ROLE_PROJECT_ADMIN", + "RESOURCE_ROLE_PROJECT_USER", + "RESOURCE_ROLE_PROJECT_EDITOR", + "RESOURCE_ROLE_ENVIRONMENT_SERVICE_ADMIN", + "RESOURCE_ROLE_ENVIRONMENT_SERVICE_VIEWER", + "RESOURCE_ROLE_ENVIRONMENT_SERVICE_USER", + "RESOURCE_ROLE_ENVIRONMENT_SERVICE_ENV", + "RESOURCE_ROLE_ENVIRONMENT_TASK_ADMIN", + "RESOURCE_ROLE_ENVIRONMENT_TASK_VIEWER", + "RESOURCE_ROLE_ENVIRONMENT_TASK_USER", + "RESOURCE_ROLE_ENVIRONMENT_TASK_ENV", + "RESOURCE_ROLE_SERVICE_ACCOUNT_IDENTITY", + "RESOURCE_ROLE_SERVICE_ACCOUNT_ADMIN", + "RESOURCE_ROLE_AGENT_EXECUTION_IDENTITY", + "RESOURCE_ROLE_AGENT_EXECUTION_USER", + "RESOURCE_ROLE_AGENT_EXECUTION_ADMIN", + "RESOURCE_ROLE_AGENT_EXECUTION_RUNNER", + "RESOURCE_ROLE_AGENT_EXECUTION_OUTPUTS_REPORTER", + "RESOURCE_ROLE_AGENT_ADMIN", + "RESOURCE_ROLE_AGENT_VIEWER", + "RESOURCE_ROLE_AGENT_EXECUTOR", + "RESOURCE_ROLE_WORKFLOW_ADMIN", + "RESOURCE_ROLE_WORKFLOW_USER", + "RESOURCE_ROLE_WORKFLOW_VIEWER", + "RESOURCE_ROLE_WORKFLOW_EXECUTOR", + "RESOURCE_ROLE_SNAPSHOT_ADMIN", + "RESOURCE_ROLE_SNAPSHOT_RUNNER", + "RESOURCE_ROLE_WEBHOOK_ADMIN", + "RESOURCE_ROLE_WEBHOOK_VIEWER", +] diff --git a/src/gitpod/types/shared_params/resource_type.py b/src/gitpod/types/shared_params/resource_type.py index 793bab2..9d489e4 100644 --- a/src/gitpod/types/shared_params/resource_type.py +++ b/src/gitpod/types/shared_params/resource_type.py @@ -50,4 +50,6 @@ "RESOURCE_TYPE_ROLE_ASSIGNMENT_CHANGED", "RESOURCE_TYPE_GROUP_MEMBERSHIP_CHANGED", "RESOURCE_TYPE_WEBHOOK", + "RESOURCE_TYPE_SCIM_CONFIGURATION", + "RESOURCE_TYPE_SERVICE_ACCOUNT_SECRET", ] diff --git a/src/gitpod/types/shared_params/state.py b/src/gitpod/types/shared_params/state.py new file mode 100644 index 0000000..1d81f94 --- /dev/null +++ b/src/gitpod/types/shared_params/state.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["State"] + +State: TypeAlias = Literal["STATE_UNSPECIFIED", "STATE_OPEN", "STATE_CLOSED", "STATE_MERGED"] diff --git a/src/gitpod/types/shared_params/user_status.py b/src/gitpod/types/shared_params/user_status.py new file mode 100644 index 0000000..fd8ac19 --- /dev/null +++ b/src/gitpod/types/shared_params/user_status.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["UserStatus"] + +UserStatus: TypeAlias = Literal[ + "USER_STATUS_UNSPECIFIED", "USER_STATUS_ACTIVE", "USER_STATUS_SUSPENDED", "USER_STATUS_LEFT" +] diff --git a/src/gitpod/types/user_input_block_param.py b/src/gitpod/types/user_input_block_param.py index 5a6b87e..905b928 100644 --- a/src/gitpod/types/user_input_block_param.py +++ b/src/gitpod/types/user_input_block_param.py @@ -2,30 +2,61 @@ from __future__ import annotations -from typing import Union +from typing import Union, Iterable from datetime import datetime -from typing_extensions import Annotated, TypedDict +from typing_extensions import Literal, Annotated, TypedDict from .._types import Base64FileInput from .._utils import PropertyInfo from .._models import set_pydantic_config -__all__ = ["UserInputBlockParam", "Image", "Text"] +__all__ = ["UserInputBlockParam", "Image", "Input", "InputImage", "InputText", "Text"] class Image(TypedDict, total=False): """ ImageInput allows sending images to the agent. - Media type is inferred from magic bytes by the backend. + Client must provide the MIME type; backend validates against magic bytes. """ data: Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")] - """Raw image data (max 4MB). Supported formats: PNG, JPEG, WebP.""" + """Raw image data (max 4MB). Supported formats: PNG, JPEG.""" + + mime_type: Annotated[Literal["image/png", "image/jpeg"], PropertyInfo(alias="mimeType")] set_pydantic_config(Image, {"arbitrary_types_allowed": True}) +class InputImage(TypedDict, total=False): + """ + ImageInput allows sending images to the agent. + Client must provide the MIME type; backend validates against magic bytes. + """ + + data: Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")] + """Raw image data (max 4MB). Supported formats: PNG, JPEG.""" + + mime_type: Annotated[Literal["image/png", "image/jpeg"], PropertyInfo(alias="mimeType")] + + +set_pydantic_config(InputImage, {"arbitrary_types_allowed": True}) + + +class InputText(TypedDict, total=False): + content: str + + +class Input(TypedDict, total=False): + image: InputImage + """ + ImageInput allows sending images to the agent. Client must provide the MIME + type; backend validates against magic bytes. + """ + + text: InputText + + class Text(TypedDict, total=False): content: str @@ -38,8 +69,10 @@ class UserInputBlockParam(TypedDict, total=False): image: Image """ - ImageInput allows sending images to the agent. Media type is inferred from magic - bytes by the backend. + ImageInput allows sending images to the agent. Client must provide the MIME + type; backend validates against magic bytes. """ + inputs: Iterable[Input] + text: Text diff --git a/tests/api_resources/environments/automations/test_services.py b/tests/api_resources/environments/automations/test_services.py index 650c04b..c0db2dc 100644 --- a/tests/api_resources/environments/automations/test_services.py +++ b/tests/api_resources/environments/automations/test_services.py @@ -46,6 +46,7 @@ def test_method_create_with_all_params(self, client: Gitpod) -> None: "role": "SERVICE_ROLE_UNSPECIFIED", "triggered_by": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -157,6 +158,7 @@ def test_method_update_with_all_params(self, client: Gitpod) -> None: "triggered_by": { "trigger": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -404,6 +406,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGitpod) -> "role": "SERVICE_ROLE_UNSPECIFIED", "triggered_by": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -515,6 +518,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncGitpod) -> "triggered_by": { "trigger": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, diff --git a/tests/api_resources/environments/automations/test_tasks.py b/tests/api_resources/environments/automations/test_tasks.py index 057d1a1..289d4f4 100644 --- a/tests/api_resources/environments/automations/test_tasks.py +++ b/tests/api_resources/environments/automations/test_tasks.py @@ -47,6 +47,7 @@ def test_method_create_with_all_params(self, client: Gitpod) -> None: "reference": "build", "triggered_by": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -151,6 +152,7 @@ def test_method_update_with_all_params(self, client: Gitpod) -> None: "triggered_by": { "trigger": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -349,6 +351,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGitpod) -> "reference": "build", "triggered_by": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -453,6 +456,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncGitpod) -> "triggered_by": { "trigger": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, diff --git a/tests/api_resources/groups/test_shares.py b/tests/api_resources/groups/test_shares.py new file mode 100644 index 0000000..3e0c57f --- /dev/null +++ b/tests/api_resources/groups/test_shares.py @@ -0,0 +1,181 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from gitpod import Gitpod, AsyncGitpod +from tests.utils import assert_matches_type + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestShares: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: Gitpod) -> None: + share = client.groups.shares.create() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: Gitpod) -> None: + share = client.groups.shares.create( + principal="PRINCIPAL_SERVICE_ACCOUNT", + principal_id="a1b2c3d4-5678-90ab-cdef-1234567890ab", + resource_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + resource_type="RESOURCE_TYPE_RUNNER", + role="RESOURCE_ROLE_RUNNER_USER", + ) + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: Gitpod) -> None: + response = client.groups.shares.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + share = response.parse() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Gitpod) -> None: + with client.groups.shares.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + share = response.parse() + assert_matches_type(object, share, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: Gitpod) -> None: + share = client.groups.shares.delete() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete_with_all_params(self, client: Gitpod) -> None: + share = client.groups.shares.delete( + principal="PRINCIPAL_USER", + principal_id="f53d2330-3795-4c5d-a1f3-453121af9c60", + resource_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + resource_type="RESOURCE_TYPE_RUNNER", + ) + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Gitpod) -> None: + response = client.groups.shares.with_raw_response.delete() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + share = response.parse() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Gitpod) -> None: + with client.groups.shares.with_streaming_response.delete() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + share = response.parse() + assert_matches_type(object, share, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncShares: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncGitpod) -> None: + share = await async_client.groups.shares.create() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncGitpod) -> None: + share = await async_client.groups.shares.create( + principal="PRINCIPAL_SERVICE_ACCOUNT", + principal_id="a1b2c3d4-5678-90ab-cdef-1234567890ab", + resource_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + resource_type="RESOURCE_TYPE_RUNNER", + role="RESOURCE_ROLE_RUNNER_USER", + ) + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncGitpod) -> None: + response = await async_client.groups.shares.with_raw_response.create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + share = await response.parse() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncGitpod) -> None: + async with async_client.groups.shares.with_streaming_response.create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + share = await response.parse() + assert_matches_type(object, share, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncGitpod) -> None: + share = await async_client.groups.shares.delete() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete_with_all_params(self, async_client: AsyncGitpod) -> None: + share = await async_client.groups.shares.delete( + principal="PRINCIPAL_USER", + principal_id="f53d2330-3795-4c5d-a1f3-453121af9c60", + resource_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + resource_type="RESOURCE_TYPE_RUNNER", + ) + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncGitpod) -> None: + response = await async_client.groups.shares.with_raw_response.delete() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + share = await response.parse() + assert_matches_type(object, share, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncGitpod) -> None: + async with async_client.groups.shares.with_streaming_response.delete() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + share = await response.parse() + assert_matches_type(object, share, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/organizations/test_scim_configurations.py b/tests/api_resources/organizations/test_scim_configurations.py new file mode 100644 index 0000000..16c6e25 --- /dev/null +++ b/tests/api_resources/organizations/test_scim_configurations.py @@ -0,0 +1,501 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from gitpod import Gitpod, AsyncGitpod +from tests.utils import assert_matches_type +from gitpod.pagination import SyncScimConfigurationsPage, AsyncScimConfigurationsPage +from gitpod.types.organizations import ( + ScimConfiguration, + ScimConfigurationCreateResponse, + ScimConfigurationUpdateResponse, + ScimConfigurationRetrieveResponse, + ScimConfigurationRegenerateTokenResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestScimConfigurations: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + name="name", + ) + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create(self, client: Gitpod) -> None: + response = client.organizations.scim_configurations.with_raw_response.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Gitpod) -> None: + with client.organizations.scim_configurations.with_streaming_response.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.retrieve( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationRetrieveResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Gitpod) -> None: + response = client.organizations.scim_configurations.with_raw_response.retrieve( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationRetrieveResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Gitpod) -> None: + with client.organizations.scim_configurations.with_streaming_response.retrieve( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationRetrieveResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + enabled=False, + name="name", + sso_configuration_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update(self, client: Gitpod) -> None: + response = client.organizations.scim_configurations.with_raw_response.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Gitpod) -> None: + with client.organizations.scim_configurations.with_streaming_response.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.list() + assert_matches_type(SyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.list( + token="token", + page_size=0, + pagination={ + "token": "token", + "page_size": 20, + }, + ) + assert_matches_type(SyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: Gitpod) -> None: + response = client.organizations.scim_configurations.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = response.parse() + assert_matches_type(SyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Gitpod) -> None: + with client.organizations.scim_configurations.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = response.parse() + assert_matches_type(SyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.delete( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(object, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Gitpod) -> None: + response = client.organizations.scim_configurations.with_raw_response.delete( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = response.parse() + assert_matches_type(object, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Gitpod) -> None: + with client.organizations.scim_configurations.with_streaming_response.delete( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = response.parse() + assert_matches_type(object, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_regenerate_token(self, client: Gitpod) -> None: + scim_configuration = client.organizations.scim_configurations.regenerate_token( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationRegenerateTokenResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_regenerate_token(self, client: Gitpod) -> None: + response = client.organizations.scim_configurations.with_raw_response.regenerate_token( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationRegenerateTokenResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_regenerate_token(self, client: Gitpod) -> None: + with client.organizations.scim_configurations.with_streaming_response.regenerate_token( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = response.parse() + assert_matches_type(ScimConfigurationRegenerateTokenResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncScimConfigurations: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + name="name", + ) + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncGitpod) -> None: + response = await async_client.organizations.scim_configurations.with_raw_response.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncGitpod) -> None: + async with async_client.organizations.scim_configurations.with_streaming_response.create( + organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", + sso_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationCreateResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.retrieve( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationRetrieveResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncGitpod) -> None: + response = await async_client.organizations.scim_configurations.with_raw_response.retrieve( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationRetrieveResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncGitpod) -> None: + async with async_client.organizations.scim_configurations.with_streaming_response.retrieve( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationRetrieveResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + enabled=False, + name="name", + sso_configuration_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncGitpod) -> None: + response = await async_client.organizations.scim_configurations.with_raw_response.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncGitpod) -> None: + async with async_client.organizations.scim_configurations.with_streaming_response.update( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationUpdateResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.list() + assert_matches_type(AsyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.list( + token="token", + page_size=0, + pagination={ + "token": "token", + "page_size": 20, + }, + ) + assert_matches_type(AsyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncGitpod) -> None: + response = await async_client.organizations.scim_configurations.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = await response.parse() + assert_matches_type(AsyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncGitpod) -> None: + async with async_client.organizations.scim_configurations.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = await response.parse() + assert_matches_type(AsyncScimConfigurationsPage[ScimConfiguration], scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.delete( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(object, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncGitpod) -> None: + response = await async_client.organizations.scim_configurations.with_raw_response.delete( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = await response.parse() + assert_matches_type(object, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncGitpod) -> None: + async with async_client.organizations.scim_configurations.with_streaming_response.delete( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = await response.parse() + assert_matches_type(object, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_regenerate_token(self, async_client: AsyncGitpod) -> None: + scim_configuration = await async_client.organizations.scim_configurations.regenerate_token( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(ScimConfigurationRegenerateTokenResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_regenerate_token(self, async_client: AsyncGitpod) -> None: + response = await async_client.organizations.scim_configurations.with_raw_response.regenerate_token( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationRegenerateTokenResponse, scim_configuration, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_regenerate_token(self, async_client: AsyncGitpod) -> None: + async with async_client.organizations.scim_configurations.with_streaming_response.regenerate_token( + scim_configuration_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + scim_configuration = await response.parse() + assert_matches_type(ScimConfigurationRegenerateTokenResponse, scim_configuration, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_agents.py b/tests/api_resources/test_agents.py index b92173b..e006c3c 100644 --- a/tests/api_resources/test_agents.py +++ b/tests/api_resources/test_agents.py @@ -361,7 +361,19 @@ def test_method_send_to_execution_with_all_params(self, client: Gitpod) -> None: user_input={ "id": "id", "created_at": parse_datetime("2019-12-27T18:11:19.117Z"), - "image": {"data": "U3RhaW5sZXNzIHJvY2tz"}, + "image": { + "data": "U3RhaW5sZXNzIHJvY2tz", + "mime_type": "image/png", + }, + "inputs": [ + { + "image": { + "data": "U3RhaW5sZXNzIHJvY2tz", + "mime_type": "image/png", + }, + "text": {"content": "x"}, + } + ], "text": {"content": "Generate a report based on the latest logs."}, }, ) @@ -410,6 +422,7 @@ def test_method_start_execution_with_all_params(self, client: Gitpod) -> None: "pull_request": { "id": "id", "author": "author", + "draft": True, "from_branch": "fromBranch", "repository": { "clone_url": "cloneUrl", @@ -417,6 +430,7 @@ def test_method_start_execution_with_all_params(self, client: Gitpod) -> None: "name": "name", "owner": "owner", }, + "state": "STATE_UNSPECIFIED", "title": "title", "to_branch": "toBranch", "url": "url", @@ -872,7 +886,19 @@ async def test_method_send_to_execution_with_all_params(self, async_client: Asyn user_input={ "id": "id", "created_at": parse_datetime("2019-12-27T18:11:19.117Z"), - "image": {"data": "U3RhaW5sZXNzIHJvY2tz"}, + "image": { + "data": "U3RhaW5sZXNzIHJvY2tz", + "mime_type": "image/png", + }, + "inputs": [ + { + "image": { + "data": "U3RhaW5sZXNzIHJvY2tz", + "mime_type": "image/png", + }, + "text": {"content": "x"}, + } + ], "text": {"content": "Generate a report based on the latest logs."}, }, ) @@ -921,6 +947,7 @@ async def test_method_start_execution_with_all_params(self, async_client: AsyncG "pull_request": { "id": "id", "author": "author", + "draft": True, "from_branch": "fromBranch", "repository": { "clone_url": "cloneUrl", @@ -928,6 +955,7 @@ async def test_method_start_execution_with_all_params(self, async_client: AsyncG "name": "name", "owner": "owner", }, + "state": "STATE_UNSPECIFIED", "title": "title", "to_branch": "toBranch", "url": "url", diff --git a/tests/api_resources/test_environments.py b/tests/api_resources/test_environments.py index 127cc4b..b2a37f6 100644 --- a/tests/api_resources/test_environments.py +++ b/tests/api_resources/test_environments.py @@ -43,6 +43,7 @@ def test_method_create_with_all_params(self, client: Gitpod) -> None: "session": "session", "trigger_filter": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -394,6 +395,7 @@ def test_method_create_from_project_with_all_params(self, client: Gitpod) -> Non "session": "session", "trigger_filter": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -697,6 +699,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGitpod) -> "session": "session", "trigger_filter": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, @@ -1048,6 +1051,7 @@ async def test_method_create_from_project_with_all_params(self, async_client: As "session": "session", "trigger_filter": [ { + "before_snapshot": True, "manual": True, "post_devcontainer_start": True, "post_environment_start": True, diff --git a/tests/api_resources/test_organizations.py b/tests/api_resources/test_organizations.py index 8cda4e7..b404eb7 100644 --- a/tests/api_resources/test_organizations.py +++ b/tests/api_resources/test_organizations.py @@ -266,11 +266,19 @@ def test_method_list_members_with_all_params(self, client: Gitpod) -> None: organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", token="token", page_size=0, - filter={"search": "search"}, + filter={ + "roles": ["ORGANIZATION_ROLE_UNSPECIFIED"], + "search": "search", + "statuses": ["USER_STATUS_UNSPECIFIED"], + }, pagination={ "token": "token", "page_size": 20, }, + sort={ + "field": "SORT_FIELD_UNSPECIFIED", + "order": "SORT_ORDER_UNSPECIFIED", + }, ) assert_matches_type(SyncMembersPage[OrganizationMember], organization, path=["response"]) @@ -595,11 +603,19 @@ async def test_method_list_members_with_all_params(self, async_client: AsyncGitp organization_id="b0e12f6c-4c67-429d-a4a6-d9838b5da047", token="token", page_size=0, - filter={"search": "search"}, + filter={ + "roles": ["ORGANIZATION_ROLE_UNSPECIFIED"], + "search": "search", + "statuses": ["USER_STATUS_UNSPECIFIED"], + }, pagination={ "token": "token", "page_size": 20, }, + sort={ + "field": "SORT_FIELD_UNSPECIFIED", + "order": "SORT_ORDER_UNSPECIFIED", + }, ) assert_matches_type(AsyncMembersPage[OrganizationMember], organization, path=["response"]) diff --git a/tests/api_resources/test_runners.py b/tests/api_resources/test_runners.py index 9ce4674..eaf96b9 100644 --- a/tests/api_resources/test_runners.py +++ b/tests/api_resources/test_runners.py @@ -17,6 +17,8 @@ RunnerParseContextURLResponse, RunnerCreateRunnerTokenResponse, RunnerSearchRepositoriesResponse, + RunnerListScmOrganizationsResponse, + RunnerCheckRepositoryAccessResponse, RunnerCheckAuthenticationForHostResponse, ) from gitpod.pagination import SyncRunnersPage, AsyncRunnersPage @@ -291,6 +293,43 @@ def test_streaming_response_check_authentication_for_host(self, client: Gitpod) assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_check_repository_access(self, client: Gitpod) -> None: + runner = client.runners.check_repository_access() + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_check_repository_access_with_all_params(self, client: Gitpod) -> None: + runner = client.runners.check_repository_access( + repository_url="https://github.com/org/repo", + runner_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_check_repository_access(self, client: Gitpod) -> None: + response = client.runners.with_raw_response.check_repository_access() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + runner = response.parse() + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_check_repository_access(self, client: Gitpod) -> None: + with client.runners.with_streaming_response.check_repository_access() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + runner = response.parse() + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create_logs_token(self, client: Gitpod) -> None: @@ -363,6 +402,45 @@ def test_streaming_response_create_runner_token(self, client: Gitpod) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_scm_organizations(self, client: Gitpod) -> None: + runner = client.runners.list_scm_organizations() + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_scm_organizations_with_all_params(self, client: Gitpod) -> None: + runner = client.runners.list_scm_organizations( + token="token", + page_size=0, + runner_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + scm_host="github.com", + ) + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list_scm_organizations(self, client: Gitpod) -> None: + response = client.runners.with_raw_response.list_scm_organizations() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + runner = response.parse() + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list_scm_organizations(self, client: Gitpod) -> None: + with client.runners.with_streaming_response.list_scm_organizations() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + runner = response.parse() + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_parse_context_url(self, client: Gitpod) -> None: @@ -714,6 +792,43 @@ async def test_streaming_response_check_authentication_for_host(self, async_clie assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_check_repository_access(self, async_client: AsyncGitpod) -> None: + runner = await async_client.runners.check_repository_access() + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_check_repository_access_with_all_params(self, async_client: AsyncGitpod) -> None: + runner = await async_client.runners.check_repository_access( + repository_url="https://github.com/org/repo", + runner_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_check_repository_access(self, async_client: AsyncGitpod) -> None: + response = await async_client.runners.with_raw_response.check_repository_access() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + runner = await response.parse() + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_check_repository_access(self, async_client: AsyncGitpod) -> None: + async with async_client.runners.with_streaming_response.check_repository_access() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + runner = await response.parse() + assert_matches_type(RunnerCheckRepositoryAccessResponse, runner, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create_logs_token(self, async_client: AsyncGitpod) -> None: @@ -786,6 +901,45 @@ async def test_streaming_response_create_runner_token(self, async_client: AsyncG assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_scm_organizations(self, async_client: AsyncGitpod) -> None: + runner = await async_client.runners.list_scm_organizations() + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_scm_organizations_with_all_params(self, async_client: AsyncGitpod) -> None: + runner = await async_client.runners.list_scm_organizations( + token="token", + page_size=0, + runner_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + scm_host="github.com", + ) + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list_scm_organizations(self, async_client: AsyncGitpod) -> None: + response = await async_client.runners.with_raw_response.list_scm_organizations() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + runner = await response.parse() + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list_scm_organizations(self, async_client: AsyncGitpod) -> None: + async with async_client.runners.with_streaming_response.list_scm_organizations() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + runner = await response.parse() + assert_matches_type(RunnerListScmOrganizationsResponse, runner, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_parse_context_url(self, async_client: AsyncGitpod) -> None: diff --git a/tests/api_resources/test_secrets.py b/tests/api_resources/test_secrets.py index 6a54d36..680a9d7 100644 --- a/tests/api_resources/test_secrets.py +++ b/tests/api_resources/test_secrets.py @@ -41,6 +41,7 @@ def test_method_create_with_all_params(self, client: Gitpod) -> None: scope={ "organization_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "project_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "service_account_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "user_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", }, value="postgresql://user:pass@localhost:5432/db", @@ -86,6 +87,7 @@ def test_method_list_with_all_params(self, client: Gitpod) -> None: "scope": { "organization_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "project_id": "b0e12f6c-4c67-429d-a4a6-d9838b5da047", + "service_account_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "user_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", }, }, @@ -252,6 +254,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGitpod) -> scope={ "organization_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "project_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "service_account_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "user_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", }, value="postgresql://user:pass@localhost:5432/db", @@ -297,6 +300,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncGitpod) -> N "scope": { "organization_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "project_id": "b0e12f6c-4c67-429d-a4a6-d9838b5da047", + "service_account_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", "user_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", }, }, diff --git a/tests/test_client.py b/tests/test_client.py index f948b8a..81db6c8 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -8,10 +8,11 @@ import json import asyncio import inspect +import dataclasses import tracemalloc -from typing import Any, Union, cast +from typing import Any, Union, TypeVar, Callable, Iterable, Iterator, Optional, Coroutine, cast from unittest import mock -from typing_extensions import Literal +from typing_extensions import Literal, AsyncIterator, override import httpx import pytest @@ -36,6 +37,7 @@ from .utils import update_env +T = TypeVar("T") base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") bearer_token = "My Bearer Token" @@ -50,6 +52,57 @@ def _low_retry_timeout(*_args: Any, **_kwargs: Any) -> float: return 0.1 +def mirror_request_content(request: httpx.Request) -> httpx.Response: + return httpx.Response(200, content=request.content) + + +# note: we can't use the httpx.MockTransport class as it consumes the request +# body itself, which means we can't test that the body is read lazily +class MockTransport(httpx.BaseTransport, httpx.AsyncBaseTransport): + def __init__( + self, + handler: Callable[[httpx.Request], httpx.Response] + | Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]], + ) -> None: + self.handler = handler + + @override + def handle_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert not inspect.iscoroutinefunction(self.handler), "handler must not be a coroutine function" + assert inspect.isfunction(self.handler), "handler must be a function" + return self.handler(request) + + @override + async def handle_async_request( + self, + request: httpx.Request, + ) -> httpx.Response: + assert inspect.iscoroutinefunction(self.handler), "handler must be a coroutine function" + return await self.handler(request) + + +@dataclasses.dataclass +class Counter: + value: int = 0 + + +def _make_sync_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> Iterator[T]: + for item in iterable: + if counter: + counter.value += 1 + yield item + + +async def _make_async_iterator(iterable: Iterable[T], counter: Optional[Counter] = None) -> AsyncIterator[T]: + for item in iterable: + if counter: + counter.value += 1 + yield item + + def _get_open_connections(client: Gitpod | AsyncGitpod) -> int: transport = client._client._transport assert isinstance(transport, httpx.HTTPTransport) or isinstance(transport, httpx.AsyncHTTPTransport) @@ -511,6 +564,70 @@ def test_multipart_repeating_array(self, client: Gitpod) -> None: b"", ] + @pytest.mark.respx(base_url=base_url) + def test_binary_content_upload(self, respx_mock: MockRouter, client: Gitpod) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + response = client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + + def test_binary_content_upload_with_iterator(self) -> None: + file_content = b"Hello, this is a test file." + counter = Counter() + iterator = _make_sync_iterator([file_content], counter=counter) + + def mock_handler(request: httpx.Request) -> httpx.Response: + assert counter.value == 0, "the request body should not have been read" + return httpx.Response(200, content=request.read()) + + with Gitpod( + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + http_client=httpx.Client(transport=MockTransport(handler=mock_handler)), + ) as client: + response = client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 + + @pytest.mark.respx(base_url=base_url) + def test_binary_content_upload_with_body_is_deprecated(self, respx_mock: MockRouter, client: Gitpod) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + with pytest.deprecated_call( + match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." + ): + response = client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + @pytest.mark.respx(base_url=base_url) def test_basic_union_response(self, respx_mock: MockRouter, client: Gitpod) -> None: class Model1(BaseModel): @@ -1364,6 +1481,72 @@ def test_multipart_repeating_array(self, async_client: AsyncGitpod) -> None: b"", ] + @pytest.mark.respx(base_url=base_url) + async def test_binary_content_upload(self, respx_mock: MockRouter, async_client: AsyncGitpod) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + response = await async_client.post( + "/upload", + content=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + + async def test_binary_content_upload_with_asynciterator(self) -> None: + file_content = b"Hello, this is a test file." + counter = Counter() + iterator = _make_async_iterator([file_content], counter=counter) + + async def mock_handler(request: httpx.Request) -> httpx.Response: + assert counter.value == 0, "the request body should not have been read" + return httpx.Response(200, content=await request.aread()) + + async with AsyncGitpod( + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + http_client=httpx.AsyncClient(transport=MockTransport(handler=mock_handler)), + ) as client: + response = await client.post( + "/upload", + content=iterator, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + assert counter.value == 1 + + @pytest.mark.respx(base_url=base_url) + async def test_binary_content_upload_with_body_is_deprecated( + self, respx_mock: MockRouter, async_client: AsyncGitpod + ) -> None: + respx_mock.post("/upload").mock(side_effect=mirror_request_content) + + file_content = b"Hello, this is a test file." + + with pytest.deprecated_call( + match="Passing raw bytes as `body` is deprecated and will be removed in a future version. Please pass raw bytes via the `content` parameter instead." + ): + response = await async_client.post( + "/upload", + body=file_content, + cast_to=httpx.Response, + options={"headers": {"Content-Type": "application/octet-stream"}}, + ) + + assert response.status_code == 200 + assert response.request.headers["Content-Type"] == "application/octet-stream" + assert response.content == file_content + @pytest.mark.respx(base_url=base_url) async def test_basic_union_response(self, respx_mock: MockRouter, async_client: AsyncGitpod) -> None: class Model1(BaseModel):