From 02a3ac402e5b07ea0efffaf6a35ea3740b800211 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 17 Dec 2025 12:11:07 +0000
Subject: [PATCH 1/5] feat(agent): add group-based SCM tools access control
---
.stats.yml | 8 ++---
api.md | 2 ++
groupmembership.go | 62 ++++++++++++++++++++++++++++++++++++++
groupmembership_test.go | 29 ++++++++++++++++++
organizationpolicy.go | 21 ++++++++-----
organizationpolicy_test.go | 7 +++--
project.go | 3 ++
project_test.go | 7 +++--
8 files changed, 122 insertions(+), 17 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 0fdb5b6..2b7ac98 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/api.md b/api.md
index 958a997..8b1f37f 100644
--- a/api.md
+++ b/api.md
@@ -316,11 +316,13 @@ Response Types:
- gitpod.GroupMembership
- gitpod.GroupMembershipNewResponse
+- gitpod.GroupMembershipGetResponse
- gitpod.GroupMembershipDeleteResponse
Methods:
- client.Groups.Memberships.New(ctx context.Context, body gitpod.GroupMembershipNewParams) (gitpod.GroupMembershipNewResponse, error)
+- client.Groups.Memberships.Get(ctx context.Context, body gitpod.GroupMembershipGetParams) (gitpod.GroupMembershipGetResponse, error)
- client.Groups.Memberships.List(ctx context.Context, params gitpod.GroupMembershipListParams) (pagination.MembersPage[gitpod.GroupMembership], error)
- client.Groups.Memberships.Delete(ctx context.Context, body gitpod.GroupMembershipDeleteParams) (gitpod.GroupMembershipDeleteResponse, error)
diff --git a/groupmembership.go b/groupmembership.go
index fc9d2c6..68a01c9 100644
--- a/groupmembership.go
+++ b/groupmembership.go
@@ -67,6 +67,36 @@ func (r *GroupMembershipService) New(ctx context.Context, body GroupMembershipNe
return
}
+// 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).
+func (r *GroupMembershipService) Get(ctx context.Context, body GroupMembershipGetParams, opts ...option.RequestOption) (res *GroupMembershipGetResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "gitpod.v1.GroupService/GetMembership"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
// Lists all memberships of a group.
//
// Use this method to:
@@ -216,6 +246,28 @@ func (r groupMembershipNewResponseJSON) RawJSON() string {
return r.raw
}
+type GroupMembershipGetResponse struct {
+ // The membership if found, nil if subject is not a member
+ Member GroupMembership `json:"member"`
+ JSON groupMembershipGetResponseJSON `json:"-"`
+}
+
+// groupMembershipGetResponseJSON contains the JSON metadata for the struct
+// [GroupMembershipGetResponse]
+type groupMembershipGetResponseJSON struct {
+ Member apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *GroupMembershipGetResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r groupMembershipGetResponseJSON) RawJSON() string {
+ return r.raw
+}
+
type GroupMembershipDeleteResponse = interface{}
type GroupMembershipNewParams struct {
@@ -228,6 +280,16 @@ func (r GroupMembershipNewParams) MarshalJSON() (data []byte, err error) {
return apijson.MarshalRoot(r)
}
+type GroupMembershipGetParams struct {
+ // Subject to check membership for
+ Subject param.Field[shared.SubjectParam] `json:"subject,required"`
+ GroupID param.Field[string] `json:"groupId" format:"uuid"`
+}
+
+func (r GroupMembershipGetParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
type GroupMembershipListParams struct {
Token param.Field[string] `query:"token"`
PageSize param.Field[int64] `query:"pageSize"`
diff --git a/groupmembership_test.go b/groupmembership_test.go
index 6206821..7977e02 100644
--- a/groupmembership_test.go
+++ b/groupmembership_test.go
@@ -43,6 +43,35 @@ func TestGroupMembershipNewWithOptionalParams(t *testing.T) {
}
}
+func TestGroupMembershipGetWithOptionalParams(t *testing.T) {
+ t.Skip("Prism tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := gitpod.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithBearerToken("My Bearer Token"),
+ )
+ _, err := client.Groups.Memberships.Get(context.TODO(), gitpod.GroupMembershipGetParams{
+ Subject: gitpod.F(shared.SubjectParam{
+ ID: gitpod.F("f53d2330-3795-4c5d-a1f3-453121af9c60"),
+ Principal: gitpod.F(shared.PrincipalUser),
+ }),
+ GroupID: gitpod.F("d2c94c27-3b76-4a42-b88c-95a85e392c68"),
+ })
+ if err != nil {
+ var apierr *gitpod.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
func TestGroupMembershipListWithOptionalParams(t *testing.T) {
t.Skip("Prism tests are disabled")
baseURL := "http://localhost:4010"
diff --git a/organizationpolicy.go b/organizationpolicy.go
index 99f95cb..1a71fff 100644
--- a/organizationpolicy.go
+++ b/organizationpolicy.go
@@ -106,17 +106,21 @@ type AgentPolicy struct {
McpDisabled bool `json:"mcpDisabled,required"`
// scm_tools_disabled controls whether SCM (Source Control Management) tools are
// disabled for agents
- ScmToolsDisabled bool `json:"scmToolsDisabled,required"`
- JSON agentPolicyJSON `json:"-"`
+ ScmToolsDisabled bool `json:"scmToolsDisabled,required"`
+ // 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).
+ ScmToolsAllowedGroupID string `json:"scmToolsAllowedGroupId"`
+ JSON agentPolicyJSON `json:"-"`
}
// agentPolicyJSON contains the JSON metadata for the struct [AgentPolicy]
type agentPolicyJSON struct {
- CommandDenyList apijson.Field
- McpDisabled apijson.Field
- ScmToolsDisabled apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+ CommandDenyList apijson.Field
+ McpDisabled apijson.Field
+ ScmToolsDisabled apijson.Field
+ ScmToolsAllowedGroupID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
}
func (r *AgentPolicy) UnmarshalJSON(data []byte) (err error) {
@@ -401,6 +405,9 @@ type OrganizationPolicyUpdateParamsAgentPolicy struct {
// mcp_disabled controls whether MCP (Model Context Protocol) is disabled for
// agents
McpDisabled param.Field[bool] `json:"mcpDisabled"`
+ // 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).
+ ScmToolsAllowedGroupID param.Field[string] `json:"scmToolsAllowedGroupId"`
// scm_tools_disabled controls whether SCM (Source Control Management) tools are
// disabled for agents
ScmToolsDisabled param.Field[bool] `json:"scmToolsDisabled"`
diff --git a/organizationpolicy_test.go b/organizationpolicy_test.go
index cea9261..386370a 100644
--- a/organizationpolicy_test.go
+++ b/organizationpolicy_test.go
@@ -54,9 +54,10 @@ func TestOrganizationPolicyUpdateWithOptionalParams(t *testing.T) {
_, err := client.Organizations.Policies.Update(context.TODO(), gitpod.OrganizationPolicyUpdateParams{
OrganizationID: gitpod.F("b0e12f6c-4c67-429d-a4a6-d9838b5da047"),
AgentPolicy: gitpod.F(gitpod.OrganizationPolicyUpdateParamsAgentPolicy{
- CommandDenyList: gitpod.F([]string{"string"}),
- McpDisabled: gitpod.F(true),
- ScmToolsDisabled: gitpod.F(true),
+ CommandDenyList: gitpod.F([]string{"string"}),
+ McpDisabled: gitpod.F(true),
+ ScmToolsAllowedGroupID: gitpod.F("scmToolsAllowedGroupId"),
+ ScmToolsDisabled: gitpod.F(true),
}),
AllowedEditorIDs: gitpod.F([]string{"string"}),
AllowLocalRunners: gitpod.F(true),
diff --git a/project.go b/project.go
index d152d8a..621884c 100644
--- a/project.go
+++ b/project.go
@@ -1055,6 +1055,9 @@ type ProjectListParamsFilter struct {
// runner_ids filters the response to only projects that use environment classes
// from these runners
RunnerIDs param.Field[[]string] `json:"runnerIds" format:"uuid"`
+ // runner_kinds filters the response to only projects that use environment classes
+ // from runners of these kinds
+ RunnerKinds param.Field[[]RunnerKind] `json:"runnerKinds"`
// search performs case-insensitive search across project name, project ID, and
// repository name
Search param.Field[string] `json:"search"`
diff --git a/project_test.go b/project_test.go
index c86a0d3..5c65cfc 100644
--- a/project_test.go
+++ b/project_test.go
@@ -171,9 +171,10 @@ func TestProjectListWithOptionalParams(t *testing.T) {
Token: gitpod.F("token"),
PageSize: gitpod.F(int64(0)),
Filter: gitpod.F(gitpod.ProjectListParamsFilter{
- ProjectIDs: gitpod.F([]string{"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"}),
- RunnerIDs: gitpod.F([]string{"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"}),
- Search: gitpod.F("search"),
+ ProjectIDs: gitpod.F([]string{"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"}),
+ RunnerIDs: gitpod.F([]string{"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"}),
+ RunnerKinds: gitpod.F([]gitpod.RunnerKind{gitpod.RunnerKindUnspecified}),
+ Search: gitpod.F("search"),
}),
Pagination: gitpod.F(gitpod.ProjectListParamsPagination{
Token: gitpod.F("token"),
From 2e9de50431b0d2ab64db8b7bbba3c83aedc7d74b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 17 Dec 2025 17:14:53 +0000
Subject: [PATCH 2/5] fix: skip usage tests that don't work with Prism
---
usage1_test.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/usage1_test.go b/usage1_test.go
index 6d6b8f3..f557b5e 100644
--- a/usage1_test.go
+++ b/usage1_test.go
@@ -24,6 +24,7 @@ func TestUsage(t *testing.T) {
option.WithBaseURL(baseURL),
option.WithBearerToken("My Bearer Token"),
)
+ t.Skip("Prism tests are disabled")
response, err := client.Identity.GetAuthenticatedIdentity(context.TODO(), gitpod.IdentityGetAuthenticatedIdentityParams{})
if err != nil {
t.Error(err)
From af1d69c695071e89c7ede111953b510914b6dff0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jes=C3=BAs=20Espino?=
Date: Fri, 19 Dec 2025 16:41:10 +0100
Subject: [PATCH 3/5] chore: pin GitHub Actions to SHA
---
.github/workflows/ci.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 846bc19..ee5b1f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,10 +20,10 @@ jobs:
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup go
- uses: actions/setup-go@v5
+ uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
with:
go-version-file: ./go.mod
@@ -35,10 +35,10 @@ jobs:
runs-on: ${{ github.repository == 'stainless-sdks/gitpod-go' && '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: Setup go
- uses: actions/setup-go@v5
+ uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
with:
go-version-file: ./go.mod
From 9d21ce0d9d368e05063f05d14845fab2bfa617f2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 19 Dec 2025 18:54:08 +0000
Subject: [PATCH 4/5] codegen metadata
---
.stats.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 2b7ac98..f59d5bf 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-a19818e87979929d5484f97ec50318899c659c73733b4a700a41f28687ee2632.yml
-openapi_spec_hash: f2d83905d1ed19d50c2f4641ecf29204
-config_hash: e84bdcd3fab4b185dd3dd79f70ea527d
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/gitpod%2Fgitpod-8b86b2ad546df57ba9b530cb8d31733d99c4b629bbcac61bc10775bbd577e6b4.yml
+openapi_spec_hash: 9d895493e3b1ad702e554d9e2b19e8bc
+config_hash: 8e1b089e9f5af438fd56b523014af4f2
From a46ea1b13f48686b8d86a9d4d3d8f127a7e53577 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 19 Dec 2025 18:54:24 +0000
Subject: [PATCH 5/5] release: 0.8.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 18 ++++++++++++++++++
README.md | 2 +-
internal/version.go | 2 +-
4 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 1b77f50..6538ca9 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.7.0"
+ ".": "0.8.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 484c1fe..d56477a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,23 @@
# Changelog
+## 0.8.0 (2025-12-19)
+
+Full Changelog: [v0.7.0...v0.8.0](https://github.com/gitpod-io/gitpod-sdk-go/compare/v0.7.0...v0.8.0)
+
+### Features
+
+* **agent:** add group-based SCM tools access control ([02a3ac4](https://github.com/gitpod-io/gitpod-sdk-go/commit/02a3ac402e5b07ea0efffaf6a35ea3740b800211))
+
+
+### Bug Fixes
+
+* skip usage tests that don't work with Prism ([2e9de50](https://github.com/gitpod-io/gitpod-sdk-go/commit/2e9de50431b0d2ab64db8b7bbba3c83aedc7d74b))
+
+
+### Chores
+
+* pin GitHub Actions to SHA ([af1d69c](https://github.com/gitpod-io/gitpod-sdk-go/commit/af1d69c695071e89c7ede111953b510914b6dff0))
+
## 0.7.0 (2025-12-15)
Full Changelog: [v0.6.1...v0.7.0](https://github.com/gitpod-io/gitpod-sdk-go/compare/v0.6.1...v0.7.0)
diff --git a/README.md b/README.md
index b88b96e..c5e3a37 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/gitpod-io/gitpod-sdk-go@v0.7.0'
+go get -u 'github.com/gitpod-io/gitpod-sdk-go@v0.8.0'
```
diff --git a/internal/version.go b/internal/version.go
index 79301ae..3c8392e 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.7.0" // x-release-please-version
+const PackageVersion = "0.8.0" // x-release-please-version