Developer Guide¶
See algorithms for a description of the compilation algorithms and high-level implementation considerations.
Coding Standards¶
See coding standards
Git Etiquette¶
See git etiquette
Runtime Notes And Known Issues¶
Globbing Unexpected File Order¶
Do not rely on glob order when output order matters. CWL runners may return
globbed files in a different order than the input values that produced them.
When order is semantically important, write an explicit manifest or index file from the tool and read that file downstream.
The simplified example below shows the problem:
input: [3, 2, 1] # Here is the order of the input array.
#!/usr/bin/env cwl-runner
cwlVersion: v1.2
class: CommandLineTool
baseCommand: ["python", "example.py"]
requirements:
- class: InitialWorkDirRequirement
listing:
# See https://www.commonwl.org/user_guide/topics/creating-files-at-runtime.html
- entryname: example.py
entry: |
import sys
from pathlib import Path
for arg in sys.argv[1:]:
Path(f'{arg}.txt').touch()
inputs:
input:
type: Any[]
inputBinding:
position: 0
outputs:
output:
type: File[]
outputBinding:
glob: "*.txt"
cwltool touch_array.cwl touch_array_inputs.yml
INFO [job test.cwl] /tmp/0x0q86bg$ python \
example.py \
3 \
2 \
1
INFO [job test.cwl] completed success
{
"output": [
{
"location": "file:///home/walkerbd/sophios/cwl_adapters/1.txt",
"basename": "1.txt",
"class": "File",
"checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
"size": 0,
"path": "/home/walkerbd/sophios/cwl_adapters/1.txt"
},
{
"location": "file:///home/walkerbd/sophios/cwl_adapters/2.txt",
"basename": "2.txt",
"class": "File",
"checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
"size": 0,
"path": "/home/walkerbd/sophios/cwl_adapters/2.txt"
},
{
"location": "file:///home/walkerbd/sophios/cwl_adapters/3.txt",
"basename": "3.txt",
"class": "File",
"checksum": "sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709",
"size": 0,
"path": "/home/walkerbd/sophios/cwl_adapters/3.txt"
}
]
The output array is sorted by filename, not by the original input order.
Partial Failures¶
When partial failures are enabled, the command for a workflow step can succeed while a CWL JavaScript post-processing expression still fails. Sophios can compile the CWL structure, but it cannot automatically repair arbitrary JavaScript embedded in a tool.
For example, this output expression assumes that self[0] exists:
outputs:
topology_changed:
type: boolean
outputBinding:
glob: valid.txt
loadContents: true
outputEval: |
${
// Read the contents of the file
const lines = self[0].contents.split("\n");
// Read boolean value from the first line
const valid = lines[0].trim() === "True";
return valid;
}
stdout was: ''
stderr was: 'evalmachine.<anonymous>:45
const lines = self[0].contents.split("\n");
^
TypeError: Cannot read properties of undefined (reading 'contents')
Fix the tool by checking that the globbed object exists before reading it:
outputs:
topology_changed:
type: boolean
outputBinding:
glob: valid.txt
loadContents: true
outputEval: |
${
// check if self[0] exists
if (!self[0]) {
return null;
}
// Read the contents of the file
const lines = self[0].contents.split("\n");
// Read boolean value from the first line
const valid = lines[0].trim() === "True";
return valid;
}
Workflow Development¶
When adding new .cwl or .wic files, regenerate the discovery config and
schemas when editor validation or tool discovery looks stale:
sophios --generate_config
sophios --generate_schemas
Sophios uses ~/wic/global_config.json by default. Inspect that file before
deleting ~/wic, because it may contain local search paths you want to keep.
Singularity¶
When building images with Singularity, clear the cache if cwltool or
cwl-docker-extract reports stale-image or cache-related failures:
singularity cache clean
Toil¶
When working with Toil, stale job stores can preserve older runtime state. If changing workflow inputs or runner flags produces surprising behavior, clean the Toil state:
toil clean
rm -r ~/.toil