Skip to content

Conversation

@cheub
Copy link
Contributor

@cheub cheub commented Aug 25, 2025

Description

The option to disable semantic conventions currently is only passed down if a single subgraph is composed (config.subgraph). It should also be possible to disable the option when composing multiple subgraphs to a supergraph (config.subgraphs).

Fixes #8714

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

Manual tests are described in #8714. I basically used a schema that contains queries conforming to semantic conventions and disabled the feature. The directives were genereted anyway.
Additionally I implemented a basic e2e test (semantic-conventions).

Test Environment:

  • OS: Windows 11
  • @graphql-mesh/compose-cli: 1.4.12
  • NodeJS: 24.0.2

Checklist:

  • I have followed the
    CONTRIBUTING doc and the
    style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works, and I have added a
    changeset using yarn changeset that bumps the version
  • New and existing unit tests and linter rules pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 25, 2025

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Composition now correctly respects the ignoreSemanticConventions option, ensuring merge directives are generated only when conventions are enabled.
  • Tests

    • Added end-to-end tests verifying schema output with semantic conventions enabled vs. disabled.
  • Chores

    • Introduced e2e setup and minimal schema to support semantic conventions testing.
    • Updated versioning with a patch release note for the compose CLI package.

Walkthrough

For compose-cli, forwards ignoreSemanticConventions into the composition path (and sets alwaysAddTransportDirective explicitly), adds e2e fixtures/tests verifying presence/absence of @merge directives, adds a package for the e2e tests, schema, and a changeset for a patch release.

Changes

Cohort / File(s) Summary
E2E: Semantic Conventions configs & test
e2e/semantic-conventions/mesh.config.conventions-enabled.ts, e2e/semantic-conventions/mesh.config.conventions-disabled.ts, e2e/semantic-conventions/semantic-conventions.test.ts, e2e/semantic-conventions/schema.graphql, e2e/semantic-conventions/package.json
Adds an e2e package with two compose configs (one with ignoreSemanticConventions: true, one without), a minimal Book schema, and tests asserting generation or omission of @merge(...) directives in composed output.
Compose CLI option forwarding
packages/compose-cli/src/getComposedSchemaFromConfig.ts
Passes ignoreSemanticConventions: config.ignoreSemanticConventions and alwaysAddTransportDirective: false into composeSubgraphs(...) for the composition path (previously called without these options).
Release metadata
.changeset/lucky-bats-lead.md
Adds changeset describing a patch bump for @graphql-mesh/compose-cli noting the fix for ignored ignoreSemanticConventions.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CLI as mesh-compose (CLI)
  participant GetComposed as getComposedSchemaFromConfig
  participant Compose as composeSubgraphs
  participant FS as Filesystem

  CLI->>GetComposed: invoke with composeConfig (may include ignoreSemanticConventions)
  GetComposed->>Compose: composeSubgraphs(subgraphConfigs, { ignoreSemanticConventions: config.ignoreSemanticConventions, alwaysAddTransportDirective: false })
  alt ignoreSemanticConventions = true
    Note over Compose: Compose omits automatic semantic merge directives
  else ignoreSemanticConventions = false
    Note over Compose: Compose may add semantic merge directives
  end
  Compose-->>GetComposed: supergraph SDL
  GetComposed->>FS: write supergraph output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Honor ignoreSemanticConventions in composition flow (#8714)
Ensure alwaysAddTransportDirective is correctly forwarded (#8714) The PR sets alwaysAddTransportDirective: false for the composeSubgraphs call; it's unclear whether this satisfies the intended behavior in all code paths or tests.

Assessment against linked issues: Out-of-scope changes

(No out-of-scope functional changes identified.)

Suggested reviewers

  • enisdenjo

Poem

I nibble tests and schema seeds,
No stray @merge in my meadows.
Flip the flag and hush the feeds,
Compose obeys where logic flows.
Patch carrots bounce — hooray, compose! 🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (8)
.changeset/lucky-bats-lead.md (1)

5-5: Optionally reference the linked issue for traceability.

Consider appending “Fixes #8714.” to the body to auto-link the issue in release notes.

packages/compose-cli/src/getComposedSchemaFromConfig.ts (2)

119-122: Good move centralizing shared composition options. Add an explicit type and coerce the boolean.

Typing catches typos at compile-time and documents intent. Coercing to boolean avoids passing undefined.

Apply:

@@
-import {
-  composeSubgraphs,
-  futureAdditions,
-  getAnnotatedSubgraphs,
-  type FutureAddition,
-  type SubgraphConfig,
-} from '@graphql-mesh/fusion-composition';
+import {
+  composeSubgraphs,
+  futureAdditions,
+  getAnnotatedSubgraphs,
+  type FutureAddition,
+  type SubgraphConfig,
+  type ComposeSubgraphsOptions,
+} from '@graphql-mesh/fusion-composition';
@@
-  const options = {
-    ignoreSemanticConventions: config.ignoreSemanticConventions,
-    alwaysAddTransportDirective: true,
-  };
+  const options: ComposeSubgraphsOptions = {
+    ignoreSemanticConventions: Boolean(config.ignoreSemanticConventions),
+    alwaysAddTransportDirective: true,
+  };

121-121: Double-check side effects of alwaysAddTransportDirective: true.

Setting this unconditionally means minimal @transport directives won’t be stripped even when headers/options are empty. If that’s intentional for CLI output stability, great; otherwise consider exposing a CLI flag or deferring to library defaults.

e2e/semantic-conventions/package.json (1)

1-8: Align GraphQL dependency strategy with the monorepo.

If other e2e packages use workspace protocol for GraphQL, consider switching to keep versions in lockstep; otherwise this is fine as-is.

Would you like me to scan sibling e2e packages and open a small follow-up to standardize?

e2e/semantic-conventions/mesh.config.conventions-disabled.ts (1)

6-18: Optional: Add a companion test for the config.subgraph flow.

The bug was in the subgraphs[] branch, which you now cover. For completeness against future regressions, consider a second minimal config using config.subgraph to ensure both code paths honor ignoreSemanticConventions.

e2e/semantic-conventions/semantic-conventions.test.ts (3)

4-4: Regex is brittle; allow optional whitespace and avoid greedy capture

The current /@merge\(.*\)/ can miss matches if a space appears before ( or if the printer introduces formatting tweaks. A quick, minimal improvement:

Apply this diff to make the regex more resilient:

-const regExp = /@merge\(.*\)/;
+const regExp = /@merge\s*\([^)]*\)/m;

Note: If you adopt the AST-based approach suggested below, this regex becomes unnecessary.


1-14: Prefer AST-based assertion over regex to avoid false positives/negatives

Regex can (1) falsely match directive definitions (e.g., directive @merge(...)) and (2) break with printer formatting. Parsing the SDL and scanning for actual directive usages is robust and intention-revealing.

Apply this diff to parse the SDL and assert on directive usage:

-import { createTenv } from '@e2e/tenv';
+import { createTenv } from '@e2e/tenv';
+import { parse, visit } from 'graphql';
 
 const { compose, fs } = createTenv(__dirname);
-const regExp = /@merge\(.*\)/;
+
+function hasDirectiveUsage(sdl: string, name: string): boolean {
+  const ast = parse(sdl);
+  let used = false;
+  visit(ast, {
+    Directive(node) {
+      if (node.name.value === name) used = true;
+    },
+  });
+  return used;
+}
 
-it('should generate merge directives', async () => {
+it('should generate merge directive usages when conventions are enabled', async () => {
   const { output } = await compose({ output: 'graphql', args: ['-c', 'mesh.config.conventions-enabled.ts'] });
-  await expect(fs.read(output)).resolves.toMatch(regExp);
+  const sdl = await fs.read(output);
+  expect(hasDirectiveUsage(sdl, 'merge')).toBe(true);
 });
 
-it('should not generate merge directives', async () => {
+it('should not generate merge directive usages when conventions are disabled', async () => {
   const { output } = await compose({ output: 'graphql', args: ['-c', 'mesh.config.conventions-disabled.ts'] });
-  await expect(fs.read(output)).resolves.not.toMatch(regExp);
+  const sdl = await fs.read(output);
+  expect(hasDirectiveUsage(sdl, 'merge')).toBe(false);
 });

6-14: Add coverage for multi-subgraphs (the original bug surface)

The issue fixed here manifests when composing multiple subgraphs via config.subgraphs. The current tests exercise only a single subgraph. Please add an e2e that composes at least two subgraphs and verifies:

  • enabled: usages of @merge are present,
  • disabled (ignoreSemanticConventions: true): no usages of @merge are present.

I can draft the additional configs (e.g., mesh.config.subgraphs-conventions-enabled.ts and mesh.config.subgraphs-conventions-disabled.ts) and, if needed, minimal additional SDL (or reuse the same SDL for two subgraphs) plus corresponding test blocks.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3d55cde and d7f72ec.

📒 Files selected for processing (7)
  • .changeset/lucky-bats-lead.md (1 hunks)
  • e2e/semantic-conventions/mesh.config.conventions-disabled.ts (1 hunks)
  • e2e/semantic-conventions/mesh.config.conventions-enabled.ts (1 hunks)
  • e2e/semantic-conventions/package.json (1 hunks)
  • e2e/semantic-conventions/schema.graphql (1 hunks)
  • e2e/semantic-conventions/semantic-conventions.test.ts (1 hunks)
  • packages/compose-cli/src/getComposedSchemaFromConfig.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
e2e/semantic-conventions/semantic-conventions.test.ts (1)
e2e/utils/tenv.ts (2)
  • createTenv (216-655)
  • compose (303-358)
packages/compose-cli/src/getComposedSchemaFromConfig.ts (1)
packages/fusion/composition/src/compose.ts (2)
  • getAnnotatedSubgraphs (77-547)
  • composeSubgraphs (562-572)
e2e/semantic-conventions/mesh.config.conventions-enabled.ts (3)
e2e/semantic-conventions/mesh.config.conventions-disabled.ts (1)
  • composeConfig (6-18)
packages/compose-cli/src/types.ts (1)
  • defineConfig (45-47)
packages/compose-cli/src/loadGraphQLHTTPSubgraph.ts (1)
  • loadGraphQLHTTPSubgraph (203-368)
e2e/semantic-conventions/mesh.config.conventions-disabled.ts (3)
e2e/semantic-conventions/mesh.config.conventions-enabled.ts (1)
  • composeConfig (6-17)
packages/compose-cli/src/types.ts (1)
  • defineConfig (45-47)
packages/compose-cli/src/loadGraphQLHTTPSubgraph.ts (1)
  • loadGraphQLHTTPSubgraph (203-368)
🔇 Additional comments (5)
.changeset/lucky-bats-lead.md (1)

1-5: Changeset looks good and targets the right package.

Patch bump on @graphql-mesh/compose-cli with a concise message aligns with the scope of this fix.

packages/compose-cli/src/getComposedSchemaFromConfig.ts (1)

124-124: Bug fix confirmed: options now flow through both single- and multi-subgraph paths.

Previously only the single-subgraph branch respected ignoreSemanticConventions; this resolves #8714’s core complaint for subgraphs[]. Nicely done.

Also applies to: 132-132

e2e/semantic-conventions/mesh.config.conventions-disabled.ts (1)

6-18: Config correctly disables semantic conventions via subgraphs[].

This exercises the path that previously ignored the option. Looks good.

e2e/semantic-conventions/mesh.config.conventions-enabled.ts (1)

6-17: Enabled config mirrors the disabled variant appropriately.

Good parity between the two configs to validate presence vs. absence of @merge.

e2e/semantic-conventions/schema.graphql (1)

1-7: LGTM: minimal schema is sufficient for exercising semantic conventions

The simple Query and Book types are adequate for the e2e scenario. No issues spotted.

Copy link
Owner

@ardatan ardatan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! It looks great!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
.changeset/lucky-bats-lead.md (2)

5-5: Polish wording and capture both forwarded flags for accuracy.

Current phrasing is a bit awkward and only mentions ignoreSemanticConventions, while the PR also forwards alwaysAddTransportDirective. Consider this tighter copy:

-`ignoreSemanticConventions` option was ignored when you compose subgraphs into a supergraph.
+Fix: Respect `ignoreSemanticConventions` (and `alwaysAddTransportDirective`) when composing via `composeConfig.subgraphs`.
+Previously, these options were only applied when using the single `subgraph` path.

5-6: Remove stray trailing character.

There appears to be an orphaned “6” on Line 6. It’s harmless but untidy in release notes.

-`ignoreSemanticConventions` option was ignored when you compose subgraphs into a supergraph.
-6
+`ignoreSemanticConventions` option was ignored when you compose subgraphs into a supergraph.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d7f72ec and e8daa6d.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (1)
  • .changeset/lucky-bats-lead.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
.changeset/lucky-bats-lead.md

[grammar] ~5-~5: There might be a mistake here.
Context: ...you compose subgraphs into a supergraph.

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: apollo-federation-compatibility
  • GitHub Check: e2e / node v20
  • GitHub Check: integration / node 18
  • GitHub Check: integration / node 22
  • GitHub Check: integration / node 20
  • GitHub Check: check
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 18
🔇 Additional comments (1)
.changeset/lucky-bats-lead.md (1)

1-4: Changeset front‑matter looks correct for a patch bump.

Package name and release type align with the PR scope (compose-cli only).

}
const options = {
ignoreSemanticConventions: config.ignoreSemanticConventions,
alwaysAddTransportDirective: true,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I realized, this should not be true for regular subgraph composition.

@ardatan ardatan force-pushed the fix-semantic-conventions branch from e8daa6d to 701c927 Compare August 25, 2025 15:52
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/compose-cli/src/getComposedSchemaFromConfig.ts (1)

131-134: Correctly propagate ignoreSemanticConventions and disable transport directives in multi-subgraph composition

This aligns the multi-subgraph path with the intended behavior and fixes the reported issue where merge directives appeared despite ignoreSemanticConventions: true. Good catch.

🧹 Nitpick comments (4)
.changeset/lucky-bats-lead.md (1)

5-5: Tighten phrasing and clarify scope in the changeset entry

Minor grammar fix and make it explicit this affects the subgraphs array path; also mention the transport directive toggle to preempt questions when scanning release notes.

-`ignoreSemanticConventions` option was ignored when you compose subgraphs into a supergraph.
+`ignoreSemanticConventions` option was ignored when composing multiple subgraphs (`composeConfig.subgraphs`) into a supergraph.
+The composition path now forwards this flag and disables `alwaysAddTransportDirective` by default.
packages/compose-cli/src/getComposedSchemaFromConfig.ts (1)

131-134: Document why transport directives differ between annotated vs. composed paths

Future readers may wonder why alwaysAddTransportDirective is true for the annotated single-subgraph path but false here. A short comment helps avoid regressions.

-  const result = composeSubgraphs(subgraphConfigsForComposition, {
+  // In regular supergraph composition we avoid synthetic transport directives;
+  // they are only needed when printing a single annotated subgraph (config.subgraph).
+  const result = composeSubgraphs(subgraphConfigsForComposition, {
     ignoreSemanticConventions: config.ignoreSemanticConventions,
     alwaysAddTransportDirective: false,
   });
e2e/semantic-conventions/semantic-conventions.test.ts (2)

4-4: Make the directive detection regex more robust to whitespace/formatting

GraphQL printers can vary spacing/line-wrapping. This regex avoids potential false negatives.

-const regExp = /@merge\(.*\)/;
+const regExp = /@merge\s*\([^)]*\)/m;

6-20: Add a multi-subgraph scenario to reflect the original failure mode

The linked issue was about the subgraphs array. The current fixtures use a single subgraph configuration, which is good, but a second test that composes two simple subgraphs (one providing an entity and another referencing it) would harden coverage and prevent regressions.

If you’d like, I can draft:

  • two tiny SDLs (Book + Review),
  • corresponding mesh.config.conventions-enabled|disabled.2-subgraphs.ts fixtures,
  • and an extra test that asserts presence/absence of @merge across the composed supergraph.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e8daa6d and 701c927.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • .changeset/lucky-bats-lead.md (1 hunks)
  • e2e/semantic-conventions/mesh.config.conventions-disabled.ts (1 hunks)
  • e2e/semantic-conventions/mesh.config.conventions-enabled.ts (1 hunks)
  • e2e/semantic-conventions/package.json (1 hunks)
  • e2e/semantic-conventions/schema.graphql (1 hunks)
  • e2e/semantic-conventions/semantic-conventions.test.ts (1 hunks)
  • packages/compose-cli/src/getComposedSchemaFromConfig.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • e2e/semantic-conventions/mesh.config.conventions-disabled.ts
  • e2e/semantic-conventions/package.json
  • e2e/semantic-conventions/schema.graphql
  • e2e/semantic-conventions/mesh.config.conventions-enabled.ts
🧰 Additional context used
🧬 Code graph analysis (2)
e2e/semantic-conventions/semantic-conventions.test.ts (1)
e2e/utils/tenv.ts (1)
  • compose (303-358)
packages/compose-cli/src/getComposedSchemaFromConfig.ts (1)
packages/fusion/composition/src/compose.ts (1)
  • composeSubgraphs (562-572)
🪛 LanguageTool
.changeset/lucky-bats-lead.md

[grammar] ~5-~5: There might be a mistake here.
Context: ...you compose subgraphs into a supergraph.

(QB_NEW_EN)

🔇 Additional comments (1)
packages/compose-cli/src/getComposedSchemaFromConfig.ts (1)

131-134: ✅ All composeSubgraphs call sites are properly guarded

  • Only two production‐code invocations remain:
    • In packages/fusion/composition/src/compose.ts (getUnifiedGraphGracefully) using defaults
    • In packages/compose-cli/src/getComposedSchemaFromConfig.ts (one for single‐subgraph via getAnnotatedSubgraphs with alwaysAddTransportDirective: true, another for multi-subgraph via composeSubgraphs with alwaysAddTransportDirective: false)
  • No other unguarded composeSubgraphs calls were found outside of tests.
  • Every E2E mesh.config.ts fixture now uses the subgraphs array, confirming the new multi-subgraph path is exercised.

@ardatan ardatan merged commit f63a9d7 into ardatan:master Aug 25, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The option ignoreSemanticConventions is ignored

2 participants