Deprecate GraphQL ID/GlobalID compatibility
Deprecation Summary
See #257883 (closed)
In !36209 (merged) a compatibility layer was introduced to allow us to change the types of arguments from ID_TYPE
to GlobalIDType[T]
. This requires us to be careful and add lots of explicit coercions.
Breaking Change
Users who wrote GraphQL queries using ID
types in query signatures will be affected if they are used to provide arguments for any of these fields:
Query.snippets(ids: [SnippetID!])
Query.snippets(authorId: UserID)
Query.snippets(projectId: ProjectID)
Query.milestone(id: MilestoneID!)
Query.containerRepository(id: ContainerRepositoryID!)
Query.package(id: PackagesPackageID!)
Query.user(id: UserID)
Query.issue(id: IssueID!)
Query.mergeRequest(id: MergeRequestID!)
Query.runnerSetup(projectId: ProjectID)
Query.runnerSetup(groupId: GroupID)
Query.runner(id: CiRunnerID!)
Query.timelogs(projectId: ProjectID)
Query.timelogs(groupId: GroupID)
Query.boardList(id: ListID!)
Query.iteration(id: IterationID!)
Query.vulnerabilities(scannerId: [VulnerabilitiesScannerID!])
Query.vulnerabilities(clusterId: [ClustersClusterID!])
Query.vulnerabilities(clusterAgentId: [ClustersAgentID!])
Query.vulnerability(id: VulnerabilityID!)
Query.devopsAdoptionEnabledNamespaces(displayNamespaceId: NamespaceID)
Query.ciMinutesUsage(namespaceId: NamespaceID)
Project.sentryDetailedError(id: GitlabErrorTrackingDetailedErrorID!)
Project.snippets(ids: [SnippetID!])
Project.boards(id: BoardID)
Project.board(id: BoardID!)
Project.alertManagementHttpIntegrations(id: AlertManagementHttpIntegrationID)
Project.timelogs(projectId: ProjectID)
Project.timelogs(groupId: GroupID)
Project.vulnerabilities(scannerId: [VulnerabilitiesScannerID!])
Project.vulnerabilities(clusterId: [ClustersClusterID!])
Project.vulnerabilities(clusterAgentId: [ClustersAgentID!])
Project.vulnerabilitySeveritiesCount(scannerId: [VulnerabilitiesScannerID!])
Project.iterations(iterationCadenceIds: [IterationsCadenceID!])
Project.iterationCadences(id: IterationsCadenceID)
Project.dastProfile(id: DastProfileID!)
Project.dastSiteProfile(id: DastSiteProfileID!)
Project.incidentManagementEscalationPolicy(id: IncidentManagementEscalationPolicyID!)
Project.incidentManagementTimelineEvents(incidentId: IssueID!)
Project.incidentManagementTimelineEvent(incidentId: IssueID!)
Project.incidentManagementTimelineEvent(id: IncidentManagementTimelineEventID!)
Project.networkPolicies(environmentId: EnvironmentID)
Namespace.complianceFrameworks(id: ComplianceManagementFrameworkID)
Namespace.complianceFrameworks(id: ComplianceManagementFrameworkID)
Group.boards(id: BoardID)
Group.board(id: BoardID!)
Group.timelogs(projectId: ProjectID)
Group.timelogs(groupId: GroupID)
Group.epicBoard(id: BoardsEpicBoardID!)
Group.iterations(iterationCadenceIds: [IterationsCadenceID!])
Group.iterationCadences(id: IterationsCadenceID)
Group.vulnerabilities(scannerId: [VulnerabilitiesScannerID!])
Group.vulnerabilities(clusterId: [ClustersClusterID!])
Group.vulnerabilities(clusterAgentId: [ClustersAgentID!])
Group.vulnerabilitySeveritiesCount(scannerId: [VulnerabilitiesScannerID!])
User.authoredMergeRequests(projectId: ProjectID)
User.assignedMergeRequests(projectId: ProjectID)
User.reviewRequestedMergeRequests(projectId: ProjectID)
User.snippets(ids: [SnippetID!])
User.timelogs(projectId: ProjectID)
User.timelogs(groupId: GroupID)
MemberInterface.mergeRequestInteraction(id: MergeRequestID!)
MemberInterface.mergeRequestInteraction(id: MergeRequestID!)
MemberInterface.mergeRequestInteraction(id: MergeRequestID!)
Design.versions(earlierOrEqualToId: DesignManagementVersionID)
DesignVersion.designsAtVersion(ids: [DesignManagementDesignID!])
DesignVersion.designAtVersion(designId: DesignManagementDesignID)
DesignVersion.designAtVersion(id: DesignManagementDesignAtVersionID)
Pipeline.job(id: JobID)
User.authoredMergeRequests(projectId: ProjectID)
User.assignedMergeRequests(projectId: ProjectID)
User.reviewRequestedMergeRequests(projectId: ProjectID)
User.snippets(ids: [SnippetID!])
User.timelogs(projectId: ProjectID)
User.timelogs(groupId: GroupID)
User.authoredMergeRequests(projectId: ProjectID)
User.assignedMergeRequests(projectId: ProjectID)
User.reviewRequestedMergeRequests(projectId: ProjectID)
User.snippets(ids: [SnippetID!])
User.timelogs(projectId: ProjectID)
User.timelogs(groupId: GroupID)
User.authoredMergeRequests(projectId: ProjectID)
User.assignedMergeRequests(projectId: ProjectID)
User.reviewRequestedMergeRequests(projectId: ProjectID)
User.snippets(ids: [SnippetID!])
User.timelogs(projectId: ProjectID)
User.timelogs(groupId: GroupID)
DesignCollection.designs(atVersion: DesignManagementVersionID)
DesignCollection.designs(ids: [DesignManagementDesignID!])
DesignCollection.versions(earlierOrEqualToId: DesignManagementVersionID)
DesignCollection.version(id: DesignManagementVersionID)
DesignCollection.designAtVersion(id: DesignManagementDesignAtVersionID!)
DesignCollection.design(id: DesignManagementDesignID)
IncidentManagementOncallSchedule.rotation(id: IncidentManagementOncallRotationID!)
Board.lists(id: ListID)
EpicBoard.lists(id: BoardsEpicListID)
SentryErrorCollection.detailedError(id: GitlabErrorTrackingDetailedErrorID!)
SentryErrorCollection.errorStackTrace(id: GitlabErrorTrackingDetailedErrorID!)
DesignManagement.version(id: DesignManagementVersionID!)
DesignManagement.designAtVersion(id: DesignManagementDesignAtVersionID!)
InstanceSecurityDashboard.vulnerabilitySeveritiesCount(scannerId: [VulnerabilitiesScannerID!])
Subscription.issuableAssigneesUpdated(issuableId: IssuableID!)
Subscription.issueCrmContactsUpdated(issuableId: IssuableID!)
Subscription.issuableTitleUpdated(issuableId: IssuableID!)
The list of query field arguments that have the ID
type and do not need to be updated is:
Query.project(fullPath: ID!)
Query.projects(ids: [ID!])
Query.group(fullPath: ID!)
Query.namespace(fullPath: ID!)
Query.users(ids: [ID!])
Query.ciConfig(projectPath: ID!)
Query.vulnerabilities(projectId: [ID!])
Project.issues(iterationId: [ID])
Project.milestones(ids: [ID!])
Project.issue(iterationId: [ID])
Project.pipeline(iid: ID)
Project.vulnerabilities(projectId: [ID!])
Project.vulnerabilitySeveritiesCount(projectId: [ID!])
Project.requirement(iid: ID)
Project.requirement(iids: [ID!])
Project.requirements(iid: ID)
Project.requirements(iids: [ID!])
Project.iterations(id: ID)
Project.iterations(iid: ID)
Project.incidentManagementOncallSchedules(iids: [ID!])
Namespace.projects(ids: [ID!])
Namespace.projects(ids: [ID!])
Group.issues(iterationId: [ID])
Group.milestones(ids: [ID!])
Group.epic(iid: ID)
Group.epic(iids: [ID!])
Group.epics(iid: ID)
Group.epics(iids: [ID!])
Group.iterations(id: ID)
Group.iterations(iid: ID)
Group.vulnerabilities(projectId: [ID!])
Group.vulnerabilitySeveritiesCount(projectId: [ID!])
User.todos(authorId: [ID!])
User.todos(projectId: [ID!])
User.todos(groupId: [ID!])
Pipeline.testSuite(buildIds: [ID!]!)
User.todos(authorId: [ID!])
User.todos(projectId: [ID!])
User.todos(groupId: [ID!])
User.todos(authorId: [ID!])
User.todos(projectId: [ID!])
User.todos(groupId: [ID!])
User.todos(authorId: [ID!])
User.todos(projectId: [ID!])
User.todos(groupId: [ID!])
AlertManagementAlert.todos(authorId: [ID!])
AlertManagementAlert.todos(projectId: [ID!])
AlertManagementAlert.todos(groupId: [ID!])
Epic.children(iid: ID)
Epic.children(iids: [ID!])
Epic.ancestors(iid: ID)
Epic.ancestors(iids: [ID!])
Epic.children(iid: ID)
Epic.children(iids: [ID!])
Epic.ancestors(iid: ID)
Epic.ancestors(iids: [ID!])
GeoNode.mergeRequestDiffRegistries(ids: [ID!])
GeoNode.packageFileRegistries(ids: [ID!])
GeoNode.snippetRepositoryRegistries(ids: [ID!])
GeoNode.terraformStateVersionRegistries(ids: [ID!])
GeoNode.groupWikiRepositoryRegistries(ids: [ID!])
GeoNode.lfsObjectRegistries(ids: [ID!])
GeoNode.pipelineArtifactRegistries(ids: [ID!])
GeoNode.pagesDeploymentRegistries(ids: [ID!])
GeoNode.uploadRegistries(ids: [ID!])
InstanceSecurityDashboard.vulnerabilitySeveritiesCount(projectId: [ID!])
Currently we support values for these arguments being supplied as ID
, which is a non-standard extension to the GraphQL validation logic. This will become a validation error.
Instead of:
query($id: ID!) {
issue(id: $id) { title }
}
You should write this query as:
query($id: IssueID!) {
issue(id: $id) { title }
}
or use an inline argument expression:
query {
issue(id: "gid://gitlab/Issue/71807251") { title }
}
If you encounter this breaking change, you will see a validation error in the response similar to:
{
"errors": [
{
"message": "Type mismatch on variable $id and argument id (ID! / IssueID!)",
"locations": [
{
"line": 2,
"column": 9
}
],
"path": [
"query",
"issue",
"id"
],
"extensions": {
"code": "variableMismatch",
"variableName": "id",
"typeName": "ID!",
"argumentName": "id",
"errorMessage": "Type mismatch"
}
}
]
}
Affected Topology
All deployments are affected by this change.
Affected Tier
GraphQL is available in the Free tier.
Checklist
-
@mention your stage's stable counterparts on this issue. For example, Customer Support, Customer Success (Technical Account Manager), Product Marketing Manager. - To see who the stable counterparts are for a product team visit product categories
- If there is no stable counterpart listed for Sales/CS please mention
@timtams
- If there is no stable counterpart listed for Support please mention
@gitlab-com/support/managers
- If there is no stable counterpart listed for Marketing please mention
@cfoster3
- If there is no stable counterpart listed for Sales/CS please mention
- To see who the stable counterparts are for a product team visit product categories
-
@mention
your GPM so that they are aware of planned deprecations. The goal is to have reviews happen at least two releases before the final removal of the feature or introduction of a breaking change.
Deprecation Milestone
Planned Removal Milestone
Links
All developers should use the GraphQL reference documentation and schemas to help write valid queries:
Users are encouraged to make use of the GraphQL explorer to build and validate queries:
The GraphQL explorer only permits use of the standards-compliant queries, so users will be able to test any queries they use for validity.