diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d60bafb6..a69c2e7b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ 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@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Install Rye run: | @@ -44,7 +44,7 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/gitpod-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Install Rye run: | @@ -63,7 +63,7 @@ jobs: - name: Get GitHub OIDC Token if: github.repository == 'stainless-sdks/gitpod-python' id: github-oidc - uses: actions/github-script@v6 + uses: actions/github-script@00f12e3e20659f42342b1c0226afda7f7c042325 # v6 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -81,7 +81,7 @@ 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@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Install Rye run: | diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 483b8ded..3343ab60 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -17,10 +17,10 @@ jobs: id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Install Rye - uses: eifinger/setup-rye@v4 + uses: eifinger/setup-rye@c694239a43768373e87d0103d7f547027a23f3c8 # v4 with: version: '0.44.0' @@ -31,7 +31,7 @@ jobs: run: rye build --clean - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1 with: # No token needed! Trusted publishing handles authentication packages-dir: dist/ diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 383dd5a3..4208b5cb 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.2" + ".": "0.6.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 0fdb5b62..2b7ac984 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 159 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-d62ef4b9187c1f3d36f428abc4b31d8a09ffd36e93d39b8136c60c8f463c838e.yml -openapi_spec_hash: d7f01b6f24e88eb46d744ecd28061f26 -config_hash: 26e4a10dfc6ec809322e60d889d15414 +configured_endpoints: 160 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-a19818e87979929d5484f97ec50318899c659c73733b4a700a41f28687ee2632.yml +openapi_spec_hash: f2d83905d1ed19d50c2f4641ecf29204 +config_hash: e84bdcd3fab4b185dd3dd79f70ea527d diff --git a/CHANGELOG.md b/CHANGELOG.md index 0124d5c6..bc2c5e40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.6.0 (2025-12-19) + +Full Changelog: [v0.5.2...v0.6.0](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.5.2...v0.6.0) + +### Features + +* **agent:** add group-based SCM tools access control ([9e23e57](https://github.com/gitpod-io/gitpod-sdk-python/commit/9e23e576ea787296c10f7edbb2a20bd9c47f5a4b)) + + +### Bug Fixes + +* use async_to_httpx_files in patch method ([af8d708](https://github.com/gitpod-io/gitpod-sdk-python/commit/af8d70859c29a43ffd66f949bb70712491458c3d)) + + +### Chores + +* **internal:** codegen related update ([34dd0fe](https://github.com/gitpod-io/gitpod-sdk-python/commit/34dd0fe4f13576840288a518b7c7c70f8d39d8f4)) +* pin GitHub Actions to SHA ([36acefc](https://github.com/gitpod-io/gitpod-sdk-python/commit/36acefc6f9ab2cbbde739b885e0734a9f476115b)) + ## 0.5.2 (2025-12-16) Full Changelog: [v0.5.1...v0.5.2](https://github.com/gitpod-io/gitpod-sdk-python/compare/v0.5.1...v0.5.2) diff --git a/api.md b/api.md index 54769280..fc5a1570 100644 --- a/api.md +++ b/api.md @@ -281,12 +281,17 @@ Methods: Types: ```python -from gitpod.types.groups import GroupMembership, MembershipCreateResponse +from gitpod.types.groups import ( + GroupMembership, + MembershipCreateResponse, + MembershipRetrieveResponse, +) ``` Methods: - client.groups.memberships.create(\*\*params) -> MembershipCreateResponse +- client.groups.memberships.retrieve(\*\*params) -> MembershipRetrieveResponse - client.groups.memberships.list(\*\*params) -> SyncMembersPage[GroupMembership] - client.groups.memberships.delete(\*\*params) -> object diff --git a/pyproject.toml b/pyproject.toml index d864376a..6136eaf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "gitpod-sdk" -version = "0.5.2" +version = "0.6.0" description = "The official Python library for the gitpod API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/scripts/lint b/scripts/lint index 6a98ee4f..1b2951be 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,8 +4,13 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running lints" -rye run lint +if [ "$1" = "--fix" ]; then + echo "==> Running lints with --fix" + rye run fix:ruff +else + echo "==> Running lints" + rye run lint +fi echo "==> Making sure it imports" rye run python -c 'import gitpod' diff --git a/src/gitpod/_base_client.py b/src/gitpod/_base_client.py index a1f4ce1c..16139794 100644 --- a/src/gitpod/_base_client.py +++ b/src/gitpod/_base_client.py @@ -1774,7 +1774,7 @@ async def patch( options: RequestOptions = {}, ) -> ResponseT: opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + method="patch", url=path, json_data=body, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts) diff --git a/src/gitpod/_version.py b/src/gitpod/_version.py index de507a36..850eb95d 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.5.2" # x-release-please-version +__version__ = "0.6.0" # x-release-please-version diff --git a/src/gitpod/resources/groups/memberships.py b/src/gitpod/resources/groups/memberships.py index 11b07f11..9ccee3ce 100644 --- a/src/gitpod/resources/groups/memberships.py +++ b/src/gitpod/resources/groups/memberships.py @@ -16,10 +16,16 @@ ) from ...pagination import SyncMembersPage, AsyncMembersPage from ..._base_client import AsyncPaginator, make_request_options -from ...types.groups import membership_list_params, membership_create_params, membership_delete_params +from ...types.groups import ( + membership_list_params, + membership_create_params, + membership_delete_params, + membership_retrieve_params, +) from ...types.shared_params.subject import Subject from ...types.groups.group_membership import GroupMembership from ...types.groups.membership_create_response import MembershipCreateResponse +from ...types.groups.membership_retrieve_response import MembershipRetrieveResponse __all__ = ["MembershipsResource", "AsyncMembershipsResource"] @@ -108,6 +114,69 @@ def create( cast_to=MembershipCreateResponse, ) + def retrieve( + self, + *, + subject: Subject, + group_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, + ) -> MembershipRetrieveResponse: + """ + Gets a specific membership by group ID and subject. + + Use this method to: + + - Check if a user or service account is a member of a group + - Verify group membership for access control + + ### Examples + + - Check user membership: + + Checks if a user is a member of a specific group. + + ```yaml + groupId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + subject: + id: "f53d2330-3795-4c5d-a1f3-453121af9c60" + principal: PRINCIPAL_USER + ``` + + ### Authorization + + All organization members can check group membership (transparency model). + + Args: + subject: Subject to check membership 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.GroupService/GetMembership", + body=maybe_transform( + { + "subject": subject, + "group_id": group_id, + }, + membership_retrieve_params.MembershipRetrieveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MembershipRetrieveResponse, + ) + def list( self, *, @@ -323,6 +392,69 @@ async def create( cast_to=MembershipCreateResponse, ) + async def retrieve( + self, + *, + subject: Subject, + group_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, + ) -> MembershipRetrieveResponse: + """ + Gets a specific membership by group ID and subject. + + Use this method to: + + - Check if a user or service account is a member of a group + - Verify group membership for access control + + ### Examples + + - Check user membership: + + Checks if a user is a member of a specific group. + + ```yaml + groupId: "d2c94c27-3b76-4a42-b88c-95a85e392c68" + subject: + id: "f53d2330-3795-4c5d-a1f3-453121af9c60" + principal: PRINCIPAL_USER + ``` + + ### Authorization + + All organization members can check group membership (transparency model). + + Args: + subject: Subject to check membership 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.GroupService/GetMembership", + body=await async_maybe_transform( + { + "subject": subject, + "group_id": group_id, + }, + membership_retrieve_params.MembershipRetrieveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MembershipRetrieveResponse, + ) + def list( self, *, @@ -463,6 +595,9 @@ def __init__(self, memberships: MembershipsResource) -> None: self.create = to_raw_response_wrapper( memberships.create, ) + self.retrieve = to_raw_response_wrapper( + memberships.retrieve, + ) self.list = to_raw_response_wrapper( memberships.list, ) @@ -478,6 +613,9 @@ def __init__(self, memberships: AsyncMembershipsResource) -> None: self.create = async_to_raw_response_wrapper( memberships.create, ) + self.retrieve = async_to_raw_response_wrapper( + memberships.retrieve, + ) self.list = async_to_raw_response_wrapper( memberships.list, ) @@ -493,6 +631,9 @@ def __init__(self, memberships: MembershipsResource) -> None: self.create = to_streamed_response_wrapper( memberships.create, ) + self.retrieve = to_streamed_response_wrapper( + memberships.retrieve, + ) self.list = to_streamed_response_wrapper( memberships.list, ) @@ -508,6 +649,9 @@ def __init__(self, memberships: AsyncMembershipsResource) -> None: self.create = async_to_streamed_response_wrapper( memberships.create, ) + self.retrieve = async_to_streamed_response_wrapper( + memberships.retrieve, + ) self.list = async_to_streamed_response_wrapper( memberships.list, ) diff --git a/src/gitpod/types/groups/__init__.py b/src/gitpod/types/groups/__init__.py index f689e45d..abbe99fe 100644 --- a/src/gitpod/types/groups/__init__.py +++ b/src/gitpod/types/groups/__init__.py @@ -9,7 +9,9 @@ from .membership_create_params import MembershipCreateParams as MembershipCreateParams from .membership_delete_params import MembershipDeleteParams as MembershipDeleteParams from .membership_create_response import MembershipCreateResponse as MembershipCreateResponse +from .membership_retrieve_params import MembershipRetrieveParams as MembershipRetrieveParams from .role_assignment_list_params import RoleAssignmentListParams as RoleAssignmentListParams +from .membership_retrieve_response import MembershipRetrieveResponse as MembershipRetrieveResponse from .role_assignment_create_params import RoleAssignmentCreateParams as RoleAssignmentCreateParams from .role_assignment_delete_params import RoleAssignmentDeleteParams as RoleAssignmentDeleteParams from .role_assignment_create_response import RoleAssignmentCreateResponse as RoleAssignmentCreateResponse diff --git a/src/gitpod/types/groups/membership_retrieve_params.py b/src/gitpod/types/groups/membership_retrieve_params.py new file mode 100644 index 00000000..7934b5c8 --- /dev/null +++ b/src/gitpod/types/groups/membership_retrieve_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 +from ..shared_params.subject import Subject + +__all__ = ["MembershipRetrieveParams"] + + +class MembershipRetrieveParams(TypedDict, total=False): + subject: Required[Subject] + """Subject to check membership for""" + + group_id: Annotated[str, PropertyInfo(alias="groupId")] diff --git a/src/gitpod/types/groups/membership_retrieve_response.py b/src/gitpod/types/groups/membership_retrieve_response.py new file mode 100644 index 00000000..bfa92f8d --- /dev/null +++ b/src/gitpod/types/groups/membership_retrieve_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..._models import BaseModel +from .group_membership import GroupMembership + +__all__ = ["MembershipRetrieveResponse"] + + +class MembershipRetrieveResponse(BaseModel): + member: Optional[GroupMembership] = None + """The membership if found, nil if subject is not a member""" diff --git a/src/gitpod/types/organizations/agent_policy.py b/src/gitpod/types/organizations/agent_policy.py index 7f5e1de9..92827dd2 100644 --- a/src/gitpod/types/organizations/agent_policy.py +++ b/src/gitpod/types/organizations/agent_policy.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Optional from pydantic import Field as FieldInfo @@ -29,3 +29,9 @@ class AgentPolicy(BaseModel): scm_tools_disabled controls whether SCM (Source Control Management) tools are disabled for agents """ + + scm_tools_allowed_group_id: Optional[str] = FieldInfo(alias="scmToolsAllowedGroupId", default=None) + """ + scm_tools_allowed_group_id restricts SCM tools access to members of this group. + Empty means no restriction (all users can use SCM tools if not disabled). + """ diff --git a/src/gitpod/types/organizations/policy_update_params.py b/src/gitpod/types/organizations/policy_update_params.py index 50cfaae4..6c5f5ebb 100644 --- a/src/gitpod/types/organizations/policy_update_params.py +++ b/src/gitpod/types/organizations/policy_update_params.py @@ -131,6 +131,12 @@ class AgentPolicy(TypedDict, total=False): agents """ + scm_tools_allowed_group_id: Annotated[Optional[str], PropertyInfo(alias="scmToolsAllowedGroupId")] + """ + scm_tools_allowed_group_id restricts SCM tools access to members of this group. + Empty means no restriction (all users can use SCM tools if not disabled). + """ + scm_tools_disabled: Annotated[Optional[bool], PropertyInfo(alias="scmToolsDisabled")] """ scm_tools_disabled controls whether SCM (Source Control Management) tools are diff --git a/src/gitpod/types/project_list_params.py b/src/gitpod/types/project_list_params.py index ea25cc93..0ce45e83 100644 --- a/src/gitpod/types/project_list_params.py +++ b/src/gitpod/types/project_list_params.py @@ -2,10 +2,12 @@ from __future__ import annotations +from typing import List from typing_extensions import Annotated, TypedDict from .._types import SequenceNotStr from .._utils import PropertyInfo +from .runner_kind import RunnerKind __all__ = ["ProjectListParams", "Filter", "Pagination"] @@ -31,6 +33,12 @@ class Filter(TypedDict, total=False): from these runners """ + runner_kinds: Annotated[List[RunnerKind], PropertyInfo(alias="runnerKinds")] + """ + runner_kinds filters the response to only projects that use environment classes + from runners of these kinds + """ + search: str """ search performs case-insensitive search across project name, project ID, and diff --git a/tests/api_resources/groups/test_memberships.py b/tests/api_resources/groups/test_memberships.py index b0de9f54..88c7c32b 100644 --- a/tests/api_resources/groups/test_memberships.py +++ b/tests/api_resources/groups/test_memberships.py @@ -13,6 +13,7 @@ from gitpod.types.groups import ( GroupMembership, MembershipCreateResponse, + MembershipRetrieveResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -61,6 +62,52 @@ def test_streaming_response_create(self, client: Gitpod) -> None: 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: + membership = client.groups.memberships.retrieve( + subject={}, + ) + assert_matches_type(MembershipRetrieveResponse, membership, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve_with_all_params(self, client: Gitpod) -> None: + membership = client.groups.memberships.retrieve( + subject={ + "id": "f53d2330-3795-4c5d-a1f3-453121af9c60", + "principal": "PRINCIPAL_USER", + }, + group_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(MembershipRetrieveResponse, membership, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Gitpod) -> None: + response = client.groups.memberships.with_raw_response.retrieve( + subject={}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + membership = response.parse() + assert_matches_type(MembershipRetrieveResponse, membership, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Gitpod) -> None: + with client.groups.memberships.with_streaming_response.retrieve( + subject={}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + membership = response.parse() + assert_matches_type(MembershipRetrieveResponse, membership, 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: @@ -185,6 +232,52 @@ async def test_streaming_response_create(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_retrieve(self, async_client: AsyncGitpod) -> None: + membership = await async_client.groups.memberships.retrieve( + subject={}, + ) + assert_matches_type(MembershipRetrieveResponse, membership, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncGitpod) -> None: + membership = await async_client.groups.memberships.retrieve( + subject={ + "id": "f53d2330-3795-4c5d-a1f3-453121af9c60", + "principal": "PRINCIPAL_USER", + }, + group_id="d2c94c27-3b76-4a42-b88c-95a85e392c68", + ) + assert_matches_type(MembershipRetrieveResponse, membership, 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.groups.memberships.with_raw_response.retrieve( + subject={}, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + membership = await response.parse() + assert_matches_type(MembershipRetrieveResponse, membership, 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.groups.memberships.with_streaming_response.retrieve( + subject={}, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + membership = await response.parse() + assert_matches_type(MembershipRetrieveResponse, membership, 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: diff --git a/tests/api_resources/organizations/test_policies.py b/tests/api_resources/organizations/test_policies.py index 1d743341..eed1d45d 100644 --- a/tests/api_resources/organizations/test_policies.py +++ b/tests/api_resources/organizations/test_policies.py @@ -67,6 +67,7 @@ def test_method_update_with_all_params(self, client: Gitpod) -> None: agent_policy={ "command_deny_list": ["string"], "mcp_disabled": True, + "scm_tools_allowed_group_id": "scmToolsAllowedGroupId", "scm_tools_disabled": True, }, allowed_editor_ids=["string"], @@ -177,6 +178,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncGitpod) -> agent_policy={ "command_deny_list": ["string"], "mcp_disabled": True, + "scm_tools_allowed_group_id": "scmToolsAllowedGroupId", "scm_tools_disabled": True, }, allowed_editor_ids=["string"], diff --git a/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py index 0408e8a1..6acd6e18 100644 --- a/tests/api_resources/test_projects.py +++ b/tests/api_resources/test_projects.py @@ -210,6 +210,7 @@ def test_method_list_with_all_params(self, client: Gitpod) -> None: filter={ "project_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], "runner_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "runner_kinds": ["RUNNER_KIND_UNSPECIFIED"], "search": "search", }, pagination={ @@ -506,6 +507,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncGitpod) -> N filter={ "project_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], "runner_ids": ["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + "runner_kinds": ["RUNNER_KIND_UNSPECIFIED"], "search": "search", }, pagination={