Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
584d182
v1
yolanfery May 9, 2025
0434af6
v2
yolanfery May 9, 2025
90ff1fe
v3 untested
yolanfery May 9, 2025
8ff6584
v3 working
yolanfery May 9, 2025
22f09cc
TODO
yolanfery May 9, 2025
dbf1317
Fix for deprecated features
yolanfery May 9, 2025
3d69573
Minor
yolanfery May 9, 2025
7558f10
Minor
yolanfery May 9, 2025
0dff3f6
Fix
yolanfery May 9, 2025
83b2eea
Cache
yolanfery May 9, 2025
6a63766
Cache
yolanfery May 9, 2025
7df3531
2/4 tests
yolanfery May 12, 2025
edc2554
fix
yolanfery May 12, 2025
d5728e3
Test 3/4
yolanfery May 12, 2025
5dcbeb1
Test 4/4
yolanfery May 12, 2025
4b88b9a
clean
yolanfery May 12, 2025
3a453ba
Fix
yolanfery May 12, 2025
b0bb0a0
Dependency
yolanfery May 12, 2025
b23bf7e
Dependency
yolanfery May 12, 2025
9204700
Lint
yolanfery May 12, 2025
ace843c
Merge remote-tracking branch 'origin/main' into HEXA-1238-implement-s…
yolanfery May 15, 2025
5c58c48
With command
yolanfery May 15, 2025
7d28522
TODO
yolanfery May 15, 2025
bea9eff
Fix
yolanfery May 15, 2025
d1ee33b
Fix test
yolanfery May 15, 2025
c228c36
Revert "Fix test"
yolanfery May 15, 2025
b28cdbe
Revert "Fix"
yolanfery May 15, 2025
45c9878
secho
yolanfery May 15, 2025
1a72de8
Rely on settings and not file
yolanfery May 15, 2025
b4d8bde
Fix 1/2 test
yolanfery May 15, 2025
c2053bf
Fix 2/2 test
yolanfery May 15, 2025
7b6cb7c
small fix
yolanfery May 15, 2025
064360d
update schema
yolanfery May 15, 2025
fcfa192
TODOs
yolanfery May 15, 2025
9b9e8f6
ariadne-codegen
yolanfery May 15, 2025
1378b52
Use the new client
yolanfery May 16, 2025
e38ae2f
Better CI
yolanfery May 16, 2025
29acbbb
Fix tests
yolanfery May 16, 2025
a237be2
Merge remote-tracking branch 'origin/main' into HEXA-1254-ariadne-cod…
yolanfery May 16, 2025
757ffb6
Fix GHA
yolanfery May 16, 2025
3457f31
Fix GHA
yolanfery May 16, 2025
88176b0
Fix GHA
yolanfery May 16, 2025
a914101
Fix GHA
yolanfery May 16, 2025
bae70d5
Try
yolanfery May 16, 2025
7a0513d
Better ci
yolanfery May 16, 2025
e8353aa
Better ci
yolanfery May 16, 2025
f2bbeab
Fix
yolanfery May 16, 2025
5ef667b
Fix
yolanfery May 16, 2025
dc7f4fc
Test
yolanfery May 16, 2025
106b8bf
Fix
yolanfery May 16, 2025
125bc9e
Fix
yolanfery May 16, 2025
51272c4
Fix
yolanfery May 16, 2025
5aeb634
rebase
yolanfery May 20, 2025
0861f19
Fix
yolanfery May 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ jobs:
with:
python-version: 3.13

- name: Install Ariadne-codegen
run: pip install ariadne-codegen

- uses: pre-commit/action@v3.0.1
test:
name: Run test suite
Expand Down
13 changes: 12 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,15 @@ repos:
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]
- id: ruff-format
- id: ruff-format

- repo: local
hooks:
- id: ariadne-codegen
name: ariadne-codegen
entry: bash -c
echo "Running ariadne-codegen" && \
ariadne-codegen
language: system
types: [graphql]
pass_filenames: false
62 changes: 56 additions & 6 deletions openhexa/cli/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from graphql.utilities import find_breaking_changes
from jinja2 import Template

from openhexa.cli.graphql.graphql_client import Client
from openhexa.cli.settings import settings
from openhexa.sdk.pipelines import get_local_workspace_config
from openhexa.sdk.pipelines.runtime import get_pipeline
Expand Down Expand Up @@ -107,7 +108,16 @@ def get_library_versions() -> tuple[str, str]:
return installed_version, installed_version


def detect_graphql_breaking_changes(token):
def _detect_graphql_breaking_changes_if_needed(token):
"""Detect breaking changes if not done recently between the schema referenced in the SDK and the server using graphql-core."""
ONE_HOUR = 60 * 60
now_timestamp = int(datetime.now().timestamp())
if not settings.last_breaking_change_check or now_timestamp - settings.last_breaking_change_check > ONE_HOUR:
_detect_graphql_breaking_changes(token)
settings.last_breaking_change_check = now_timestamp


def _detect_graphql_breaking_changes(token):
"""Detect breaking changes between the schema referenced in the SDK and the server using graphql-core."""
stored_schema_obj = build_schema((Path(__file__).parent / "graphql" / "schema.generated.graphql").open().read())
server_schema_obj = build_client_schema(
Expand All @@ -133,11 +143,7 @@ def detect_graphql_breaking_changes(token):

def graphql(query: str, variables=None, token=None):
"""Check that there is no breaking change and perform a GraphQL request."""
ONE_HOUR = 60 * 60
now_timestamp = int(datetime.now().timestamp())
if not settings.last_breaking_change_check or now_timestamp - settings.last_breaking_change_check > ONE_HOUR:
detect_graphql_breaking_changes(token)
settings.last_breaking_change_check = now_timestamp
_detect_graphql_breaking_changes_if_needed(token)
return _query_graphql(query, variables, token)


Expand Down Expand Up @@ -739,3 +745,47 @@ def is_dhis2_connection_up(workspace_slug: str, connection_slug: str) -> bool:
},
)
return response["data"]["connectionBySlug"]["status"] == "UP"


class OpenHexaClient(Client):
"""OpenHexaClient is a class that provides methods to interact with the OpenHexa GraphQL API."""

def __init__(self, token=None):
"""Initialize the OpenHexaClient with the OpenHexa API URL and headers."""
self._url = settings.api_url + "/graphql/"
self._token = token or settings.access_token

if not self._token:
raise InvalidTokenError("No token found for workspace")

super().__init__(
url=self._url,
headers={
"User-Agent": f"openhexa-cli/{version('openhexa.sdk')}",
"Authorization": f"Bearer {self._token}",
},
)
logging.getLogger("httpx").setLevel(
logging.WARNING
) # HTTPX logs queries by default, we disable them here with WARNING level

def execute(self, query, **kwargs):
"""Decorate parent execute method to log the GraphQL query and response."""
_detect_graphql_breaking_changes(token=self._token)

if settings.debug:
click.echo("")
click.echo("Graphql Query:")
click.echo(f"URL: {self.url}")
click.echo(f"Query: {query}")
variables = kwargs.get("variables", {})
click.echo(f"Variables: {variables}")

response = super().execute(query=query, **kwargs)

if settings.debug:
click.echo("")
click.echo("Graphql Response:")
click.echo(f"Response: {response}")

return response
16 changes: 7 additions & 9 deletions openhexa/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
DockerError,
InvalidDefinitionError,
NoActiveWorkspaceError,
OpenHexaClient,
OutputDirectoryError,
PipelineDirectoryError,
create_pipeline,
Expand All @@ -24,7 +25,6 @@
ensure_is_pipeline_dir,
get_library_versions,
get_pipeline_from_code,
get_pipelines,
get_pipelines_pages,
get_workspace,
run_pipeline,
Expand Down Expand Up @@ -596,21 +596,19 @@ def pipelines_list():
if settings.current_workspace is None:
_terminate("No workspace activated", err=True)

workspace_pipelines = get_pipelines()
workspace_pipelines = (
OpenHexaClient().get_workspace_pipelines(workspace_slug=settings.current_workspace).pipelines.items
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Very nice, cool example of usage

if len(workspace_pipelines) == 0:
click.echo(f"No pipelines in workspace {settings.current_workspace}")
return
click.echo("Pipelines:")
for pipeline in workspace_pipelines:
if pipeline["type"] == "zipFile":
current_version = pipeline["currentVersion"].get("number") if pipeline["currentVersion"] else None
if current_version is not None:
current_version = f"v{current_version}"
else:
current_version = "N/A"
if pipeline.type == "zipFile":
current_version = f"v{pipeline.current_version.version_number}" if pipeline.current_version else "N/A"
else:
current_version = "Jupyter notebook"
click.echo(f"* {pipeline['code']} - {pipeline['name']} ({current_version})")
click.echo(f"* {pipeline.code} - {pipeline.name} ({current_version})")


def _terminate(message: str, exception: Exception = None, err: bool = False):
Expand Down
Loading