Skip to content

Commit 9b9aa67

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add partial hierarchy selection to team sync endpoints (#3591)
Co-authored-by: ci.datadog-api-spec <packages@datadoghq.com>
1 parent 79a5e22 commit 9b9aa67

File tree

16 files changed

+361
-47
lines changed

16 files changed

+361
-47
lines changed

.generator/schemas/v2/openapi.yaml

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65885,6 +65885,8 @@ components:
6588565885
properties:
6588665886
frequency:
6588765887
$ref: "#/components/schemas/TeamSyncAttributesFrequency"
65888+
selection_state:
65889+
$ref: "#/components/schemas/TeamSyncAttributesSelectionState"
6588865890
source:
6588965891
$ref: "#/components/schemas/TeamSyncAttributesSource"
6589065892
sync_membership:
@@ -65907,6 +65909,14 @@ components:
6590765909
- ONCE
6590865910
- CONTINUOUSLY
6590965911
- PAUSED
65912+
TeamSyncAttributesSelectionState:
65913+
description: |-
65914+
Specifies which teams or organizations to sync. When
65915+
provided, synchronization is limited to the specified
65916+
items and their subtrees.
65917+
items:
65918+
$ref: "#/components/schemas/TeamSyncSelectionStateItem"
65919+
type: array
6591065920
TeamSyncAttributesSource:
6591165921
description: The external source platform for team synchronization. Only "github" is supported.
6591265922
enum:
@@ -65916,6 +65926,7 @@ components:
6591665926
x-enum-varnames:
6591765927
- GITHUB
6591865928
TeamSyncAttributesSyncMembership:
65929+
default: false
6591965930
description: Whether to sync members from the external team to the Datadog team. Defaults to `false` when not provided.
6592065931
example: true
6592165932
type: boolean
@@ -65975,6 +65986,72 @@ components:
6597565986
$ref: "#/components/schemas/TeamSyncData"
6597665987
type: array
6597765988
type: object
65989+
TeamSyncSelectionStateExternalId:
65990+
description: The external identifier for a team or organization in the source platform.
65991+
properties:
65992+
type:
65993+
$ref: "#/components/schemas/TeamSyncSelectionStateExternalIdType"
65994+
value:
65995+
$ref: "#/components/schemas/TeamSyncSelectionStateExternalIdValue"
65996+
required:
65997+
- type
65998+
- value
65999+
type: object
66000+
TeamSyncSelectionStateExternalIdType:
66001+
description: |-
66002+
The type of external identifier for the selection state item.
66003+
For GitHub synchronization, the allowed values are `team` and
66004+
`organization`.
66005+
enum:
66006+
- team
66007+
- organization
66008+
example: team
66009+
type: string
66010+
x-enum-varnames:
66011+
- TEAM
66012+
- ORGANIZATION
66013+
TeamSyncSelectionStateExternalIdValue:
66014+
description: |-
66015+
The external identifier value from the source
66016+
platform. For GitHub, this is the string
66017+
representation of a GitHub organization ID or team
66018+
ID.
66019+
example: "1"
66020+
type: string
66021+
TeamSyncSelectionStateItem:
66022+
description: Identifies a team or organization hierarchy to include in synchronization.
66023+
properties:
66024+
external_id:
66025+
$ref: "#/components/schemas/TeamSyncSelectionStateExternalId"
66026+
operation:
66027+
$ref: "#/components/schemas/TeamSyncSelectionStateOperation"
66028+
scope:
66029+
$ref: "#/components/schemas/TeamSyncSelectionStateScope"
66030+
required:
66031+
- external_id
66032+
type: object
66033+
TeamSyncSelectionStateOperation:
66034+
description: |-
66035+
The operation to perform on the selected hierarchy.
66036+
When set to `include`, synchronization covers the
66037+
referenced teams or organizations.
66038+
enum:
66039+
- include
66040+
example: include
66041+
type: string
66042+
x-enum-varnames:
66043+
- INCLUDE
66044+
TeamSyncSelectionStateScope:
66045+
description: |-
66046+
The scope of the selection. When set to `subtree`,
66047+
synchronization includes the referenced team or
66048+
organization and everything nested under it.
66049+
enum:
66050+
- subtree
66051+
example: subtree
66052+
type: string
66053+
x-enum-varnames:
66054+
- SUBTREE
6597866055
TeamTarget:
6597966056
description: "Represents a team target for an escalation policy step, including the team's ID and resource type."
6598066057
properties:
@@ -105434,12 +105511,6 @@ paths:
105434105511
description: OK
105435105512
"403":
105436105513
$ref: "#/components/responses/ForbiddenResponse"
105437-
"404":
105438-
content:
105439-
application/json:
105440-
schema:
105441-
$ref: "#/components/schemas/APIErrorResponse"
105442-
description: Team sync configurations not found
105443105514
"429":
105444105515
$ref: "#/components/responses/TooManyRequestsResponse"
105445105516
security:
@@ -105456,13 +105527,17 @@ paths:
105456105527
- teams_read
105457105528
post:
105458105529
description: |-
105459-
This endpoint attempts to link your existing Datadog teams with GitHub teams by matching their names.
105530+
This endpoint configures synchronization between your existing Datadog teams and GitHub teams by matching their names.
105460105531
It evaluates all current Datadog teams and compares them against teams in the GitHub organization
105461105532
connected to your Datadog account, based on Datadog Team handle and GitHub Team slug
105462105533
(lowercased and kebab-cased).
105463105534

105464105535
This operation is read-only on the GitHub side, no teams will be modified or created.
105465105536

105537+
Optionally, provide `selection_state` to limit synchronization
105538+
to specific teams or organizations and their subtrees, instead
105539+
of syncing all teams.
105540+
105466105541
[A GitHub organization must be connected to your Datadog account](https://docs.datadoghq.com/integrations/github/),
105467105542
and the GitHub App integrated with Datadog must have the `Members Read` permission. Matching is performed by comparing the Datadog team handle to the GitHub team slug
105468105543
using a normalized exact match; case is ignored and spaces are removed. No modifications are made
@@ -105477,6 +105552,8 @@ paths:
105477105552
responses:
105478105553
"200":
105479105554
description: OK
105555+
"204":
105556+
description: No Content
105480105557
"403":
105481105558
$ref: "#/components/responses/ForbiddenResponse"
105482105559
"429":
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"2026-03-04T16:01:00.945Z"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"log": {
3+
"_recordingName": "Teams/Get team sync configurations returns \"OK\" response",
4+
"creator": {
5+
"comment": "persister:fs",
6+
"name": "Polly.JS",
7+
"version": "6.0.5"
8+
},
9+
"entries": [
10+
{
11+
"_id": "9340a9d9b12be8261e72ba1bbc945a32",
12+
"_order": 0,
13+
"cache": {},
14+
"request": {
15+
"bodySize": 0,
16+
"cookies": [],
17+
"headers": [
18+
{
19+
"_fromType": "array",
20+
"name": "accept",
21+
"value": "application/json"
22+
}
23+
],
24+
"headersSize": 521,
25+
"httpVersion": "HTTP/1.1",
26+
"method": "GET",
27+
"queryString": [
28+
{
29+
"name": "filter",
30+
"value": {
31+
"source": "github"
32+
}
33+
}
34+
],
35+
"url": "https://api.datadoghq.com/api/v2/team/sync?filter%5Bsource%5D=github"
36+
},
37+
"response": {
38+
"bodySize": 282,
39+
"content": {
40+
"mimeType": "application/vnd.api+json",
41+
"size": 282,
42+
"text": "{\"data\":[{\"id\":\"3d33cc55-aea4-4801-bb75-139d347298c9\",\"type\":\"team_sync_bulk\",\"attributes\":{\"frequency\":\"once\",\"selection_state\":[{\"external_id\":{\"type\":\"organization\",\"value\":\"1\"},\"operation\":\"include\",\"scope\":\"subtree\"}],\"source\":\"github\",\"sync_membership\":false,\"type\":\"link\"}}]}"
43+
},
44+
"cookies": [],
45+
"headers": [
46+
{
47+
"name": "content-type",
48+
"value": "application/vnd.api+json"
49+
}
50+
],
51+
"headersSize": 659,
52+
"httpVersion": "HTTP/1.1",
53+
"redirectURL": "",
54+
"status": 200,
55+
"statusText": "OK"
56+
},
57+
"startedDateTime": "2026-03-04T16:01:00.949Z",
58+
"time": 322
59+
}
60+
],
61+
"pages": [],
62+
"version": "1.2"
63+
}
64+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"2026-03-04T16:01:34.366Z"

cassettes/v2/Teams_3116892301/Sync-teams-returns-OK-response_3488879418/recording.har renamed to cassettes/v2/Teams_3116892301/Link-Teams-with-GitHub-Teams-returns-No-Content-response_3413215892/recording.har

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
{
22
"log": {
3-
"_recordingName": "Teams/Sync teams returns \"OK\" response",
3+
"_recordingName": "Teams/Link Teams with GitHub Teams returns \"No Content\" response",
44
"creator": {
55
"comment": "persister:fs",
66
"name": "Polly.JS",
77
"version": "6.0.5"
88
},
99
"entries": [
1010
{
11-
"_id": "394163072f49be157e109223981e6839",
11+
"_id": "56fda770a3895f0797c8e26a49e8311d",
1212
"_order": 0,
1313
"cache": {},
1414
"request": {
15-
"bodySize": 81,
15+
"bodySize": 153,
1616
"cookies": [],
1717
"headers": [
1818
{
@@ -26,13 +26,13 @@
2626
"value": "application/json"
2727
}
2828
],
29-
"headersSize": 535,
29+
"headersSize": 534,
3030
"httpVersion": "HTTP/1.1",
3131
"method": "POST",
3232
"postData": {
3333
"mimeType": "application/json",
3434
"params": [],
35-
"text": "{\"data\":{\"attributes\":{\"source\":\"github\",\"type\":\"link\"},\"type\":\"team_sync_bulk\"}}"
35+
"text": "{\"data\":{\"attributes\":{\"selection_state\":[{\"external_id\":{\"type\":\"organization\",\"value\":\"1\"}}],\"source\":\"github\",\"type\":\"link\"},\"type\":\"team_sync_bulk\"}}"
3636
},
3737
"queryString": [],
3838
"url": "https://api.datadoghq.com/api/v2/team/sync"
@@ -44,20 +44,15 @@
4444
"size": 0
4545
},
4646
"cookies": [],
47-
"headers": [
48-
{
49-
"name": "content-type",
50-
"value": "text/plain"
51-
}
52-
],
53-
"headersSize": 653,
47+
"headers": [],
48+
"headersSize": 594,
5449
"httpVersion": "HTTP/1.1",
5550
"redirectURL": "",
56-
"status": 200,
57-
"statusText": "OK"
51+
"status": 204,
52+
"statusText": "No Content"
5853
},
59-
"startedDateTime": "2025-08-15T17:48:19.717Z",
60-
"time": 203
54+
"startedDateTime": "2026-03-04T16:01:34.369Z",
55+
"time": 563
6156
}
6257
],
6358
"pages": [],

cassettes/v2/Teams_3116892301/Sync-teams-returns-OK-response_3488879418/frozen.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

features/v2/teams.feature

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -431,20 +431,13 @@ Feature: Teams
431431
Then the response status is 200 OK
432432
And the response "data" has length 1
433433

434-
@generated @skip @team:DataDog/aaa-omg
434+
@team:DataDog/aaa-omg
435435
Scenario: Get team sync configurations returns "OK" response
436436
Given new "GetTeamSync" request
437-
And request contains "filter[source]" parameter from "REPLACE.ME"
437+
And request contains "filter[source]" parameter with value "github"
438438
When the request is sent
439439
Then the response status is 200 OK
440440

441-
@generated @skip @team:DataDog/aaa-omg
442-
Scenario: Get team sync configurations returns "Team sync configurations not found" response
443-
Given new "GetTeamSync" request
444-
And request contains "filter[source]" parameter from "REPLACE.ME"
445-
When the request is sent
446-
Then the response status is 404 Team sync configurations not found
447-
448441
@generated @skip @team:DataDog/aaa-omg
449442
Scenario: Get user memberships returns "API error response." response
450443
Given new "GetUserMemberships" request
@@ -461,6 +454,13 @@ Feature: Teams
461454
Then the response status is 200 Represents a user's association to a team
462455
And the response "data" has length 0
463456

457+
@team:DataDog/aaa-omg
458+
Scenario: Link Teams with GitHub Teams returns "No Content" response
459+
Given new "SyncTeams" request
460+
And body with value {"data": {"attributes": {"source": "github", "type": "link", "selection_state": [{"external_id": {"type": "organization", "value": "1"}}]}, "type": "team_sync_bulk"}}
461+
When the request is sent
462+
Then the response status is 204 No Content
463+
464464
@generated @skip @team:DataDog/aaa-omg
465465
Scenario: Link Teams with GitHub Teams returns "OK" response
466466
Given new "SyncTeams" request
@@ -582,13 +582,6 @@ Feature: Teams
582582
When the request is sent
583583
Then the response status is 204 No Content
584584

585-
@replay-only @team:DataDog/aaa-omg
586-
Scenario: Sync teams returns "OK" response
587-
Given new "SyncTeams" request
588-
And body with value {"data": {"attributes": {"source": "github", "type": "link"}, "type": "team_sync_bulk"}}
589-
When the request is sent
590-
Then the response status is 200 OK
591-
592585
@team:DataDog/aaa-omg
593586
Scenario: Update a team link returns "API error response." response
594587
Given new "UpdateTeamLink" request

services/teams/src/v2/TeamsApi.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3160,11 +3160,7 @@ export class TeamsApiResponseProcessor {
31603160
) as TeamSyncResponse;
31613161
return body;
31623162
}
3163-
if (
3164-
response.httpStatusCode === 403 ||
3165-
response.httpStatusCode === 404 ||
3166-
response.httpStatusCode === 429
3167-
) {
3163+
if (response.httpStatusCode === 403 || response.httpStatusCode === 429) {
31683164
const bodyText = parse(await response.body.text(), contentType);
31693165
let body: APIErrorResponse;
31703166
try {
@@ -3592,7 +3588,7 @@ export class TeamsApiResponseProcessor {
35923588
*/
35933589
public async syncTeams(response: ResponseContext): Promise<void> {
35943590
const contentType = normalizeMediaType(response.headers["content-type"]);
3595-
if (response.httpStatusCode === 200) {
3591+
if (response.httpStatusCode === 200 || response.httpStatusCode === 204) {
35963592
return;
35973593
}
35983594
if (
@@ -5264,13 +5260,17 @@ export class TeamsApi {
52645260
}
52655261

52665262
/**
5267-
* This endpoint attempts to link your existing Datadog teams with GitHub teams by matching their names.
5263+
* This endpoint configures synchronization between your existing Datadog teams and GitHub teams by matching their names.
52685264
* It evaluates all current Datadog teams and compares them against teams in the GitHub organization
52695265
* connected to your Datadog account, based on Datadog Team handle and GitHub Team slug
52705266
* (lowercased and kebab-cased).
52715267
*
52725268
* This operation is read-only on the GitHub side, no teams will be modified or created.
52735269
*
5270+
* Optionally, provide `selection_state` to limit synchronization
5271+
* to specific teams or organizations and their subtrees, instead
5272+
* of syncing all teams.
5273+
*
52745274
* [A GitHub organization must be connected to your Datadog account](https://docs.datadoghq.com/integrations/github/),
52755275
* and the GitHub App integrated with Datadog must have the `Members Read` permission. Matching is performed by comparing the Datadog team handle to the GitHub team slug
52765276
* using a normalized exact match; case is ignored and spaces are removed. No modifications are made

services/teams/src/v2/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ export { TeamSyncBulkType } from "./models/TeamSyncBulkType";
146146
export { TeamSyncData } from "./models/TeamSyncData";
147147
export { TeamSyncRequest } from "./models/TeamSyncRequest";
148148
export { TeamSyncResponse } from "./models/TeamSyncResponse";
149+
export { TeamSyncSelectionStateExternalId } from "./models/TeamSyncSelectionStateExternalId";
150+
export { TeamSyncSelectionStateExternalIdType } from "./models/TeamSyncSelectionStateExternalIdType";
151+
export { TeamSyncSelectionStateItem } from "./models/TeamSyncSelectionStateItem";
152+
export { TeamSyncSelectionStateOperation } from "./models/TeamSyncSelectionStateOperation";
153+
export { TeamSyncSelectionStateScope } from "./models/TeamSyncSelectionStateScope";
149154
export { TeamType } from "./models/TeamType";
150155
export { TeamUpdate } from "./models/TeamUpdate";
151156
export { TeamUpdateAttributes } from "./models/TeamUpdateAttributes";

0 commit comments

Comments
 (0)