Easily restore your project to a previous version with our new feature.
Hygraph
Docs

Environment diffing

#Overview

Environment diffing is a feature in the Management API that lets you compare schemas between two environments in a project.

When working with multiple environments, environment diffing helps you track changes made in development compared to the master environment. This helps you identify the changes needed to align your target environment with your source environment.

#How does environment diffing work?

Right after cloning, both environments have the same schema. As you apply schema changes to your development environment, it will start to diverge. To find out what exactly those differences are and then apply them to your target environment, you can create a diff.

#1. Get environment names

To create a diff, you need the names of the target and source environments.

The query to the ManagementApi looks like this:

query MyQuery {
viewer {
project(id: "<your-project-id>") {
environments {
name
id
}
}
}
}

#2. Create the diff

After getting the environment names, generate the diff. The response lists the changes needed to align the target with the source.

To differentiate between the environments master and dev, you can use the following query to the ManagementApi:

{
viewer {
project(id: "<your-project-id>") {
environment(name: "master") {
diff(environmentName: "development") {
changes
}
}
}
}
}

The response example above shows an array of objects (an ordered list of BatchMigrations), showing all the changes you need to apply to your target environment so that it's the same as your source environment.

#3. Apply schema changes

Use the returned list to apply updates to the target environment. Here's an example mutation in the ManagementApi:

mutation MyMutation($changes: [BatchMigrationChangeInput!]!) {
submitBatchChanges(
data: { environmentId: "<your-target-environment-id>", changes: $changes }
) {
migration {
id
}
}
}

In the above example, $changes is the environment variable with value equal to the changes object in the diff. This can be supplied like so:

#Supported schema elements

The following schema elements are supported:

  • Models
  • Components
  • Locales
  • Simple fields
  • Conditional visibility in fields
  • Relational fields
  • Enumerations
  • Enumerable fields
  • Initial values in enumeration fields
  • Stages
  • Union fields
  • Apps
  • Custom renderers and app fields
  • Sidebar elements
  • Remote fields
  • Remote type definitions
  • Remote sources

#Apps in diffs

The diff accounts for app installations, generating createAppInstallation and deleteAppInstallation operations as needed.

#Custom renderers and app fields in diffs

When creating or updating app fields, diffing includes configurations for custom renderers, like so:

The diff generates create, delete, or update statements for both system and custom sidebar elements within a model.

#Remote fields in diffs

Environment diffing manages create, delete, and update operations for remote fields, including their source selections and specific configurations.

#Conditional visibility in diffs

Environment diffing takes into account the conditional visibility settings on all fields:

"visibilityCondition": {
"baseField": "buildingMaterial",
"operator": "IS",
"booleanValue": null,
"enumerationValues": [
"plexiGlass"
]
}

#Environment diffing limitations

Please take into account the following limitations when using environment diffing.

#Schema changes in master

Environment diffing does not merge changes. Instead, it replaces the schema in the target environment with the one from the source.

If master changes after cloning but development does not, the diff suggests deleting unmatched changes. This can lead to content loss.

To avoid issues:

  • Freeze schema changes in master while working in development.
  • Mirror changes in both environments as you go.
  • Manually review the diff before applying it to prevent unintended deletions.

Example situations:

  • Imagine you cloned your master environment last week to create a development environment and have spent some time since then working on development, making changes to the schema. During that time, you also applied schema changes to your master environment, which you did not mirror in development. Later on, when using environment diffing to get the diff and apply it, the diff will find those differences, and suggest deleting the changes you made to the schema in your master during the last week. Remember it does not merge, but replaces / overwrites.
  • Imagine your target environment schema has a field called Title Field, and after cloning you change its name to Title in master. In this case, environment diffing would suggest to delete Title and create Title Field. Doing this would result in schemas being the same in both environments, but you will have lost the content.
  • Imagine you delete a field in your development environment, then create a new field with the same name, environment diffing would not detect them as different fields at all.

Once you get the diff, you can apply it as is or, if necessary, edit it manually before applying to avoid content loss in the case of schema changes in the target environment.

Review diff changes before applying them to ensure accuracy. Double-check deletions to prevent content loss.

#Required fields in diffs

If you make a field required in development, you must provide a migration value. This value replaces null for existing content.

Migration value in field validationsMigration value in field validations

In this case, environment diffing would suggest updating the field to required, but would not provide a migration value.

You must include it manually in the change request before applying it to prevent it from failing.

To do this, add "migrationValue": "value", like so:

{
"changes": [
{
"createSimpleField": {
"apiId": "newField",
"parentApiId": "Post",
"type": "STRING",
"displayName": "NewField",
"description": null,
"initialValue": null,
"tableRenderer": "GCMS_SINGLE_LINE",
"formRenderer": "GCMS_SINGLE_LINE",
"tableExtension": null,
"formExtension": null,
"formConfig": {},
"tableConfig": {},
"isList": false,
"isLocalized": false,
"isRequired": true,
"isUnique": false,
"isHidden": false,
"embeddableModels": [],
"visibility": "READ_WRITE",
"isTitle": false,
"position": 3,
"validations": null,
"embedsEnabled": null,
"migrationValue": "value"
}
}
]
}

This way, "value" will replace null after the diff.

#Remote Sources with OAuth

If a remote source uses OAuth authentication, the diff will exclude the clientSecret. You must manually add the actual secret before applying the changes.

You must manually replace CLIENT_SECRET with your actual secret before applying the batch mutation.

So, for instance, this:

"clientSecret": "CLIENT_SECRET",

Would turn into this:

"clientSecret": "23sad-129132", //actual secret value