Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditionals #4

Merged
merged 16 commits into from
Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 119 additions & 2 deletions Workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ $graph:

## Changelog

* Adds `when` field to [WorkflowStep](#WorkflowStep) for conditional
execution
* Adds `pickValue` field to [WorkflowStepInput](#WorkflowStepInput) and
[WorkflowOutputParameter](#WorkflowOutputParameter) for selecting among null and
non-null source values

See also the [CWL Command Line Tool Description, v1.2.0-dev1 changelog](CommandLineTool.html#Changelog).

## Purpose
Expand Down Expand Up @@ -163,6 +169,17 @@ $graph:
- merge_flattened


- name: PickValueMethod
type: enum
docParent: "#WorkflowStepInput"
doc: |
Picking non-null values among inbound data links, described in [WorkflowStepInput](#WorkflowStepInput).
symbols:
- first_non_null
- only_non_null
- all_non_null


- name: WorkflowOutputParameter
type: record
extends: OutputParameter
Expand All @@ -172,6 +189,9 @@ $graph:
connected to one or more parameters defined in the workflow that
will provide the value of the output parameter. It is legal to
connect a WorkflowInputParameter to a WorkflowOutputParameter.

See [WorkflowStepInput](#WorkflowStepInput) for discussion of
`linkMerge` and `pickValue`.
fields:
- name: outputSource
doc: |
Expand All @@ -191,6 +211,13 @@ $graph:
doc: |
The method to use to merge multiple sources into a single array.
If not specified, the default method is "merge_nested".

- name: pickValue
type: ["null", PickValueMethod]
jsonldPredicate: "cwl:pickValue"
doc: |
The method to use to choose non-null elements among multiple sources.

- name: type
type:
- CWLType
Expand Down Expand Up @@ -236,6 +263,11 @@ $graph:
doc: |
The method to use to merge multiple inbound links into a single array.
If not specified, the default method is "merge_nested".
- name: pickValue
type: ["null", PickValueMethod]
jsonldPredicate: "cwl:pickValue"
doc: |
The method to use to choose non-null elements among multiple sources.


- type: record
Expand All @@ -251,7 +283,7 @@ $graph:
expressions for instance) - unconnected or unused parameters do not represent an
error condition.

## Input object
# Input object

A WorkflowStepInput object must contain an `id` field in the form
`#fieldname` or `#prefix/fieldname`. When the `id` field contains a slash
Expand All @@ -260,7 +292,7 @@ $graph:
This defines a field of the workflow step input object with the value of
the `source` parameter(s).

## Merging
# Merging multiple inbound data links

To merge multiple inbound data links,
[MultipleInputFeatureRequirement](#MultipleInputFeatureRequirement) must be specified
Expand All @@ -287,6 +319,64 @@ $graph:
Source parameters which are single element types are appended as
single elements.

# Picking non-null values among inbound data links

If present, `pickValue` specifies how to picking non-null values among inbound data links.

`pickValue` is evaluated
1. Once all source values from upstream step or parameters are available.
2. After `linkMerge`.
3. Before `scatter` or `valueFrom`.

This is specifically intended to be useful in combination with
[conditional execution](#WorkflowStep), where several upstream
steps may be connected to a single input (`source` is a list), and
skipped steps produce null values.

Static type checkers should check for type consistency after infering what the type
will be after `pickValue` is applied, just as they do currently for `linkMerge`.

* **first_non_null**

For the first level of a list input, pick the first non-null element. The result is a scalar.
It is an error if there is no non-null element. Examples:
* `[null, x, null, y] -> x`
* `[null, [null], null, y] -> [null]`
* `[null, null, null] -> Runtime Error`

*Intended use case*: If-else pattern where the
value comes either from a conditional step or from a default or
fallback value. The conditional step(s) should be placed first in
the list.

* **only_non_null**

For the first level of a list input, pick the single non-null element. The result is a scalar.
It is an error if there is more than one non-null element. Examples:

* `[null, x, null] -> x`
* `[null, x, null, y] -> Runtime Error`
* `[null, [null], null] -> [null]`
* `[null, null, null] -> Runtime Error`

*Intended use case*: Switch type patterns where developer considers
more than one active code path as a workflow error
(possibly indicating an error in writing `when` condition expressions).

* **all_non_null**

For the first level of a list input, pick all non-null values.
The result is a list, which may be empty. Examples:

* `[null, x, null] -> [x]`
* `[x, null, y] -> [x, y]`
* `[null, [x], [null]] -> [[x], [null]]`
* `[null, null, null] -> []`

*Intended use case*: It is valid to have more than one source, but
sources are conditional, so null sources (from skipped steps)
should be filtered out.

fields:
- name: default
type: ["null", Any]
Expand Down Expand Up @@ -405,6 +495,24 @@ $graph:
output arrays must be flattened to a single level, but otherwise listed in the
order that the input arrays are listed in the `scatter` field.

# Conditional execution

Conditional execution makes execution of a step conditional on an
expression. A step that is not executed is "skipped". A skipped
step produces `null` for all output parameters.

The condition is evaluated after `scatter`, using the input object
of each individual scatter job. This means over a set of scatter
jobs, some may be executed and some may be skipped. When the
results are gathered, skipped steps must be `null` in the output
arrays.

The `when` field controls conditional execution. This is an
expression that must be evaluated with `inputs` bound to the step
input object (or individual scatter job), and returns a boolean
value. It is an error if this expression returns a value other
than `true` or `false`.

# Subworkflows

To specify a nested workflow as part of a workflow step,
Expand Down Expand Up @@ -469,6 +577,15 @@ $graph:
subscope: run
doc: |
Specifies the process to run.
- name: when
type:
- "null"
- Expression
jsonldPredicate: "cwl:when"
doc: |
If defined, only run the step when the expression evaluates to
`true`. If `false` the step is skipped. A skipped step
produces a `null` on each output.
- name: scatter
type:
- string?
Expand Down
2 changes: 2 additions & 0 deletions conformance_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3310,3 +3310,5 @@
Test that optional number output is returned as 0, not null
tags: [ required, inline_javascript, command_line_tool ]
id: 253

- $import: tests/conditionals/test-index.yaml
Loading