From 2a667a00ce5aa0f0317d9c8228385157cf5f9bd8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de>
Date: Fri, 22 Sep 2023 15:39:57 +0200
Subject: [PATCH] Sort by created_at timestamp when getting latest workflow
 version

#51
---
 app/api/endpoints/workflow.py     | 10 +++++-----
 app/crud/crud_workflow.py         |  6 +++---
 app/crud/crud_workflow_version.py |  8 +++++---
 app/schemas/workflow.py           | 10 ++++------
 app/schemas/workflow_version.py   |  4 +++-
 app/tests/api/test_workflow.py    |  1 -
 6 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/app/api/endpoints/workflow.py b/app/api/endpoints/workflow.py
index cf6b14e..58768df 100644
--- a/app/api/endpoints/workflow.py
+++ b/app/api/endpoints/workflow.py
@@ -146,7 +146,7 @@ async def create_workflow(
     # Create the workflow in the DB
     workflow_db = await CRUDWorkflow.create(db, workflow, current_user.uid)
 
-    # If it is a private repository, create a SCM file and upload it to the params bucket
+    # If it is a private repository, create an SCM file and upload it to the params bucket
     scm_provider = Provider.from_repo(repo, name=f"repo{workflow_db.workflow_id.hex}")
     if scm_provider is not None:
         background_tasks.add_task(
@@ -154,7 +154,7 @@ async def create_workflow(
         )
 
     # If there are workflow modes with alternative parameter schemas, cache them in the WORKFLOW Bucket
-    if workflow.modes is not None and len(workflow.modes) > 0:
+    if len(workflow.modes) > 0:
         for mode_db in workflow_db.versions[0].workflow_modes:
             background_tasks.add_task(
                 repo.copy_file_to_bucket,
@@ -361,7 +361,7 @@ async def update_workflow(
     # Get modes of previous version
     previous_version_modes = await CRUDWorkflowMode.list_modes(db, previous_version.git_commit_hash)
 
-    if version_update.delete_modes is not None:
+    if len(version_update.delete_modes) > 0:
         # Check if mode to delete actually exist
         mode_ids = [mode.mode_id for mode in previous_version_modes]
         for delete_mode in version_update.delete_modes:
@@ -384,13 +384,13 @@ async def update_workflow(
 
     check_repo_modes = previous_version_modes.copy()
     # If there are new modes, add them to the list for file checking
-    if version_update.append_modes is not None:
+    if len(version_update.append_modes) > 0:
         check_repo_modes += version_update.append_modes
     await check_repo(repo=repo, client=client, modes=check_repo_modes)
 
     append_modes_db: List[WorkflowMode] = []
     # Create new modes in database
-    if version_update.append_modes is not None:
+    if len(version_update.append_modes) > 0:
         append_modes_db = await CRUDWorkflowMode.create(db, version_update.append_modes)
     # Make a list with all DB modes of modes for the new workflow version
     db_modes = previous_version_modes + append_modes_db
diff --git a/app/crud/crud_workflow.py b/app/crud/crud_workflow.py
index 4e3d521..6bcce20 100644
--- a/app/crud/crud_workflow.py
+++ b/app/crud/crud_workflow.py
@@ -203,8 +203,8 @@ class CRUDWorkflow:
         await db.commit()
 
         # If there are workflow modes, create them first
-        modes_db = None
-        if workflow.modes is not None and len(workflow.modes) > 0:
+        modes_db = []
+        if len(workflow.modes) > 0:
             modes_db = await CRUDWorkflowMode.create(db, workflow.modes)
         await CRUDWorkflowVersion.create(
             db,
@@ -212,6 +212,6 @@ class CRUDWorkflow:
             version=workflow.initial_version,
             wid=workflow_db.workflow_id,
             icon_slug=icon_slug,
-            modes=[mode.mode_id for mode in modes_db] if modes_db is not None else None,
+            modes=[mode.mode_id for mode in modes_db],
         )
         return await CRUDWorkflow.get(db, workflow_db.workflow_id)
diff --git a/app/crud/crud_workflow_version.py b/app/crud/crud_workflow_version.py
index 74804e8..f4d53f9 100644
--- a/app/crud/crud_workflow_version.py
+++ b/app/crud/crud_workflow_version.py
@@ -2,7 +2,7 @@ from typing import List, Optional, Sequence, Union
 from uuid import UUID
 
 from clowmdb.models import WorkflowVersion, workflow_mode_association_table
-from sqlalchemy import insert, or_, select, update
+from sqlalchemy import desc, insert, or_, select, update
 from sqlalchemy.ext.asyncio import AsyncSession
 from sqlalchemy.orm import joinedload, selectinload
 
@@ -70,7 +70,7 @@ class CRUDWorkflowVersion:
             .where(
                 WorkflowVersion._workflow_id == wid.bytes if isinstance(wid, UUID) else wid  # type: ignore[arg-type]
             )
-            .order_by(WorkflowVersion.created_at)
+            .order_by(desc(WorkflowVersion.created_at))
             .limit(1)
             .options(selectinload(WorkflowVersion.workflow_modes))
         )
@@ -153,6 +153,8 @@ class CRUDWorkflowVersion:
         workflow_version : clowmdb.models.WorkflowVersion
             Newly create WorkflowVersion
         """
+        if modes is None:
+            modes = []
         workflow_version = WorkflowVersion(
             git_commit_hash=git_commit_hash,
             version=version,
@@ -161,7 +163,7 @@ class CRUDWorkflowVersion:
             previous_version_hash=previous_version,
         )
         db.add(workflow_version)
-        if modes is not None and len(modes) > 0:
+        if len(modes) > 0:
             await db.commit()
             await db.execute(
                 insert(workflow_mode_association_table),
diff --git a/app/schemas/workflow.py b/app/schemas/workflow.py
index c37ac5e..6936e52 100644
--- a/app/schemas/workflow.py
+++ b/app/schemas/workflow.py
@@ -58,8 +58,8 @@ class WorkflowIn(_BaseWorkflow):
         examples=["vnpau89avpa48iunga984gh9h89pvhj"],
         max_length=128,
     )
-    modes: Optional[List[WorkflowModeIn]] = Field(
-        default=None, max_length=10, description="List of modes with alternative entrypoint the new workflow has"
+    modes: List[WorkflowModeIn] = Field(
+        default=[], max_length=10, description="List of modes with alternative entrypoint the new workflow has"
     )
 
 
@@ -146,7 +146,5 @@ class WorkflowUpdate(BaseModel):
         min_length=40,
         max_length=40,
     )
-    append_modes: Optional[List[WorkflowModeIn]] = Field(
-        default=None, description="Add modes to the new workflow version"
-    )
-    delete_modes: Optional[List[UUID]] = Field(None, description="Delete modes for the new workflow version.")
+    append_modes: List[WorkflowModeIn] = Field(default=[], description="Add modes to the new workflow version")
+    delete_modes: List[UUID] = Field([], description="Delete modes for the new workflow version.")
diff --git a/app/schemas/workflow_version.py b/app/schemas/workflow_version.py
index 3a46b2a..277ef19 100644
--- a/app/schemas/workflow_version.py
+++ b/app/schemas/workflow_version.py
@@ -41,7 +41,7 @@ class WorkflowVersion(WorkflowVersionStatus):
         description="Timestamp when the version was created as UNIX timestamp",
         examples=[round(datetime(year=2023, month=1, day=1).timestamp())],
     )
-    modes: Optional[List[UUID]] = Field(default=None, description="Optional modes his workflow version has")
+    modes: List[UUID] = Field(default=[], description="Optional modes his workflow version has")
 
     @staticmethod
     def from_db_version(
@@ -70,6 +70,8 @@ class WorkflowVersion(WorkflowVersionStatus):
         then the parameter `mode_ids` will be ignored.
         """
         icon_url = None
+        if mode_ids is None:
+            mode_ids = []
         if db_version.icon_slug is not None:
             icon_url = str(settings.OBJECT_GATEWAY_URI) + "/".join([settings.ICON_BUCKET, db_version.icon_slug])
         return WorkflowVersion(
diff --git a/app/tests/api/test_workflow.py b/app/tests/api/test_workflow.py
index f1e8a7d..1812155 100644
--- a/app/tests/api/test_workflow.py
+++ b/app/tests/api/test_workflow.py
@@ -923,7 +923,6 @@ class TestWorkflowRoutesUpdate(_TestWorkflowRoutes):
         assert created_version["git_commit_hash"] == git_commit_hash
         assert created_version["status"] == WorkflowVersion.Status.CREATED
         assert created_version["icon_url"] == str(random_workflow.versions[0].icon_url)
-        assert created_version["modes"] is not None
         assert len(created_version["modes"]) == 1
         assert created_version["modes"][0] != str(random_workflow_mode.mode_id)
 
-- 
GitLab