88import os
99import tempfile
1010import typing
11+ from datetime import datetime
1112from importlib .metadata import version
1213from pathlib import Path
1314from zipfile import ZipFile
1617import docker
1718import requests
1819from docker .models .containers import Container
20+ from graphql import build_client_schema , build_schema , get_introspection_query
21+ from graphql .utilities import find_breaking_changes
1922from jinja2 import Template
2023
2124from openhexa .cli .settings import settings
@@ -104,7 +107,41 @@ def get_library_versions() -> tuple[str, str]:
104107 return installed_version , installed_version
105108
106109
110+ def detect_graphql_breaking_changes (token ):
111+ """Detect breaking changes between the schema referenced in the SDK and the server using graphql-core."""
112+ stored_schema_obj = build_schema ((Path (__file__ ).parent / "graphql" / "schema.generated.graphql" ).open ().read ())
113+ server_schema_obj = build_client_schema (
114+ _query_graphql (get_introspection_query (input_value_deprecation = True ), token = token )
115+ )
116+
117+ breaking_changes = find_breaking_changes (stored_schema_obj , server_schema_obj )
118+ if breaking_changes :
119+ current_version , latest_version = get_library_versions ()
120+ click .secho (
121+ f"⚠️ Breaking changes detected between the SDK (version { current_version } ) and the server:" ,
122+ fg = "red" ,
123+ )
124+ for change in breaking_changes :
125+ click .secho (f"- { change .description } " , fg = "yellow" )
126+ click .secho (
127+ "This could lead to unexpected results.\n "
128+ f"Please update the SDK to the latest version { latest_version } "
129+ f"(using `pip install openhexa-sdk=={ latest_version } `) or use a version of the SDK compatible with the server." ,
130+ fg = "red" ,
131+ )
132+
133+
107134def graphql (query : str , variables = None , token = None ):
135+ """Check that there is no breaking change and perform a GraphQL request."""
136+ ONE_HOUR = 60 * 60
137+ now_timestamp = int (datetime .now ().timestamp ())
138+ if not settings .last_breaking_change_check or now_timestamp - settings .last_breaking_change_check > ONE_HOUR :
139+ detect_graphql_breaking_changes (token )
140+ settings .last_breaking_change_check = now_timestamp
141+ return _query_graphql (query , variables , token )
142+
143+
144+ def _query_graphql (query : str , variables = None , token = None ):
108145 """Perform a GraphQL request."""
109146 url = settings .api_url + "/graphql/"
110147 if token is None :
@@ -121,6 +158,7 @@ def graphql(query: str, variables=None, token=None):
121158 click .echo (f"Variables: { variables } " )
122159
123160 session = create_requests_session ()
161+
124162 response = session .post (
125163 url ,
126164 headers = {
0 commit comments