Jinja2 macros are great way to automatically construct parts of your workflow based on input parameters (macro arguments).
Here’s an example macro that adds a task to print a given word (default “hello”) to stdout, after a given task in your graph:
{% macro say_it(
after_task,
say_what = "hello"
)
%}
[scheduling]
[[graph]]
R1 = "{{after_task}} => say_{{say_what}}"
[runtime]
[[say_{{say_what}}]]
script = "echo {{say_what}}"
{% endmacro %}
And a workflow that uses it twice:
#!Jinja2
{% import 'macros.j2' as macros %}
{{ macros.say_it(after_task="b")}}
{{ macros.say_it(after_task="c", say_what="goodbye")}}
[scheduling]
[[graph]]
R1 = "a => b => c"
[runtime]
[[a, b, c]]
Here’s the result after template processing and config parsing, via cylc config:
[scheduling]
initial cycle point = 1
final cycle point = 1
cycling mode = integer
[[graph]]
R1 = """
b => say_hello
c => say_goodbye
a => b => c
"""
[runtime]
[[root]]
[[say_hello]]
script = echo hello
completion = succeeded
[[say_goodbye]]
script = echo goodbye
completion = succeeded
[[a]]
completion = succeeded
[[b]]
completion = succeeded
[[c]]
completion = succeeded