Skip to content

feat: schema version promotion#8031

Draft
n1ru4l wants to merge 18 commits into
mainfrom
feat-schema-version-promotion
Draft

feat: schema version promotion#8031
n1ru4l wants to merge 18 commits into
mainfrom
feat-schema-version-promotion

Conversation

@n1ru4l
Copy link
Copy Markdown
Contributor

@n1ru4l n1ru4l commented May 10, 2026

Background

Closes #4021

Description

Introduces functionality for promoting a schema version from one target to another target (or the same target), making it the latest version within that target.

This enables workflows such as:

  • Promote schema version from one environment to another environment (staging to production)
  • Quick rollbacks to a specific previous schema version within one environment

Alongside a new CLI command for performing these promotions this change also comes along a new UI for schema versions with more insights into the individual changes of the subgraphs.

image image image

Comment on lines +31 to +32
ALTER COLUMN IF EXISTS "action_id" DROP NOT NULL
, ADD COLUMN IF NOT EXISTS "origin" jsonb NULL
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There is now no longer "one" single action that caused a schema version.

Instead we have now a origin column that stores the information (subgraph/schema publish; subgraph removal; schema promotion) in a more flexible way.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
hive 11.1.1-alpha-20260514114711-308bfead7053c7d3b0683041a5e0b6f3daca2ce6 npm ↗︎ unpkg ↗︎

ALTER TABLE "schema_versions"
ALTER COLUMN IF EXISTS "action_id" DROP NOT NULL
, ADD COLUMN IF NOT EXISTS "origin" jsonb NULL
, ADD COLUMN IF NOT EXISTS "supergraph_changes" jsonb NULL
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We store the public schema changes in a separate table schema_version_changes. However, we do not do anything with that table aside from loading the rows. No custom indices etc.

Thus I made the decision to add the column to store supergraph changes to the schema_versions table directly.

Comment on lines +965 to +967
log: RegistryLog!
@tag(name: "public")
@deprecated(reason: "Please use 'SchemaVersion.origin' instead.")
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note: I plan to remove this field as part of this pull request. I just deprecated it for now as it is used in unit tests.

Conditional breaking changes says its safe to remove it.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

🐋 This PR was built and pushed to the following Docker images:

Targets: build

Platforms: linux/arm64

Image Tag: 308bfead7053c7d3b0683041a5e0b6f3daca2ce6

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a schema version promotion feature, allowing users to promote a schema version from one target to another within a project. It includes a new database migration, GraphQL schema updates for the schemaVersionPromote mutation and PromotionSchemaLog type, and significant logic in SchemaPublisher and SchemaVersionStore to handle the promotion process and track version origins. Feedback includes identifying a missing crypto import that will cause runtime errors, a typo in a SQL string, and unsafe array access. Additionally, there are suggestions to update an incorrect migration comment, reconsider the use of a dummy field in the GraphQL schema, and evaluate if STITCHING projects should also support this feature.

throw new Error('INVARIANT: Remove logs require a service name.');
}
// Note: we seed the ID here so we do not need to map some more within the logic within `SchemaVersions.promoteSchemaVersionToTarget`
const logId = crypto.randomUUID();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The variable crypto is not defined in this scope. Only createHash is explicitly imported from node:crypto at the top of the file. Unless crypto is available globally in your environment, this will cause a runtime error. Consider importing randomUUID from node:crypto and using it directly.

Comment on lines +5 to +10
/**
* Adds an expiration date to tokens. This expiration doesn't need to
* be an index since we're always looking up by ID and then can verify
* the timestamp via a filter. Since these lookups are always be done
* via provider methods and not via a raw table query, this is safe.
*/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The comment block appears to be copied from a different migration related to token expiration. It should be updated to reflect the actual purpose of this migration, which is schema version promotion.

"""
The origin of this schema log promotion.
"""
_: Boolean! @tag(name: "public")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using a dummy field _ in PromotionSchemaLog is not ideal for API clarity. Even if the type currently has no specific fields, consider adding meaningful metadata such as promotedAt or information about the source target/version to make the API more descriptive and useful for clients.

}),
]);

if (project.type !== Types.ProjectType.FEDERATION) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The check restricts promotion to FEDERATION projects only. However, STITCHING is also a composite project type supported by the CompositeModel and other helpers in this module. Consider if STITCHING projects should also support schema version promotion.

Comment on lines +474 to +475
const schemas = await this.schemaVersions.getSchemasBySchemaVersionId(schemaVersion.id);
actionId = schemas[0].id;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Unsafe access to schemas[0]. If getSchemasBySchemaVersionId returns an empty array, this will throw a runtime error. It is safer to check if the array has elements before accessing them.

          const schemas = await this.schemaVersions.getSchemasBySchemaVersionId(schemaVersion.id);
          if (schemas.length === 0) {
            throw new Error('INVARIANT: No schemas found for the version');
          }
          actionId = schemas[0].id;

Comment thread packages/services/api/src/modules/schema/providers/schema-version-store.ts Outdated
@n1ru4l n1ru4l force-pushed the feat-schema-version-promotion branch 2 times, most recently from 91ca78a to 05a3f05 Compare May 10, 2026 21:18
Base automatically changed from chore-refactor-schema-version-store to main May 11, 2026 20:59
@n1ru4l n1ru4l force-pushed the feat-schema-version-promotion branch 5 times, most recently from f15a85c to c0f20b4 Compare May 13, 2026 10:48
@n1ru4l n1ru4l force-pushed the feat-schema-version-promotion branch from c0f20b4 to 9d6cac5 Compare May 13, 2026 10:49
@n1ru4l n1ru4l changed the title Feat schema version promotion feat: schema version promotion May 13, 2026
ALTER COLUMN "action_id" DROP NOT NULL
, ADD COLUMN IF NOT EXISTS "origin" jsonb NULL
, ADD COLUMN IF NOT EXISTS "supergraph_changes" jsonb NULL
, ADD COLUMN IF NOT EXISTS "meta" jsonb NULL
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This column stores additional user-provided metadata such as commit and author. Previously this was exclusively stored on the schema_log. However, since now a schema version is no longer exclusively triggered by "one" schema_log, we need to store that metadata on the schema version directly in order to make other existing functionality still work as expected.

Comment on lines +13 to +18
ALTER TABLE "schema_version_to_log"
ADD COLUMN IF NOT EXISTS type hive_subgraph_log_type DEFAULT NULL
, ADD COLUMN IF NOT EXISTS "previous_action_id" UUID DEFAULT NULL REFERENCES "schema_log"("id") ON DELETE CASCADE
, ADD COLUMN IF NOT EXISTS "schema_changes" JSONB DEFAULT NULL
, ADD COLUMN IF NOT EXISTS "subgraph_name" TEXT NULL
;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This type stores now more complex information that serves the purpose of tracking how the subgraphs changed between schema versions.

@n1ru4l n1ru4l force-pushed the feat-schema-version-promotion branch from 9867645 to 308bfea Compare May 14, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Promote schema version from one target to another target

1 participant