Skip to content

Commit b358923

Browse files
authored
fix(cli): correct bad plan ID format (#3594)
1 parent 80770a5 commit b358923

File tree

4 files changed

+72
-3
lines changed

4 files changed

+72
-3
lines changed

renku/command/checks/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from .project import check_project_id_group
2929
from .storage import check_lfs_info
3030
from .validate_shacl import check_datasets_structure, check_project_structure
31-
from .workflow import check_activity_catalog, check_plan_modification_date
31+
from .workflow import check_activity_catalog, check_plan_id, check_plan_modification_date
3232

3333
# Checks will be executed in the order as they are listed in __all__. They are mostly used in ``doctor`` command to
3434
# inspect broken things. The order of operations matters when fixing issues, so, don't sort this list.
@@ -47,5 +47,6 @@
4747
"check_project_id_group",
4848
"check_project_structure",
4949
"check_plan_modification_date",
50+
"check_plan_id",
5051
"check_activity_dates",
5152
)

renku/command/checks/workflow.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,44 @@ def fix_plan_dates(plans: List[AbstractPlan], plan_gateway):
127127
if plan.date_removed and plan.date_removed < plan.date_created:
128128
plan.date_removed = plan.date_created + timedelta(seconds=1)
129129
plan.freeze()
130+
131+
132+
@inject.autoparams("plan_gateway")
133+
def check_plan_id(fix, plan_gateway: IPlanGateway, **_) -> Tuple[bool, bool, Optional[str]]:
134+
"""Check if all plans have correct IDs.
135+
136+
Args:
137+
fix(bool): Whether to fix found issues.
138+
plan_gateway(IPlanGateway): Injected PlanGateway.
139+
_: keyword arguments.
140+
141+
Returns:
142+
Tuple[bool, Optional[str]]: Tuple of whether there are plans with invalid IDs, if an automated fix is
143+
available and a string of their IDs
144+
"""
145+
plans: List[AbstractPlan] = plan_gateway.get_all_plans()
146+
147+
to_be_processed = []
148+
for plan in plans:
149+
if isinstance(plan.id, str) and plan.id.startswith("/plans//plans"):
150+
to_be_processed.append(plan)
151+
152+
if not to_be_processed:
153+
return True, False, None
154+
if not fix:
155+
ids = [plan.id for plan in to_be_processed]
156+
message = (
157+
WARNING
158+
+ "The following workflows have incorrect IDs (use 'renku doctor --fix' to fix them):\n\t"
159+
+ "\n\t".join(ids)
160+
)
161+
return False, True, message
162+
163+
for plan in to_be_processed:
164+
plan.unfreeze()
165+
plan.id = plan.id.replace("//plans/", "/")
166+
plan.freeze()
167+
project_context.database.commit()
168+
communication.info("Workflow IDs were fixed")
169+
170+
return True, False, None

renku/ui/service/serializers/workflows.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"""Renku service workflow serializers."""
1818
from enum import Enum
1919

20-
from marshmallow import Schema, fields
20+
from marshmallow import Schema, fields, pre_dump
2121
from marshmallow_oneofschema import OneOfSchema
2222

2323
from renku.domain_model.dataset import DatasetCreatorsJson
@@ -43,6 +43,23 @@ class AbstractPlanResponse(Schema):
4343
touches_existing_files = fields.Boolean()
4444
duration = fields.Integer(dump_default=None)
4545

46+
@pre_dump(pass_many=True)
47+
def fix_ids(self, objs, many, **kwargs):
48+
"""Renku up to 2.4.1 had a bug that created wrong ids for workflow file entities, this fixes those on export."""
49+
50+
def _replace_id(obj):
51+
obj.unfreeze()
52+
obj.id = obj.id.replace("//plans/", "/")
53+
obj.freeze()
54+
55+
if many:
56+
for obj in objs:
57+
_replace_id(obj)
58+
return objs
59+
60+
_replace_id(objs)
61+
return objs
62+
4663

4764
class WorflowPlanEntryResponse(AbstractPlanResponse):
4865
"""Serialize a plan to a response object."""

tests/core/test_plan.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import pytest
2121

22-
from renku.command.checks import check_plan_modification_date
22+
from renku.command.checks import check_plan_id, check_plan_modification_date
2323
from renku.core import errors
2424
from renku.core.workflow.plan import (
2525
get_activities,
@@ -189,3 +189,13 @@ def test_modification_date_fix(project_with_injection):
189189
assert dummy_date == plan.date_modified
190190
assert unrelated.date_created == unrelated.date_modified
191191
assert date_created == plan.date_created
192+
193+
194+
def test_plan_id_fix(project_with_injection):
195+
"""Check that plans with incorrect IDs are fixed."""
196+
_, _, plan, _, _, unrelated = create_dummy_plans()
197+
198+
plan.id = "/plans/" + plan.id
199+
assert plan.id.startswith("/plans//plans")
200+
check_plan_id(fix=True)
201+
assert not plan.id.startswith("/plans//plans")

0 commit comments

Comments
 (0)