From be707ec736b0c69d57e91b3255254c4723e7f490 Mon Sep 17 00:00:00 2001 From: Wilson Rivera Date: Tue, 14 Jul 2026 14:40:01 -0400 Subject: [PATCH 1/3] feat: avoid extra compositions due trailing newline --- controlplane/src/core/repositories/SubgraphRepository.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/controlplane/src/core/repositories/SubgraphRepository.ts b/controlplane/src/core/repositories/SubgraphRepository.ts index 3b08f5e598..15bd99afa9 100644 --- a/controlplane/src/core/repositories/SubgraphRepository.ts +++ b/controlplane/src/core/repositories/SubgraphRepository.ts @@ -421,11 +421,14 @@ export class SubgraphRepository { } // TODO: avoid downloading the schema use hash instead - if (data.schemaSDL && (subgraph.type === 'grpc_plugin' || data.schemaSDL !== subgraph.schemaSDL.trimEnd())) { + if ( + data.schemaSDL && + (subgraph.type === 'grpc_plugin' || data.schemaSDL.trimEnd() !== subgraph.schemaSDL.trimEnd()) + ) { subgraphChanged = true; const updatedSubgraph = await subgraphRepo.addSchemaVersion({ targetId: subgraph.targetId, - subgraphSchema: data.schemaSDL, + subgraphSchema: data.schemaSDL.trimEnd(), isV2Graph: data.isV2Graph, proto: data.proto, }); From dcbd96116c5e696d7c5859f12fd4b8507dd0b27b Mon Sep 17 00:00:00 2001 From: Wilson Rivera Date: Tue, 14 Jul 2026 14:45:23 -0400 Subject: [PATCH 2/3] chore: add validation test --- .../test/subgraph/publish-subgraph.test.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/controlplane/test/subgraph/publish-subgraph.test.ts b/controlplane/test/subgraph/publish-subgraph.test.ts index ad24f88ac1..166c64763a 100644 --- a/controlplane/test/subgraph/publish-subgraph.test.ts +++ b/controlplane/test/subgraph/publish-subgraph.test.ts @@ -81,6 +81,43 @@ describe('Publish subgraph tests', () => { expect(publishFederatedSubgraphResp.response?.code).toBe(EnumStatusCode.OK); }); + test('that newlines do not cause extra compositions', async () => { + const { client, server } = await SetupTest({ dbname }); + onTestFinished(() => server.close()); + + const subgraphName = genID('subgraph'); + + await createSubgraph(client, subgraphName, 'http://localhost:4001'); + let publishFederatedSubgraphResp = await client.publishFederatedSubgraph({ + name: subgraphName, + namespace: 'default', + schema: subgraphSDL, + }); + + expect(publishFederatedSubgraphResp.response?.code).toBe(EnumStatusCode.OK); + expect(publishFederatedSubgraphResp.hasChanged).toBe(true); + + // Multiple newlines should not cause extra composition + publishFederatedSubgraphResp = await client.publishFederatedSubgraph({ + name: subgraphName, + namespace: 'default', + schema: subgraphSDL + '\r\n\r\n\r\n\n\n\n', + }); + + expect(publishFederatedSubgraphResp.response?.code).toBe(EnumStatusCode.OK); + expect(publishFederatedSubgraphResp.hasChanged).toBe(false); + + // Trimmed should not cause extra composition + publishFederatedSubgraphResp = await client.publishFederatedSubgraph({ + name: subgraphName, + namespace: 'default', + schema: subgraphSDL.trimEnd(), + }); + + expect(publishFederatedSubgraphResp.response?.code).toBe(EnumStatusCode.OK); + expect(publishFederatedSubgraphResp.hasChanged).toBe(false); + }); + test.each(['organization-admin', 'organization-developer', 'subgraph-admin', 'subgraph-publisher'])( '%s should be able to publish to existing regular subgraph', async (role) => { From 1b5ec87c263ad0ef1c5d6469ad06bd880a2e67eb Mon Sep 17 00:00:00 2001 From: Wilson Rivera Date: Tue, 14 Jul 2026 15:12:56 -0400 Subject: [PATCH 3/3] chore: fix tests --- .../test-data/feature-flags/products-standalone-feature.graphql | 1 - 1 file changed, 1 deletion(-) diff --git a/controlplane/test/test-data/feature-flags/products-standalone-feature.graphql b/controlplane/test/test-data/feature-flags/products-standalone-feature.graphql index b8d0611902..e9bc25d2df 100644 --- a/controlplane/test/test-data/feature-flags/products-standalone-feature.graphql +++ b/controlplane/test/test-data/feature-flags/products-standalone-feature.graphql @@ -3,7 +3,6 @@ type Product @key(fields: "upc sku") { sku: String! details: String! isPremium: Boolean! @tag(name: "exclude") - newField: String! } type Query {