feat: extract headless workflow engine
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
|
||||
from alembic.runtime.migration import MigrationContext
|
||||
from sqlalchemy import create_engine, inspect
|
||||
|
||||
from govoplan_core.db.migrations import migrate_database
|
||||
from dataclasses import replace
|
||||
|
||||
from govoplan_workflow_engine.backend.manifest import get_manifest
|
||||
|
||||
|
||||
class WorkflowMigrationTests(unittest.TestCase):
|
||||
def test_migration_creates_definition_tables_and_head(self) -> None:
|
||||
with tempfile.TemporaryDirectory(
|
||||
prefix="govoplan-workflow-engine-migration-"
|
||||
) as directory:
|
||||
url = f"sqlite:///{Path(directory) / 'workflow.db'}"
|
||||
migrate_database(
|
||||
database_url=url,
|
||||
enabled_modules=("workflow_engine",),
|
||||
manifest_factories=(get_manifest,),
|
||||
)
|
||||
engine = create_engine(url)
|
||||
try:
|
||||
with engine.connect() as connection:
|
||||
self.assertIn(
|
||||
"0b4e7c9a2d6f",
|
||||
set(MigrationContext.configure(connection).get_current_heads()),
|
||||
)
|
||||
self.assertEqual(
|
||||
{
|
||||
"workflow_definition_revisions",
|
||||
"workflow_definitions",
|
||||
"workflow_instance_events",
|
||||
"workflow_instance_steps",
|
||||
"workflow_instances",
|
||||
},
|
||||
{
|
||||
name
|
||||
for name in inspect(connection).get_table_names()
|
||||
if name.startswith("workflow_")
|
||||
},
|
||||
)
|
||||
revision_columns = {
|
||||
item["name"]
|
||||
for item in inspect(connection).get_columns(
|
||||
"workflow_definition_revisions"
|
||||
)
|
||||
}
|
||||
self.assertTrue(
|
||||
{
|
||||
"bpmn_xml",
|
||||
"bpmn_hash",
|
||||
"bpmn_adapter_id",
|
||||
"bpmn_adapter_version",
|
||||
"bpmn_runtime_kind",
|
||||
"bpmn_executable",
|
||||
"execution_mode",
|
||||
"view_id",
|
||||
"view_revision_id",
|
||||
}.issubset(revision_columns)
|
||||
)
|
||||
instance_columns = {
|
||||
item["name"]
|
||||
for item in inspect(connection).get_columns(
|
||||
"workflow_instances"
|
||||
)
|
||||
}
|
||||
self.assertIn("start_origin", instance_columns)
|
||||
definition_columns = {
|
||||
item["name"]
|
||||
for item in inspect(connection).get_columns(
|
||||
"workflow_definitions"
|
||||
)
|
||||
}
|
||||
self.assertIn(
|
||||
"standard_origin_module_id",
|
||||
definition_columns,
|
||||
)
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
def test_existing_workflow_migration_head_transfers_without_replay(self) -> None:
|
||||
with tempfile.TemporaryDirectory(
|
||||
prefix="govoplan-workflow-engine-upgrade-"
|
||||
) as directory:
|
||||
url = f"sqlite:///{Path(directory) / 'workflow.db'}"
|
||||
engine_manifest = get_manifest()
|
||||
assert engine_manifest.migration_spec is not None
|
||||
legacy_revisions = Path(directory) / "legacy-revisions"
|
||||
legacy_revisions.mkdir()
|
||||
current_revisions = Path(
|
||||
engine_manifest.migration_spec.script_location or ""
|
||||
)
|
||||
for path in current_revisions.glob("*.py"):
|
||||
if path.name.startswith("0b4e7c9a2d6f_"):
|
||||
continue
|
||||
shutil.copy2(path, legacy_revisions / path.name)
|
||||
legacy_manifest = replace(
|
||||
engine_manifest,
|
||||
id="workflow",
|
||||
name="Workflow",
|
||||
permission_namespace=None,
|
||||
migration_spec=replace(
|
||||
engine_manifest.migration_spec,
|
||||
module_id="workflow",
|
||||
script_location=str(legacy_revisions),
|
||||
),
|
||||
)
|
||||
migrate_database(
|
||||
database_url=url,
|
||||
enabled_modules=("workflow",),
|
||||
manifest_factories=(lambda: legacy_manifest,),
|
||||
)
|
||||
engine = create_engine(url)
|
||||
try:
|
||||
first_tables = set(inspect(engine).get_table_names())
|
||||
with engine.connect() as connection:
|
||||
self.assertIn(
|
||||
"f1b7d3e5a9c2",
|
||||
set(
|
||||
MigrationContext.configure(
|
||||
connection
|
||||
).get_current_heads()
|
||||
),
|
||||
)
|
||||
self.assertNotIn(
|
||||
"standard_origin_module_id",
|
||||
{
|
||||
item["name"]
|
||||
for item in inspect(engine).get_columns(
|
||||
"workflow_definitions"
|
||||
)
|
||||
},
|
||||
)
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
result = migrate_database(
|
||||
database_url=url,
|
||||
enabled_modules=("workflow_engine",),
|
||||
manifest_factories=(get_manifest,),
|
||||
)
|
||||
|
||||
self.assertIn("0b4e7c9a2d6f", result.current_revision or "")
|
||||
engine = create_engine(url)
|
||||
try:
|
||||
self.assertEqual(first_tables, set(inspect(engine).get_table_names()))
|
||||
self.assertIn(
|
||||
"standard_origin_module_id",
|
||||
{
|
||||
item["name"]
|
||||
for item in inspect(engine).get_columns(
|
||||
"workflow_definitions"
|
||||
)
|
||||
},
|
||||
)
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user