diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6538ca9..6d78745 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.0" + ".": "0.9.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 592d8a4..cca37c7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 172 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-b97dcde84128bcf3740b0cf3c2c005e1dcd1cdac9b0768a28bd734f8d83c9fa2.yml -openapi_spec_hash: 1172889d2eb3f0453514c6caae3459b3 -config_hash: 49d499b8ab46cede0e3461ef7cd549ca +configured_endpoints: 175 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-8f6ee769411e2d21a2f437d49eb2f16880fcef0db52ac1985f2a3963af45f6a0.yml +openapi_spec_hash: 28f2d9d7e36f1f0ecd13052054449249 +config_hash: 3f1278a7a2a9285f57e81f148743e99e diff --git a/CHANGELOG.md b/CHANGELOG.md index b5584ae..b73455e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.9.0 (2026-02-11) + +Full Changelog: [v0.8.0...v0.9.0](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.8.0...v0.9.0) + +### Features + +* **api:** add bulk_create/bulk_delete/bulk_update methods to projects ([255bd90](https://github.com/gitpod-io/gitpod-sdk-python/commit/255bd90fadb010fbc75f2b38ec1e79b219cf06ef)) + ## 0.8.0 (2026-02-11) Full Changelog: [v0.7.0...v0.8.0](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.7.0...v0.8.0) diff --git a/api.md b/api.md index ce41da2..cd3547f 100644 --- a/api.md +++ b/api.md @@ -555,6 +555,9 @@ from gitpod.types import ( ProjectCreateResponse, ProjectRetrieveResponse, ProjectUpdateResponse, + ProjectBulkCreateResponse, + ProjectBulkDeleteResponse, + ProjectBulkUpdateResponse, ProjectCreateFromEnvironmentResponse, ) ``` @@ -566,6 +569,9 @@ Methods: - client.projects.update(\*\*params) -> ProjectUpdateResponse - client.projects.list(\*\*params) -> SyncProjectsPage[Project] - client.projects.delete(\*\*params) -> object +- client.projects.bulk_create(\*\*params) -> ProjectBulkCreateResponse +- client.projects.bulk_delete(\*\*params) -> ProjectBulkDeleteResponse +- client.projects.bulk_update(\*\*params) -> ProjectBulkUpdateResponse - client.projects.create_from_environment(\*\*params) -> ProjectCreateFromEnvironmentResponse ## EnvironmentClases diff --git a/pyproject.toml b/pyproject.toml index 6e89f84..bdf6bae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "gitpod-sdk" -version = "0.8.0" +version = "0.9.0" description = "The official Python library for the gitpod API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/gitpod/_version.py b/src/gitpod/_version.py index 58df503..b6b19f6 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.8.0" # x-release-please-version +__version__ = "0.9.0" # x-release-please-version diff --git a/src/gitpod/resources/projects/projects.py b/src/gitpod/resources/projects/projects.py index c3f7da6..ac2caee 100644 --- a/src/gitpod/resources/projects/projects.py +++ b/src/gitpod/resources/projects/projects.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Optional +from typing import Iterable, Optional import httpx @@ -12,9 +12,12 @@ project_delete_params, project_update_params, project_retrieve_params, + project_bulk_create_params, + project_bulk_delete_params, + project_bulk_update_params, project_create_from_environment_params, ) -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from .policies import ( PoliciesResource, @@ -47,6 +50,9 @@ from ...types.project_update_response import ProjectUpdateResponse from ...types.project_retrieve_response import ProjectRetrieveResponse from ...types.recommended_editors_param import RecommendedEditorsParam +from ...types.project_bulk_create_response import ProjectBulkCreateResponse +from ...types.project_bulk_delete_response import ProjectBulkDeleteResponse +from ...types.project_bulk_update_response import ProjectBulkUpdateResponse from ...types.environment_initializer_param import EnvironmentInitializerParam from ...types.project_prebuild_configuration_param import ProjectPrebuildConfigurationParam from ...types.project_create_from_environment_response import ProjectCreateFromEnvironmentResponse @@ -473,6 +479,172 @@ def delete( cast_to=object, ) + def bulk_create( + self, + *, + projects: Iterable[project_bulk_create_params.Project] | 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, + ) -> ProjectBulkCreateResponse: + """ + Creates multiple projects in a single request. + + Use this method to: + + - Onboard multiple repositories at once + - Import a batch of projects during initial setup + + Returns successfully created projects and details about any failures. Each + project in the request is processed independently — partial success is possible. + + ### Examples + + - Create multiple projects: + + Creates several projects in one request. + + ```yaml + projects: + - name: "Frontend" + initializer: + specs: + - git: + remoteUri: "https://github.com/org/frontend" + - name: "Backend" + initializer: + specs: + - git: + remoteUri: "https://github.com/org/backend" + ``` + + 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._post( + "/gitpod.v1.ProjectService/CreateProjects", + body=maybe_transform({"projects": projects}, project_bulk_create_params.ProjectBulkCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProjectBulkCreateResponse, + ) + + def bulk_delete( + self, + *, + project_ids: SequenceNotStr[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, + ) -> ProjectBulkDeleteResponse: + """ + Deletes multiple projects in a single request. + + Use this method to: + + - Remove multiple unused projects at once + - Clean up projects in batch + + Returns successfully deleted project IDs and details about any failures. Each + project in the request is processed independently — partial success is possible. + + ### Examples + + - Delete multiple projects: + + Permanently removes several projects in one request. + + ```yaml + projectIds: + - "b0e12f6c-4c67-429d-a4a6-d9838b5da047" + - "c1f23g7d-5d78-430e-b5b7-e0949c6eb158" + ``` + + 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._post( + "/gitpod.v1.ProjectService/DeleteProjects", + body=maybe_transform({"project_ids": project_ids}, project_bulk_delete_params.ProjectBulkDeleteParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProjectBulkDeleteResponse, + ) + + def bulk_update( + self, + *, + projects: Iterable[project_bulk_update_params.Project] | 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, + ) -> ProjectBulkUpdateResponse: + """ + Updates multiple projects in a single request. + + Use this method to: + + - Modify settings across multiple projects at once + - Apply configuration changes in batch + + Returns successfully updated projects and details about any failures. Each + project in the request is processed independently — partial success is possible. + + ### Examples + + - Update multiple projects: + + Updates several projects in one request. + + ```yaml + projects: + - projectId: "b0e12f6c-4c67-429d-a4a6-d9838b5da047" + name: "Updated Frontend" + - projectId: "c1f23g7d-5d78-430e-b5b7-e0949c6eb158" + name: "Updated Backend" + ``` + + 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._post( + "/gitpod.v1.ProjectService/UpdateProjects", + body=maybe_transform({"projects": projects}, project_bulk_update_params.ProjectBulkUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProjectBulkUpdateResponse, + ) + def create_from_environment( self, *, @@ -951,6 +1123,178 @@ async def delete( cast_to=object, ) + async def bulk_create( + self, + *, + projects: Iterable[project_bulk_create_params.Project] | 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, + ) -> ProjectBulkCreateResponse: + """ + Creates multiple projects in a single request. + + Use this method to: + + - Onboard multiple repositories at once + - Import a batch of projects during initial setup + + Returns successfully created projects and details about any failures. Each + project in the request is processed independently — partial success is possible. + + ### Examples + + - Create multiple projects: + + Creates several projects in one request. + + ```yaml + projects: + - name: "Frontend" + initializer: + specs: + - git: + remoteUri: "https://github.com/org/frontend" + - name: "Backend" + initializer: + specs: + - git: + remoteUri: "https://github.com/org/backend" + ``` + + 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 await self._post( + "/gitpod.v1.ProjectService/CreateProjects", + body=await async_maybe_transform( + {"projects": projects}, project_bulk_create_params.ProjectBulkCreateParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProjectBulkCreateResponse, + ) + + async def bulk_delete( + self, + *, + project_ids: SequenceNotStr[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, + ) -> ProjectBulkDeleteResponse: + """ + Deletes multiple projects in a single request. + + Use this method to: + + - Remove multiple unused projects at once + - Clean up projects in batch + + Returns successfully deleted project IDs and details about any failures. Each + project in the request is processed independently — partial success is possible. + + ### Examples + + - Delete multiple projects: + + Permanently removes several projects in one request. + + ```yaml + projectIds: + - "b0e12f6c-4c67-429d-a4a6-d9838b5da047" + - "c1f23g7d-5d78-430e-b5b7-e0949c6eb158" + ``` + + 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 await self._post( + "/gitpod.v1.ProjectService/DeleteProjects", + body=await async_maybe_transform( + {"project_ids": project_ids}, project_bulk_delete_params.ProjectBulkDeleteParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProjectBulkDeleteResponse, + ) + + async def bulk_update( + self, + *, + projects: Iterable[project_bulk_update_params.Project] | 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, + ) -> ProjectBulkUpdateResponse: + """ + Updates multiple projects in a single request. + + Use this method to: + + - Modify settings across multiple projects at once + - Apply configuration changes in batch + + Returns successfully updated projects and details about any failures. Each + project in the request is processed independently — partial success is possible. + + ### Examples + + - Update multiple projects: + + Updates several projects in one request. + + ```yaml + projects: + - projectId: "b0e12f6c-4c67-429d-a4a6-d9838b5da047" + name: "Updated Frontend" + - projectId: "c1f23g7d-5d78-430e-b5b7-e0949c6eb158" + name: "Updated Backend" + ``` + + 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 await self._post( + "/gitpod.v1.ProjectService/UpdateProjects", + body=await async_maybe_transform( + {"projects": projects}, project_bulk_update_params.ProjectBulkUpdateParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ProjectBulkUpdateResponse, + ) + async def create_from_environment( self, *, @@ -1029,6 +1373,15 @@ def __init__(self, projects: ProjectsResource) -> None: self.delete = to_raw_response_wrapper( projects.delete, ) + self.bulk_create = to_raw_response_wrapper( + projects.bulk_create, + ) + self.bulk_delete = to_raw_response_wrapper( + projects.bulk_delete, + ) + self.bulk_update = to_raw_response_wrapper( + projects.bulk_update, + ) self.create_from_environment = to_raw_response_wrapper( projects.create_from_environment, ) @@ -1061,6 +1414,15 @@ def __init__(self, projects: AsyncProjectsResource) -> None: self.delete = async_to_raw_response_wrapper( projects.delete, ) + self.bulk_create = async_to_raw_response_wrapper( + projects.bulk_create, + ) + self.bulk_delete = async_to_raw_response_wrapper( + projects.bulk_delete, + ) + self.bulk_update = async_to_raw_response_wrapper( + projects.bulk_update, + ) self.create_from_environment = async_to_raw_response_wrapper( projects.create_from_environment, ) @@ -1093,6 +1455,15 @@ def __init__(self, projects: ProjectsResource) -> None: self.delete = to_streamed_response_wrapper( projects.delete, ) + self.bulk_create = to_streamed_response_wrapper( + projects.bulk_create, + ) + self.bulk_delete = to_streamed_response_wrapper( + projects.bulk_delete, + ) + self.bulk_update = to_streamed_response_wrapper( + projects.bulk_update, + ) self.create_from_environment = to_streamed_response_wrapper( projects.create_from_environment, ) @@ -1125,6 +1496,15 @@ def __init__(self, projects: AsyncProjectsResource) -> None: self.delete = async_to_streamed_response_wrapper( projects.delete, ) + self.bulk_create = async_to_streamed_response_wrapper( + projects.bulk_create, + ) + self.bulk_delete = async_to_streamed_response_wrapper( + projects.bulk_delete, + ) + self.bulk_update = async_to_streamed_response_wrapper( + projects.bulk_update, + ) self.create_from_environment = async_to_streamed_response_wrapper( projects.create_from_environment, ) diff --git a/src/gitpod/types/__init__.py b/src/gitpod/types/__init__.py index b6f524e..05178ab 100644 --- a/src/gitpod/types/__init__.py +++ b/src/gitpod/types/__init__.py @@ -172,6 +172,9 @@ from .organization_join_response import OrganizationJoinResponse as OrganizationJoinResponse from .organization_update_params import OrganizationUpdateParams as OrganizationUpdateParams from .prebuild_retrieve_response import PrebuildRetrieveResponse as PrebuildRetrieveResponse +from .project_bulk_create_params import ProjectBulkCreateParams as ProjectBulkCreateParams +from .project_bulk_delete_params import ProjectBulkDeleteParams as ProjectBulkDeleteParams +from .project_bulk_update_params import ProjectBulkUpdateParams as ProjectBulkUpdateParams from .runner_configuration_param import RunnerConfigurationParam as RunnerConfigurationParam from .secret_update_value_params import SecretUpdateValueParams as SecretUpdateValueParams from .agent_stop_execution_params import AgentStopExecutionParams as AgentStopExecutionParams @@ -192,6 +195,9 @@ from .organization_retrieve_params import OrganizationRetrieveParams as OrganizationRetrieveParams from .organization_set_role_params import OrganizationSetRoleParams as OrganizationSetRoleParams from .organization_update_response import OrganizationUpdateResponse as OrganizationUpdateResponse +from .project_bulk_create_response import ProjectBulkCreateResponse as ProjectBulkCreateResponse +from .project_bulk_delete_response import ProjectBulkDeleteResponse as ProjectBulkDeleteResponse +from .project_bulk_update_response import ProjectBulkUpdateResponse as ProjectBulkUpdateResponse from .agent_delete_execution_params import AgentDeleteExecutionParams as AgentDeleteExecutionParams from .environment_initializer_param import EnvironmentInitializerParam as EnvironmentInitializerParam from .environment_retrieve_response import EnvironmentRetrieveResponse as EnvironmentRetrieveResponse diff --git a/src/gitpod/types/project_bulk_create_params.py b/src/gitpod/types/project_bulk_create_params.py new file mode 100644 index 0000000..5a7eea4 --- /dev/null +++ b/src/gitpod/types/project_bulk_create_params.py @@ -0,0 +1,55 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo +from .environment_initializer_param import EnvironmentInitializerParam +from .project_prebuild_configuration_param import ProjectPrebuildConfigurationParam + +__all__ = ["ProjectBulkCreateParams", "Project"] + + +class ProjectBulkCreateParams(TypedDict, total=False): + projects: Iterable[Project] + + +class Project(TypedDict, total=False): + initializer: Required[EnvironmentInitializerParam] + """initializer is the content initializer""" + + automations_file_path: Annotated[str, PropertyInfo(alias="automationsFilePath")] + """ + automations_file_path is the path to the automations file relative to the repo + root path must not be absolute (start with a /): + + ``` + this.matches('^$|^[^/].*') + ``` + """ + + devcontainer_file_path: Annotated[str, PropertyInfo(alias="devcontainerFilePath")] + """ + devcontainer_file_path is the path to the devcontainer file relative to the repo + root path must not be absolute (start with a /): + + ``` + this.matches('^$|^[^/].*') + ``` + """ + + name: str + + prebuild_configuration: Annotated[ProjectPrebuildConfigurationParam, PropertyInfo(alias="prebuildConfiguration")] + """ + prebuild_configuration defines how prebuilds are created for this project. If + not set, prebuilds are disabled for the project. + """ + + technical_description: Annotated[str, PropertyInfo(alias="technicalDescription")] + """ + technical_description is a detailed technical description of the project This + field is not returned by default in GetProject or ListProjects responses 8KB max + """ diff --git a/src/gitpod/types/project_bulk_create_response.py b/src/gitpod/types/project_bulk_create_response.py new file mode 100644 index 0000000..9da4397 --- /dev/null +++ b/src/gitpod/types/project_bulk_create_response.py @@ -0,0 +1,29 @@ +# 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 .project import Project +from .._models import BaseModel + +__all__ = ["ProjectBulkCreateResponse", "FailedProject"] + + +class FailedProject(BaseModel): + error: Optional[str] = None + """error describes why the project creation failed""" + + index: Optional[int] = None + """index is the position in the request array (0-based)""" + + name: Optional[str] = None + """name is the project name that failed""" + + +class ProjectBulkCreateResponse(BaseModel): + created_projects: Optional[List[Project]] = FieldInfo(alias="createdProjects", default=None) + """created_projects contains the successfully created projects""" + + failed_projects: Optional[List[FailedProject]] = FieldInfo(alias="failedProjects", default=None) + """failed_projects contains details about projects that failed to create""" diff --git a/src/gitpod/types/project_bulk_delete_params.py b/src/gitpod/types/project_bulk_delete_params.py new file mode 100644 index 0000000..9a28eff --- /dev/null +++ b/src/gitpod/types/project_bulk_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 Annotated, TypedDict + +from .._types import SequenceNotStr +from .._utils import PropertyInfo + +__all__ = ["ProjectBulkDeleteParams"] + + +class ProjectBulkDeleteParams(TypedDict, total=False): + project_ids: Annotated[SequenceNotStr[str], PropertyInfo(alias="projectIds")] diff --git a/src/gitpod/types/project_bulk_delete_response.py b/src/gitpod/types/project_bulk_delete_response.py new file mode 100644 index 0000000..f419601 --- /dev/null +++ b/src/gitpod/types/project_bulk_delete_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__ = ["ProjectBulkDeleteResponse", "FailedProject"] + + +class FailedProject(BaseModel): + error: Optional[str] = None + """error describes why the project deletion failed""" + + index: Optional[int] = None + """index is the position in the request array (0-based)""" + + project_id: Optional[str] = FieldInfo(alias="projectId", default=None) + """project_id is the project ID that failed""" + + +class ProjectBulkDeleteResponse(BaseModel): + deleted_project_ids: Optional[List[str]] = FieldInfo(alias="deletedProjectIds", default=None) + """deleted_project_ids contains the IDs of successfully deleted projects""" + + failed_projects: Optional[List[FailedProject]] = FieldInfo(alias="failedProjects", default=None) + """failed_projects contains details about projects that failed to delete""" diff --git a/src/gitpod/types/project_bulk_update_params.py b/src/gitpod/types/project_bulk_update_params.py new file mode 100644 index 0000000..255cb11 --- /dev/null +++ b/src/gitpod/types/project_bulk_update_params.py @@ -0,0 +1,69 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable, Optional +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo +from .recommended_editors_param import RecommendedEditorsParam +from .environment_initializer_param import EnvironmentInitializerParam +from .project_prebuild_configuration_param import ProjectPrebuildConfigurationParam + +__all__ = ["ProjectBulkUpdateParams", "Project"] + + +class ProjectBulkUpdateParams(TypedDict, total=False): + projects: Iterable[Project] + + +class Project(TypedDict, total=False): + automations_file_path: Annotated[Optional[str], PropertyInfo(alias="automationsFilePath")] + """ + automations_file_path is the path to the automations file relative to the repo + root path must not be absolute (start with a /): + + ``` + this.matches('^$|^[^/].*') + ``` + """ + + devcontainer_file_path: Annotated[Optional[str], PropertyInfo(alias="devcontainerFilePath")] + """ + devcontainer_file_path is the path to the devcontainer file relative to the repo + root path must not be absolute (start with a /): + + ``` + this.matches('^$|^[^/].*') + ``` + """ + + initializer: Optional[EnvironmentInitializerParam] + """initializer is the content initializer""" + + name: Optional[str] + + prebuild_configuration: Annotated[ + Optional[ProjectPrebuildConfigurationParam], PropertyInfo(alias="prebuildConfiguration") + ] + """ + prebuild_configuration defines how prebuilds are created for this project. If + not provided, the existing prebuild configuration is not modified. To disable + prebuilds, set enabled to false. + """ + + project_id: Annotated[str, PropertyInfo(alias="projectId")] + """project_id specifies the project identifier""" + + recommended_editors: Annotated[Optional[RecommendedEditorsParam], PropertyInfo(alias="recommendedEditors")] + """ + recommended_editors specifies the editors recommended for this project. If not + provided, the existing recommended editors are not modified. To clear all + recommended editors, set to an empty RecommendedEditors message. + """ + + technical_description: Annotated[Optional[str], PropertyInfo(alias="technicalDescription")] + """ + technical_description is a detailed technical description of the project This + field is not returned by default in GetProject or ListProjects responses 8KB max + """ diff --git a/src/gitpod/types/project_bulk_update_response.py b/src/gitpod/types/project_bulk_update_response.py new file mode 100644 index 0000000..c8a3f26 --- /dev/null +++ b/src/gitpod/types/project_bulk_update_response.py @@ -0,0 +1,29 @@ +# 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 .project import Project +from .._models import BaseModel + +__all__ = ["ProjectBulkUpdateResponse", "FailedProject"] + + +class FailedProject(BaseModel): + error: Optional[str] = None + """error describes why the project update failed""" + + index: Optional[int] = None + """index is the position in the request array (0-based)""" + + project_id: Optional[str] = FieldInfo(alias="projectId", default=None) + """project_id is the project ID that failed""" + + +class ProjectBulkUpdateResponse(BaseModel): + failed_projects: Optional[List[FailedProject]] = FieldInfo(alias="failedProjects", default=None) + """failed_projects contains details about projects that failed to update""" + + updated_projects: Optional[List[Project]] = FieldInfo(alias="updatedProjects", default=None) + """updated_projects contains the successfully updated projects""" diff --git a/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py index 8e3985a..b51a14b 100644 --- a/tests/api_resources/test_projects.py +++ b/tests/api_resources/test_projects.py @@ -14,6 +14,9 @@ ProjectCreateResponse, ProjectUpdateResponse, ProjectRetrieveResponse, + ProjectBulkCreateResponse, + ProjectBulkDeleteResponse, + ProjectBulkUpdateResponse, ProjectCreateFromEnvironmentResponse, ) from gitpod.pagination import SyncProjectsPage, AsyncProjectsPage @@ -279,6 +282,244 @@ def test_streaming_response_delete(self, client: Gitpod) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_bulk_create(self, client: Gitpod) -> None: + project = client.projects.bulk_create() + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_bulk_create_with_all_params(self, client: Gitpod) -> None: + project = client.projects.bulk_create( + projects=[ + { + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "https://github.com/org/frontend", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "name": "Frontend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "technical_description": "technicalDescription", + }, + { + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "https://github.com/org/backend", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "name": "Backend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "technical_description": "technicalDescription", + }, + ], + ) + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_bulk_create(self, client: Gitpod) -> None: + response = client.projects.with_raw_response.bulk_create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + project = response.parse() + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_bulk_create(self, client: Gitpod) -> None: + with client.projects.with_streaming_response.bulk_create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + project = response.parse() + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_bulk_delete(self, client: Gitpod) -> None: + project = client.projects.bulk_delete() + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_bulk_delete_with_all_params(self, client: Gitpod) -> None: + project = client.projects.bulk_delete( + project_ids=["b0e12f6c-4c67-429d-a4a6-d9838b5da047", "c1f23g7d-5d78-430e-b5b7-e0949c6eb158"], + ) + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_bulk_delete(self, client: Gitpod) -> None: + response = client.projects.with_raw_response.bulk_delete() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + project = response.parse() + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_bulk_delete(self, client: Gitpod) -> None: + with client.projects.with_streaming_response.bulk_delete() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + project = response.parse() + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_bulk_update(self, client: Gitpod) -> None: + project = client.projects.bulk_update() + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_bulk_update_with_all_params(self, client: Gitpod) -> None: + project = client.projects.bulk_update( + projects=[ + { + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "remoteUri", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "name": "Updated Frontend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "project_id": "b0e12f6c-4c67-429d-a4a6-d9838b5da047", + "recommended_editors": {"editors": {"foo": {"versions": ["string"]}}}, + "technical_description": "technicalDescription", + }, + { + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "remoteUri", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "name": "Updated Backend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "project_id": "c1f23g7d-5d78-430e-b5b7-e0949c6eb158", + "recommended_editors": {"editors": {"foo": {"versions": ["string"]}}}, + "technical_description": "technicalDescription", + }, + ], + ) + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_bulk_update(self, client: Gitpod) -> None: + response = client.projects.with_raw_response.bulk_update() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + project = response.parse() + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_bulk_update(self, client: Gitpod) -> None: + with client.projects.with_streaming_response.bulk_update() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + project = response.parse() + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create_from_environment(self, client: Gitpod) -> None: @@ -577,6 +818,244 @@ async def test_streaming_response_delete(self, async_client: AsyncGitpod) -> Non assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_bulk_create(self, async_client: AsyncGitpod) -> None: + project = await async_client.projects.bulk_create() + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_bulk_create_with_all_params(self, async_client: AsyncGitpod) -> None: + project = await async_client.projects.bulk_create( + projects=[ + { + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "https://github.com/org/frontend", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "name": "Frontend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "technical_description": "technicalDescription", + }, + { + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "https://github.com/org/backend", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "name": "Backend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "technical_description": "technicalDescription", + }, + ], + ) + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_bulk_create(self, async_client: AsyncGitpod) -> None: + response = await async_client.projects.with_raw_response.bulk_create() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + project = await response.parse() + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_bulk_create(self, async_client: AsyncGitpod) -> None: + async with async_client.projects.with_streaming_response.bulk_create() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + project = await response.parse() + assert_matches_type(ProjectBulkCreateResponse, project, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_bulk_delete(self, async_client: AsyncGitpod) -> None: + project = await async_client.projects.bulk_delete() + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_bulk_delete_with_all_params(self, async_client: AsyncGitpod) -> None: + project = await async_client.projects.bulk_delete( + project_ids=["b0e12f6c-4c67-429d-a4a6-d9838b5da047", "c1f23g7d-5d78-430e-b5b7-e0949c6eb158"], + ) + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_bulk_delete(self, async_client: AsyncGitpod) -> None: + response = await async_client.projects.with_raw_response.bulk_delete() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + project = await response.parse() + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_bulk_delete(self, async_client: AsyncGitpod) -> None: + async with async_client.projects.with_streaming_response.bulk_delete() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + project = await response.parse() + assert_matches_type(ProjectBulkDeleteResponse, project, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_bulk_update(self, async_client: AsyncGitpod) -> None: + project = await async_client.projects.bulk_update() + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_bulk_update_with_all_params(self, async_client: AsyncGitpod) -> None: + project = await async_client.projects.bulk_update( + projects=[ + { + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "remoteUri", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "name": "Updated Frontend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "project_id": "b0e12f6c-4c67-429d-a4a6-d9838b5da047", + "recommended_editors": {"editors": {"foo": {"versions": ["string"]}}}, + "technical_description": "technicalDescription", + }, + { + "automations_file_path": "automationsFilePath", + "devcontainer_file_path": "devcontainerFilePath", + "initializer": { + "specs": [ + { + "context_url": {"url": "https://example.com"}, + "git": { + "checkout_location": "checkoutLocation", + "clone_target": "cloneTarget", + "remote_uri": "remoteUri", + "target_mode": "CLONE_TARGET_MODE_UNSPECIFIED", + "upstream_remote_uri": "upstreamRemoteUri", + }, + } + ] + }, + "name": "Updated Backend", + "prebuild_configuration": { + "enabled": True, + "enable_jetbrains_warmup": True, + "environment_class_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "executor": { + "id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "principal": "PRINCIPAL_UNSPECIFIED", + }, + "timeout": "+9125115.360s", + "trigger": {"daily_schedule": {"hour_utc": 23}}, + }, + "project_id": "c1f23g7d-5d78-430e-b5b7-e0949c6eb158", + "recommended_editors": {"editors": {"foo": {"versions": ["string"]}}}, + "technical_description": "technicalDescription", + }, + ], + ) + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_bulk_update(self, async_client: AsyncGitpod) -> None: + response = await async_client.projects.with_raw_response.bulk_update() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + project = await response.parse() + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_bulk_update(self, async_client: AsyncGitpod) -> None: + async with async_client.projects.with_streaming_response.bulk_update() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + project = await response.parse() + assert_matches_type(ProjectBulkUpdateResponse, project, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create_from_environment(self, async_client: AsyncGitpod) -> None: