Environment diffing
#Overview
Environment diffing is a feature in the Management API that lets you compare schemas between two environments in a project.
This guide assumes the master environment is the target and the development environment is the source.
You can also use the Management SDK method to get the diff and apply schema changes.
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.
When using the API Playground, use the API selector dropdown to select the Management API.
The query to the ManagementApi
looks like this:
query MyQuery {viewer {project(id: "<your-project-id>") {environments {nameid}}}}
#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}}}
You can find your target environment ID using the first query example in this document.
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
Not supported: UI extensions.
#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:
#Sidebar elements in diffs
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.
A diff lists operations that make the target schema match the source. Any target changes not in the source will be replaced or overwritten.
This applies to any schema changes to your master environment, such as adding, editing, or deleting models, fields, or sidebar widgets.
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 adevelopment
environment and have spent some time since then working ondevelopment
, making changes to the schema. During that time, you also applied schema changes to yourmaster
environment, which you did not mirror indevelopment
. 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 yourmaster
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 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.
If you're working with a boolean field, you would need to pass the values true
or false
instead.
#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