How to Dump Workflows

How to Dump Workflows

To help you debug your workflows, you can generate a visual representation of them as SVG or PNG images. First, install any of these free and open source applications needed to generate the images:

  • Graphviz, provides the dot command;
  • PlantUML, provides the plantuml.jar file (which requires Java).

If you are defining the workflow inside a Symfony application, run this command to dump it as an image:

  1. # using Graphviz's 'dot' and SVG images
  2. $ php bin/console workflow:dump workflow-name | dot -Tsvg -o graph.svg
  3. # using Graphviz's 'dot' and PNG images
  4. $ php bin/console workflow:dump workflow-name | dot -Tpng -o graph.png
  5. # using PlantUML's 'plantuml.jar'
  6. $ php bin/console workflow:dump workflow_name --dump-format=puml | java -jar plantuml.jar -p > graph.png
  7. # highlight 'place1' and 'place2' in the dumped workflow
  8. $ php bin/console workflow:dump workflow-name place1 place2 | dot -Tsvg -o graph.svg

The DOT image will look like this:

../_images/blogpost.png

The PlantUML image will look like this:

../_images/blogpost_puml.png

If you are creating workflows outside of a Symfony application, use the GraphvizDumper or StateMachineGraphvizDumper class to create the DOT files and PlantUmlDumper to create the PlantUML files:

  1. // Add this code to a PHP script; for example: dump-graph.php
  2. $dumper = new GraphvizDumper();
  3. echo $dumper->dump($definition);
  4. # if you prefer PlantUML, use this code:
  5. # $dumper = new PlantUmlDumper();
  6. # echo $dumper->dump($definition);
  1. # replace 'dump-graph.php' by the name of your PHP script
  2. $ php dump-graph.php | dot -Tsvg -o graph.svg
  3. $ php dump-graph.php | java -jar plantuml.jar -p > graph.png

Styling

You can use metadata with the following keys to style the workflow:

  • for places:
    • bg_color: a color;
    • description: a string that describes the state.
  • for transitions:
    • label: a string that replaces the name of the transition;
    • color: a color;
    • arrow_color: a color.

Strings can include \n characters to display the contents in multiple lines. Colors can be defined as:

Below is the configuration for the pull request state machine with styling added.

  • YAML

    1. # config/packages/workflow.yaml
    2. framework:
    3. workflows:
    4. pull_request:
    5. type: 'state_machine'
    6. marking_store:
    7. type: 'method'
    8. property: 'currentPlace'
    9. supports:
    10. - App\Entity\PullRequest
    11. initial_marking: start
    12. places:
    13. start: ~
    14. coding: ~
    15. test: ~
    16. review:
    17. metadata:
    18. description: Human review
    19. merged: ~
    20. closed:
    21. metadata:
    22. bg_color: DeepSkyBlue
    23. transitions:
    24. submit:
    25. from: start
    26. to: test
    27. update:
    28. from: [coding, test, review]
    29. to: test
    30. metadata:
    31. arrow_color: Turquoise
    32. wait_for_review:
    33. from: test
    34. to: review
    35. metadata:
    36. color: Orange
    37. request_change:
    38. from: review
    39. to: coding
    40. accept:
    41. from: review
    42. to: merged
    43. metadata:
    44. label: Accept PR
    45. reject:
    46. from: review
    47. to: closed
    48. reopen:
    49. from: closed
    50. to: review
  • XML

    1. <!-- config/packages/workflow.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
    7. http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"
    8. >
    9. <framework:config>
    10. <framework:workflow name="pull_request" type="state_machine">
    11. <framework:marking-store>
    12. <framework:type>method</framework:type>
    13. <framework:property>currentPlace</framework:property>
    14. </framework:marking-store>
    15. <framework:support>App\Entity\PullRequest</framework:support>
    16. <framework:initial_marking>start</framework:initial_marking>
    17. <framework:place>start</framework:place>
    18. <framework:place>coding</framework:place>
    19. <framework:place>test</framework:place>
    20. <framework:place name="review">
    21. <framework:metadata>
    22. <framework:description>Human review</framework:description>
    23. </framework:metadata>
    24. </framework:place>
    25. <framework:place>merged</framework:place>
    26. <framework:place name="closed">
    27. <framework:metadata>
    28. <framework:bg_color>DeepSkyBlue</framework:bg_color>
    29. </framework:metadata>
    30. </framework:place>
    31. <framework:transition name="submit">
    32. <framework:from>start</framework:from>
    33. <framework:to>test</framework:to>
    34. </framework:transition>
    35. <framework:transition name="update">
    36. <framework:from>coding</framework:from>
    37. <framework:from>test</framework:from>
    38. <framework:from>review</framework:from>
    39. <framework:to>test</framework:to>
    40. <framework:metadata>
    41. <framework:arrow_color>Turquoise</framework:arrow_color>
    42. </framework:metadata>
    43. </framework:transition>
    44. <framework:transition name="wait_for_review">
    45. <framework:from>test</framework:from>
    46. <framework:to>review</framework:to>
    47. <framework:metadata>
    48. <framework:color>Orange</framework:color>
    49. </framework:metadata>
    50. </framework:transition>
    51. <framework:transition name="request_change">
    52. <framework:from>review</framework:from>
    53. <framework:to>coding</framework:to>
    54. </framework:transition>
    55. <framework:transition name="accept">
    56. <framework:from>review</framework:from>
    57. <framework:to>merged</framework:to>
    58. <framework:metadata>
    59. <framework:label>Accept PR</framework:label>
    60. </framework:metadata>
    61. </framework:transition>
    62. <framework:transition name="reject">
    63. <framework:from>review</framework:from>
    64. <framework:to>closed</framework:to>
    65. </framework:transition>
    66. <framework:transition name="reopen">
    67. <framework:from>closed</framework:from>
    68. <framework:to>review</framework:to>
    69. </framework:transition>
    70. </framework:workflow>
    71. </framework:config>
    72. </container>
  • PHP

    1. // config/packages/workflow.php
    2. $container->loadFromExtension('framework', [
    3. // ...
    4. 'workflows' => [
    5. 'pull_request' => [
    6. 'type' => 'state_machine',
    7. 'marking_store' => [
    8. 'type' => 'method',
    9. 'property' => 'currentPlace',
    10. ],
    11. 'supports' => ['App\Entity\PullRequest'],
    12. 'initial_marking' => 'start',
    13. 'places' => [
    14. 'start',
    15. 'coding',
    16. 'test',
    17. 'review' => [
    18. 'metadata' => [
    19. 'description' => 'Human review',
    20. ],
    21. ],
    22. 'merged',
    23. 'closed' => [
    24. 'metadata' => [
    25. 'bg_color' => 'DeepSkyBlue',
    26. ],
    27. ],
    28. ],
    29. 'transitions' => [
    30. 'submit'=> [
    31. 'from' => 'start',
    32. 'to' => 'test',
    33. ],
    34. 'update'=> [
    35. 'from' => ['coding', 'test', 'review'],
    36. 'to' => 'test',
    37. 'metadata' => [
    38. 'arrow_color' => 'Turquoise',
    39. ],
    40. ],
    41. 'wait_for_review'=> [
    42. 'from' => 'test',
    43. 'to' => 'review',
    44. 'metadata' => [
    45. 'color' => 'Orange',
    46. ],
    47. ],
    48. 'request_change'=> [
    49. 'from' => 'review',
    50. 'to' => 'coding',
    51. ],
    52. 'accept'=> [
    53. 'from' => 'review',
    54. 'to' => 'merged',
    55. 'metadata' => [
    56. 'label' => 'Accept PR',
    57. ],
    58. ],
    59. 'reject'=> [
    60. 'from' => 'review',
    61. 'to' => 'closed',
    62. ],
    63. 'reopen'=> [
    64. 'from' => 'start',
    65. 'to' => 'review',
    66. ],
    67. ],
    68. ],
    69. ],
    70. ]);

The PlantUML image will look like this:

../_images/pull_request_puml_styled.png

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.