Skip to content

Introduction

This project aims to deliver a simple yet powerful CLI tool to ingest CWL Workflows and generate PlantUML diagrams.

Installation

pip install cwl2puml

or, for early adopters:

pip install --no-cache-dir git+https://github.com/Terradue/cwl2puml@main

CLI execution

Usage: cwl2puml [OPTIONS] WORKFLOW

  Converts a CWL, given its document model, to a PlantUML diagram.

  Args:     `workflow` (`str`): The CWL workflow file (it can be an URL or a
  file on the File System)     `workflow-id` (`str`): The ID of the main
  Workflow to render     `output` (`Path`): The output file where streaming
  the PlantUML diagram     `convert_image` (`bool`): Flag to ton on/off the
  image generation (on, by default)     `puml_server` (`str`): The host of a
  PlantUML as a service server (uml.planttext.com by default)
  `image_format` (`ImageFormat`): The output image format of the PlantUML
  diagram ('png' by default)

  Returns:     `None`: none

Options:
  --workflow-id TEXT        ID of the main Workflow  [required]
  --output PATH             Output directory path  [required]
  --convert-image BOOLEAN   Flag to ton on/off the image generation (on, by
                            default)
  --puml-server TEXT        The host of a PlantUML as a service server
                            (uml.planttext.com by default)
  --image-format [png|svg]  The output image format of the PlantUML diagram
                            ('png' by default)
  --help                    Show this message and exit.

i.e.

cwl2puml \
    --workflow-id main \
    --output . \
    --convert-image no \
    https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl

Output would be

2025-09-22 16:22:42.498 | DEBUG    | cwl_loader:load_cwl_from_location:213 - Loading CWL document from https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl...
2025-09-22 16:22:42.687 | DEBUG    | cwl_loader:_load_cwl_from_stream:216 - Reading stream from https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl...
2025-09-22 16:22:42.727 | DEBUG    | cwl_loader:load_cwl_from_stream:190 - CWL data of type <class 'ruamel.yaml.comments.CommentedMap'> successfully loaded from stream
2025-09-22 16:22:42.727 | DEBUG    | cwl_loader:load_cwl_from_yaml:135 - No needs to update the Raw CWL document since it targets already the v1.2
2025-09-22 16:22:42.727 | DEBUG    | cwl_loader:load_cwl_from_yaml:137 - Parsing the raw CWL document to the CWL Utils DOM...
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:load_cwl_from_yaml:150 - Raw CWL document successfully parsed to the CWL Utils DOM!
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:load_cwl_from_yaml:152 - Dereferencing the steps[].run...
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:70 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#stac must be externally imported...
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:74 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:70 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#rio_stack must be externally imported...
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:74 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:70 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#rio_warp_stack must be externally imported...
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:74 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:70 - Checking if https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl#rio_color must be externally imported...
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_on_process:74 - run_url: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl - uri: https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:load_cwl_from_yaml:159 - steps[].run successfully dereferenced! Now dereferencing the FQNs...
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:load_cwl_from_yaml:163 - CWL document successfully dereferenced!
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:load_cwl_from_yaml:166 - Sorting Process instances by dependencies....
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:load_cwl_from_yaml:168 - Sorting process is over.
2025-09-22 16:22:43.285 | DEBUG    | cwl_loader:_load_cwl_from_stream:224 - Stream from https://raw.githubusercontent.com/eoap/how-to/refs/heads/main/cwl-workflows/conditional-workflows.cwl successfully load!
2025-09-22 16:22:43.286 | INFO     | cwl2puml.cli:main:66 - ------------------------------------------------------------------------
2025-09-22 16:22:43.286 | INFO     | cwl2puml.cli:main:72 - Saving PlantUML activity diagram to activity.puml...
2025-09-22 16:22:43.301 | SUCCESS  | cwl2puml.cli:main:83 - PlantUML activity diagram successfully rendered to activity.puml!
2025-09-22 16:22:43.301 | INFO     | cwl2puml.cli:main:72 - Saving PlantUML component diagram to component.puml...
2025-09-22 16:22:43.325 | SUCCESS  | cwl2puml.cli:main:83 - PlantUML component diagram successfully rendered to component.puml!
2025-09-22 16:22:43.325 | INFO     | cwl2puml.cli:main:72 - Saving PlantUML class diagram to class.puml...
2025-09-22 16:22:43.346 | SUCCESS  | cwl2puml.cli:main:83 - PlantUML class diagram successfully rendered to class.puml!
2025-09-22 16:22:43.347 | INFO     | cwl2puml.cli:main:72 - Saving PlantUML sequence diagram to sequence.puml...
2025-09-22 16:22:43.382 | SUCCESS  | cwl2puml.cli:main:83 - PlantUML sequence diagram successfully rendered to sequence.puml!
2025-09-22 16:22:43.382 | INFO     | cwl2puml.cli:main:72 - Saving PlantUML state diagram to state.puml...
2025-09-22 16:22:43.425 | SUCCESS  | cwl2puml.cli:main:83 - PlantUML state diagram successfully rendered to state.puml!
2025-09-22 16:22:43.425 | INFO     | cwl2puml.cli:main:89 - Total time: 0.9278 seconds
2025-09-22 16:22:43.426 | INFO     | cwl2puml.cli:main:90 - Finished at: 2025-09-22T16:22:43.425

then, for example, try to cat ./activity.puml :

/'
 ' Diagram generated by cwl2puml v0.23.0
 ' timestamp: 2025-09-22T16:22:43.301
 '/
@startuml
start

split

    :stac-item; <<input>>
split again

    :epsg_code; <<input>>
split again

    :bands; <<input>>
end split

repeat

:step: step_curl
CommandLineTool: stac;

repeat while (dotproduct step_curl/common_band_name)

if ($( inputs.epsg_code == "native"))

:step: step_stack
CommandLineTool: rio_stack;

endif

if ($( inputs.epsg_code != "native"))

:step: step_warp_stack
CommandLineTool: rio_warp_stack;

endif

:step: step_color
CommandLineTool: rio_color;

split

    :rgb-tif; <<output>>
split again

    :stack; <<output>>
end split

stop
@enduml