Skip to content

Commit 6c6f5ab

Browse files
add Mutation.updateSchemaComposition to the public GraphQL API schema (#7635)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 96152dc commit 6c6f5ab

File tree

13 files changed

+247
-133
lines changed

13 files changed

+247
-133
lines changed

.changeset/quiet-chicken-look.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'hive': minor
3+
---
4+
5+
Add `Mutation.updateSchemaComposition` to the public GraphQL API schema.

integration-tests/testkit/flow.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,9 +1527,11 @@ export async function updateSchemaComposition(input: UpdateSchemaCompositionInpu
15271527
mutation updateSchemaComposition($input: UpdateSchemaCompositionInput!) {
15281528
updateSchemaComposition(input: $input) {
15291529
ok {
1530-
id
1531-
externalSchemaComposition {
1532-
endpoint
1530+
updatedProject {
1531+
id
1532+
externalSchemaComposition {
1533+
endpoint
1534+
}
15331535
}
15341536
}
15351537
error {

integration-tests/tests/api/schema/composition-federation-2.spec.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,25 @@ test.concurrent('call an external service to compose and validate services', asy
4040
// enable external composition
4141
const externalCompositionResult = await updateSchemaComposition(
4242
{
43-
external: {
44-
endpoint: `http://${dockerAddress}/compose`,
45-
// eslint-disable-next-line no-process-env
46-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
47-
projectSlug: project.slug,
48-
organizationSlug: organization.slug,
43+
project: {
44+
bySelector: {
45+
projectSlug: project.slug,
46+
organizationSlug: organization.slug,
47+
},
48+
},
49+
method: {
50+
external: {
51+
endpoint: `http://${dockerAddress}/compose`,
52+
// eslint-disable-next-line no-process-env
53+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
54+
},
4955
},
5056
},
5157
ownerToken,
5258
).then(r => r.expectNoGraphQLErrors());
5359
expect(
54-
externalCompositionResult.updateSchemaComposition.ok?.externalSchemaComposition?.endpoint,
60+
externalCompositionResult.updateSchemaComposition.ok?.updatedProject.externalSchemaComposition
61+
?.endpoint,
5562
).toBe(`http://${dockerAddress}/compose`);
5663
// Disable Native Federation v2 composition to allow the external composition to take place
5764
await setNativeFederation(false);

integration-tests/tests/api/schema/delete.spec.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,18 @@ test.concurrent(
239239

240240
await updateSchemaComposition(
241241
{
242-
external: {
243-
endpoint: `http://${await getServiceHost('composition_federation_2', 3069, false)}/compose`,
244-
// eslint-disable-next-line no-process-env
245-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
246-
projectSlug: project.slug,
247-
organizationSlug: organization.slug,
242+
project: {
243+
bySelector: {
244+
projectSlug: project.slug,
245+
organizationSlug: organization.slug,
246+
},
247+
},
248+
method: {
249+
external: {
250+
endpoint: `http://${await getServiceHost('composition_federation_2', 3069, false)}/compose`,
251+
// eslint-disable-next-line no-process-env
252+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
253+
},
248254
},
249255
},
250256
ownerToken,

integration-tests/tests/api/schema/external-composition.spec.ts

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,25 @@ test.concurrent('call an external service to compose and validate services', asy
4545
// enable external composition
4646
const externalCompositionResult = await updateSchemaComposition(
4747
{
48-
external: {
49-
endpoint: `http://${dockerAddress}/compose`,
50-
// eslint-disable-next-line no-process-env
51-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
52-
projectSlug: project.slug,
53-
organizationSlug: organization.slug,
48+
project: {
49+
bySelector: {
50+
projectSlug: project.slug,
51+
organizationSlug: organization.slug,
52+
},
53+
},
54+
method: {
55+
external: {
56+
endpoint: `http://${dockerAddress}/compose`,
57+
// eslint-disable-next-line no-process-env
58+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
59+
},
5460
},
5561
},
5662
ownerToken,
5763
).then(r => r.expectNoGraphQLErrors());
5864
expect(
59-
externalCompositionResult.updateSchemaComposition.ok?.externalSchemaComposition?.endpoint,
65+
externalCompositionResult.updateSchemaComposition.ok?.updatedProject.externalSchemaComposition
66+
?.endpoint,
6067
).toBe(`http://${dockerAddress}/compose`);
6168

6269
// set native federation to false to force external composition
@@ -129,18 +136,25 @@ test.concurrent(
129136
// enable external composition
130137
const externalCompositionResult = await updateSchemaComposition(
131138
{
132-
external: {
133-
endpoint: `http://${dockerAddress}/fail_on_signature`,
134-
// eslint-disable-next-line no-process-env
135-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
136-
projectSlug: project.slug,
137-
organizationSlug: organization.slug,
139+
project: {
140+
bySelector: {
141+
projectSlug: project.slug,
142+
organizationSlug: organization.slug,
143+
},
144+
},
145+
method: {
146+
external: {
147+
endpoint: `http://${dockerAddress}/fail_on_signature`,
148+
// eslint-disable-next-line no-process-env
149+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
150+
},
138151
},
139152
},
140153
ownerToken,
141154
).then(r => r.expectNoGraphQLErrors());
142155
expect(
143-
externalCompositionResult.updateSchemaComposition.ok?.externalSchemaComposition?.endpoint,
156+
externalCompositionResult.updateSchemaComposition.ok?.updatedProject.externalSchemaComposition
157+
?.endpoint,
144158
).toBe(`http://${dockerAddress}/fail_on_signature`);
145159

146160
// set native federation to false to force external composition
@@ -229,18 +243,25 @@ test.concurrent(
229243
// enable external composition
230244
const externalCompositionResult = await updateSchemaComposition(
231245
{
232-
external: {
233-
endpoint: `http://${dockerAddress}/non-existing-endpoint`,
234-
// eslint-disable-next-line no-process-env
235-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
236-
projectSlug: project.slug,
237-
organizationSlug: organization.slug,
246+
project: {
247+
bySelector: {
248+
projectSlug: project.slug,
249+
organizationSlug: organization.slug,
250+
},
251+
},
252+
method: {
253+
external: {
254+
endpoint: `http://${dockerAddress}/non-existing-endpoint`,
255+
// eslint-disable-next-line no-process-env
256+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
257+
},
238258
},
239259
},
240260
ownerToken,
241261
).then(r => r.expectNoGraphQLErrors());
242262
expect(
243-
externalCompositionResult.updateSchemaComposition.ok?.externalSchemaComposition?.endpoint,
263+
externalCompositionResult.updateSchemaComposition.ok?.updatedProject.externalSchemaComposition
264+
?.endpoint,
244265
).toBe(`http://${dockerAddress}/non-existing-endpoint`);
245266
// set native federation to false to force external composition
246267
await setNativeFederation(false);
@@ -326,18 +347,25 @@ test.concurrent('a timeout error should be visible to the user', async ({ expect
326347
// enable external composition
327348
const externalCompositionResult = await updateSchemaComposition(
328349
{
329-
external: {
330-
endpoint: `http://${dockerAddress}/timeout`,
331-
// eslint-disable-next-line no-process-env
332-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
333-
projectSlug: project.slug,
334-
organizationSlug: organization.slug,
350+
project: {
351+
bySelector: {
352+
projectSlug: project.slug,
353+
organizationSlug: organization.slug,
354+
},
355+
},
356+
method: {
357+
external: {
358+
endpoint: `http://${dockerAddress}/timeout`,
359+
// eslint-disable-next-line no-process-env
360+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
361+
},
335362
},
336363
},
337364
ownerToken,
338365
).then(r => r.expectNoGraphQLErrors());
339366
expect(
340-
externalCompositionResult.updateSchemaComposition.ok?.externalSchemaComposition?.endpoint,
367+
externalCompositionResult.updateSchemaComposition.ok?.updatedProject.externalSchemaComposition
368+
?.endpoint,
341369
).toBe(`http://${dockerAddress}/timeout`);
342370
// set native federation to false to force external composition
343371
await setNativeFederation(false);

integration-tests/tests/api/schema/publish.spec.ts

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3377,12 +3377,18 @@ test('Composition Error (Federation 2) can be served from the database', async (
33773377

33783378
await updateSchemaComposition(
33793379
{
3380-
external: {
3381-
endpoint: `http://${serviceAddress}/compose`,
3382-
// eslint-disable-next-line no-process-env
3383-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
3384-
projectSlug: project.slug,
3385-
organizationSlug: organization.slug,
3380+
project: {
3381+
bySelector: {
3382+
projectSlug: project.slug,
3383+
organizationSlug: organization.slug,
3384+
},
3385+
},
3386+
method: {
3387+
external: {
3388+
endpoint: `http://${serviceAddress}/compose`,
3389+
// eslint-disable-next-line no-process-env
3390+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
3391+
},
33863392
},
33873393
},
33883394
ownerToken,
@@ -3500,12 +3506,18 @@ test('Composition Network Failure (Federation 2)', async () => {
35003506

35013507
await updateSchemaComposition(
35023508
{
3503-
external: {
3504-
endpoint: `http://${serviceAddress}/compose`,
3505-
// eslint-disable-next-line no-process-env
3506-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
3507-
projectSlug: project.slug,
3508-
organizationSlug: organization.slug,
3509+
project: {
3510+
bySelector: {
3511+
projectSlug: project.slug,
3512+
organizationSlug: organization.slug,
3513+
},
3514+
},
3515+
method: {
3516+
external: {
3517+
endpoint: `http://${serviceAddress}/compose`,
3518+
// eslint-disable-next-line no-process-env
3519+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
3520+
},
35093521
},
35103522
},
35113523
ownerToken,
@@ -3543,11 +3555,18 @@ test('Composition Network Failure (Federation 2)', async () => {
35433555

35443556
await updateSchemaComposition(
35453557
{
3546-
external: {
3547-
endpoint: `http://${serviceAddress}/no_compose`,
3548-
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
3549-
projectSlug: project.slug,
3550-
organizationSlug: organization.slug,
3558+
project: {
3559+
bySelector: {
3560+
projectSlug: project.slug,
3561+
organizationSlug: organization.slug,
3562+
},
3563+
},
3564+
method: {
3565+
external: {
3566+
endpoint: `http://${serviceAddress}/no_compose`,
3567+
// eslint-disable-next-line no-process-env
3568+
secret: process.env.EXTERNAL_COMPOSITION_SECRET!,
3569+
},
35513570
},
35523571
},
35533572
ownerToken,

packages/services/api/src/modules/schema/module.graphql.ts

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ export default gql`
88
schemaCompose(input: SchemaComposeInput!): SchemaComposePayload!
99
1010
updateBaseSchema(input: UpdateBaseSchemaInput!): UpdateBaseSchemaResult!
11-
updateSchemaComposition(input: UpdateSchemaCompositionInput!): UpdateSchemaCompositionResult!
11+
"""
12+
Update the schema composition configuration of a federation project.
13+
"""
14+
updateSchemaComposition(
15+
input: UpdateSchemaCompositionInput! @tag(name: "public")
16+
): UpdateSchemaCompositionResult! @tag(name: "public")
1217
"""
1318
Approve a failed schema check with breaking changes.
1419
"""
@@ -43,55 +48,70 @@ export default gql`
4348
): TestExternalSchemaCompositionResult!
4449
}
4550
46-
input UpdateSchemaCompositionInput @oneOf {
47-
native: UpdateSchemaCompositionNativeInput
48-
external: UpdateSchemaCompositionExternalInput
49-
legacy: UpdateSchemaCompositionLegacyInput
51+
input SchemaCompositionExternalMethodInput @tag(name: "public") {
52+
endpoint: String!
53+
secret: String!
5054
}
5155
52-
input UpdateSchemaCompositionNativeInput {
53-
organizationSlug: String!
54-
projectSlug: String!
56+
input SchemaCompositionMethodInput @oneOf @tag(name: "public") {
57+
"""
58+
Use the native federation schema composition. This is the default method for new projects.
59+
"""
60+
native: Boolean
61+
"""
62+
Use an external schema composition endpoint.
63+
"""
64+
external: SchemaCompositionExternalMethodInput
65+
"""
66+
Use the legacy federation v1 schema composition.
67+
"""
68+
legacy: Boolean
5569
}
5670
57-
input UpdateSchemaCompositionExternalInput {
58-
organizationSlug: String!
59-
projectSlug: String!
60-
endpoint: String!
61-
secret: String!
71+
input UpdateSchemaCompositionInput @tag(name: "public") {
72+
"""
73+
Reference to the project on which the schema composition should be applied.
74+
"""
75+
project: ProjectReferenceInput!
76+
"""
77+
The composition method that should be set for the project.
78+
"""
79+
method: SchemaCompositionMethodInput!
6280
}
6381
64-
input UpdateSchemaCompositionLegacyInput {
65-
organizationSlug: String!
66-
projectSlug: String!
82+
type UpdateSchemaCompositionResultOk @tag(name: "public") {
83+
updatedProject: Project!
6784
}
6885
6986
"""
7087
@oneOf
7188
"""
72-
type UpdateSchemaCompositionResult {
73-
ok: Project
89+
type UpdateSchemaCompositionResult @tag(name: "public") {
90+
ok: UpdateSchemaCompositionResultOk
7491
error: UpdateSchemaCompositionError
7592
}
7693
77-
interface UpdateSchemaCompositionError implements Error {
94+
interface UpdateSchemaCompositionError @tag(name: "public") {
7895
message: String!
7996
}
8097
81-
type UpdateSchemaCompositionNativeError implements UpdateSchemaCompositionError & Error {
98+
type UpdateSchemaCompositionNativeError implements UpdateSchemaCompositionError
99+
@tag(name: "public") {
82100
message: String!
83101
}
84102
85-
type UpdateSchemaCompositionLegacyError implements UpdateSchemaCompositionError & Error {
103+
type UpdateSchemaCompositionLegacyError implements UpdateSchemaCompositionError
104+
@tag(name: "public") {
86105
message: String!
87106
}
88107
89-
type UpdateSchemaCompositionExternalError implements UpdateSchemaCompositionError & Error {
108+
type UpdateSchemaCompositionExternalError implements UpdateSchemaCompositionError
109+
@tag(name: "public") {
90110
message: String!
91111
inputErrors: UpdateSchemaCompositionExternalInputErrors
92112
}
93113
94-
type UpdateSchemaCompositionExternalInputErrors {
114+
type UpdateSchemaCompositionExternalInputErrors @tag(name: "public") {
95115
endpoint: String
96116
secret: String
97117
}

0 commit comments

Comments
 (0)