diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 800f691..8f3951d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,10 +19,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/gitpod-typescript' && '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: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' @@ -41,10 +41,10 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' @@ -57,7 +57,7 @@ jobs: - name: Get GitHub OIDC Token if: github.repository == 'stainless-sdks/gitpod-typescript' id: github-oidc - uses: actions/github-script@v6 + uses: actions/github-script@00f12e3e20659f42342b1c0226afda7f7c042325 # v6 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -74,10 +74,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/gitpod-typescript' && '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: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 7936e80..c95a4ba 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -23,10 +23,10 @@ jobs: id-token: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '24' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 742b303..6e13518 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'gitpod-io/gitpod-sdk-typescript' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 64f3cdd..76d5538 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.0" + ".": "0.9.0" } diff --git a/.stats.yml b/.stats.yml index 0fdb5b6..f59d5bf 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-8b86b2ad546df57ba9b530cb8d31733d99c4b629bbcac61bc10775bbd577e6b4.yml +openapi_spec_hash: 9d895493e3b1ad702e554d9e2b19e8bc +config_hash: 8e1b089e9f5af438fd56b523014af4f2 diff --git a/CHANGELOG.md b/CHANGELOG.md index f86e4aa..f5f4e52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.9.0 (2025-12-19) + +Full Changelog: [v0.8.0...v0.9.0](https://github.com/gitpod-io/gitpod-sdk-typescript/compare/v0.8.0...v0.9.0) + +### Features + +* **agent:** add group-based SCM tools access control ([9f8d2f9](https://github.com/gitpod-io/gitpod-sdk-typescript/commit/9f8d2f902fc221a89e27ae74e47315d6300f2af2)) + + +### Chores + +* pin GitHub Actions to SHA ([d29f17d](https://github.com/gitpod-io/gitpod-sdk-typescript/commit/d29f17de8d5cb9632525387669978058c18ba0a7)) + ## 0.8.0 (2025-12-15) Full Changelog: [v0.7.11...v0.8.0](https://github.com/gitpod-io/gitpod-sdk-typescript/compare/v0.7.11...v0.8.0) diff --git a/api.md b/api.md index 07e45cb..c15a29c 100644 --- a/api.md +++ b/api.md @@ -275,11 +275,13 @@ Types: - GroupMembership - MembershipCreateResponse +- MembershipRetrieveResponse - MembershipDeleteResponse Methods: - client.groups.memberships.create({ ...params }) -> MembershipCreateResponse +- client.groups.memberships.retrieve({ ...params }) -> MembershipRetrieveResponse - client.groups.memberships.list({ ...params }) -> GroupMembershipsMembersPage - client.groups.memberships.delete({ ...params }) -> unknown diff --git a/package.json b/package.json index d491c93..d42136d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gitpod/sdk", - "version": "0.8.0", + "version": "0.9.0", "description": "The official TypeScript library for the Gitpod API", "author": "Gitpod ", "types": "dist/index.d.ts", diff --git a/src/resources/groups/groups.ts b/src/resources/groups/groups.ts index 5c566bf..6c991f4 100644 --- a/src/resources/groups/groups.ts +++ b/src/resources/groups/groups.ts @@ -10,6 +10,8 @@ import { MembershipDeleteParams, MembershipDeleteResponse, MembershipListParams, + MembershipRetrieveParams, + MembershipRetrieveResponse, Memberships, } from './memberships'; import * as RoleAssignmentsAPI from './role-assignments'; @@ -528,9 +530,11 @@ export declare namespace Groups { Memberships as Memberships, type GroupMembership as GroupMembership, type MembershipCreateResponse as MembershipCreateResponse, + type MembershipRetrieveResponse as MembershipRetrieveResponse, type MembershipDeleteResponse as MembershipDeleteResponse, type GroupMembershipsMembersPage as GroupMembershipsMembersPage, type MembershipCreateParams as MembershipCreateParams, + type MembershipRetrieveParams as MembershipRetrieveParams, type MembershipListParams as MembershipListParams, type MembershipDeleteParams as MembershipDeleteParams, }; diff --git a/src/resources/groups/index.ts b/src/resources/groups/index.ts index 80bf45e..bdaec7e 100644 --- a/src/resources/groups/index.ts +++ b/src/resources/groups/index.ts @@ -18,8 +18,10 @@ export { Memberships, type GroupMembership, type MembershipCreateResponse, + type MembershipRetrieveResponse, type MembershipDeleteResponse, type MembershipCreateParams, + type MembershipRetrieveParams, type MembershipListParams, type MembershipDeleteParams, type GroupMembershipsMembersPage, diff --git a/src/resources/groups/memberships.ts b/src/resources/groups/memberships.ts index 097335a..20e0929 100644 --- a/src/resources/groups/memberships.ts +++ b/src/resources/groups/memberships.ts @@ -48,6 +48,48 @@ export class Memberships extends APIResource { return this._client.post('/gitpod.v1.GroupService/CreateMembership', { body, ...options }); } + /** + * 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). + * + * @example + * ```ts + * const membership = await client.groups.memberships.retrieve( + * { + * subject: { + * id: 'f53d2330-3795-4c5d-a1f3-453121af9c60', + * principal: 'PRINCIPAL_USER', + * }, + * groupId: 'd2c94c27-3b76-4a42-b88c-95a85e392c68', + * }, + * ); + * ``` + */ + retrieve(body: MembershipRetrieveParams, options?: RequestOptions): APIPromise { + return this._client.post('/gitpod.v1.GroupService/GetMembership', { body, ...options }); + } + /** * Lists all memberships of a group. * @@ -172,6 +214,13 @@ export interface MembershipCreateResponse { member?: GroupMembership; } +export interface MembershipRetrieveResponse { + /** + * The membership if found, nil if subject is not a member + */ + member?: GroupMembership; +} + /** * Empty response */ @@ -186,6 +235,15 @@ export interface MembershipCreateParams { subject?: Shared.Subject; } +export interface MembershipRetrieveParams { + /** + * Subject to check membership for + */ + subject: Shared.Subject; + + groupId?: string; +} + export interface MembershipListParams extends MembersPageParams { /** * Body param: @@ -228,9 +286,11 @@ export declare namespace Memberships { export { type GroupMembership as GroupMembership, type MembershipCreateResponse as MembershipCreateResponse, + type MembershipRetrieveResponse as MembershipRetrieveResponse, type MembershipDeleteResponse as MembershipDeleteResponse, type GroupMembershipsMembersPage as GroupMembershipsMembersPage, type MembershipCreateParams as MembershipCreateParams, + type MembershipRetrieveParams as MembershipRetrieveParams, type MembershipListParams as MembershipListParams, type MembershipDeleteParams as MembershipDeleteParams, }; diff --git a/src/resources/organizations/policies.ts b/src/resources/organizations/policies.ts index 86b9b7c..da14a6b 100644 --- a/src/resources/organizations/policies.ts +++ b/src/resources/organizations/policies.ts @@ -111,6 +111,12 @@ export interface AgentPolicy { * disabled for agents */ scmToolsDisabled: boolean; + + /** + * 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; } /** @@ -411,6 +417,12 @@ export namespace PolicyUpdateParams { */ mcpDisabled?: boolean | null; + /** + * 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 | null; + /** * scm_tools_disabled controls whether SCM (Source Control Management) tools are * disabled for agents diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index b7d4d83..139b882 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -23,6 +23,7 @@ import { ProjectPolicy, ProjectRole, } from './policies'; +import * as RunnersAPI from '../runners/runners'; import { APIPromise } from '../../core/api-promise'; import { PagePromise, ProjectsPage, type ProjectsPageParams } from '../../core/pagination'; import { RequestOptions } from '../../internal/request-options'; @@ -821,6 +822,12 @@ export namespace ProjectListParams { */ runnerIds?: Array; + /** + * runner_kinds filters the response to only projects that use environment classes + * from runners of these kinds + */ + runnerKinds?: Array; + /** * search performs case-insensitive search across project name, project ID, and * repository name diff --git a/src/version.ts b/src/version.ts index 23f967c..5c16194 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.8.0'; // x-release-please-version +export const VERSION = '0.9.0'; // x-release-please-version diff --git a/tests/api-resources/groups/memberships.test.ts b/tests/api-resources/groups/memberships.test.ts index 5a8f3cf..e28a932 100644 --- a/tests/api-resources/groups/memberships.test.ts +++ b/tests/api-resources/groups/memberships.test.ts @@ -20,6 +20,26 @@ describe('resource memberships', () => { expect(dataAndResponse.response).toBe(rawResponse); }); + // Prism tests are disabled + test.skip('retrieve: only required params', async () => { + const responsePromise = client.groups.memberships.retrieve({ subject: {} }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('retrieve: required and optional params', async () => { + const response = await client.groups.memberships.retrieve({ + subject: { id: 'f53d2330-3795-4c5d-a1f3-453121af9c60', principal: 'PRINCIPAL_USER' }, + groupId: 'd2c94c27-3b76-4a42-b88c-95a85e392c68', + }); + }); + // Prism tests are disabled test.skip('list', async () => { const responsePromise = client.groups.memberships.list({}); diff --git a/tests/api-resources/organizations/policies.test.ts b/tests/api-resources/organizations/policies.test.ts index fbbc3b8..609ca00 100644 --- a/tests/api-resources/organizations/policies.test.ts +++ b/tests/api-resources/organizations/policies.test.ts @@ -47,7 +47,12 @@ describe('resource policies', () => { test.skip('update: required and optional params', async () => { const response = await client.organizations.policies.update({ organizationId: 'b0e12f6c-4c67-429d-a4a6-d9838b5da047', - agentPolicy: { commandDenyList: ['string'], mcpDisabled: true, scmToolsDisabled: true }, + agentPolicy: { + commandDenyList: ['string'], + mcpDisabled: true, + scmToolsAllowedGroupId: 'scmToolsAllowedGroupId', + scmToolsDisabled: true, + }, allowedEditorIds: ['string'], allowLocalRunners: true, defaultEditorId: 'defaultEditorId',