|
46 | 46 | - Cloud provider support inputs and validation |
47 | 47 | - Output block organization |
48 | 48 | - Error handling with ErrorWithMessage task |
| 49 | + - **Workflow-level parameter derivation** |
| 50 | + - Compute derived values (e.g. tool flags, directory paths, numeric parameters) as WDL expressions in the workflow, not as bash conditionals inside task command blocks |
| 51 | + - Pass the computed values as explicit task inputs rather than raw enum/mode inputs that the task must interpret |
| 52 | + - This keeps tasks focused on execution and makes the parameter contract visible in the WDL call site |
| 53 | + - Example — instead of passing `Int chemistry` and branching in bash: |
| 54 | + ```wdl |
| 55 | + # Good: compute in workflow, pass to task |
| 56 | + Int umi_len = if tenx_chemistry_version == 2 then 10 else 12 |
| 57 | + call MyTask { input: umi_len = umi_len } |
| 58 | + ``` |
| 59 | + ```wdl |
| 60 | + # Avoid: passing raw mode flag and branching in bash |
| 61 | + call MyTask { input: chemistry = tenx_chemistry_version } |
| 62 | + # ...where the task command block contains if/elif/else to derive umi_len |
| 63 | + ``` |
| 64 | + - When a derived value requires string parsing that WDL 1.0 cannot express (e.g. parsing a read structure like `"8C18C9M1X"`), use a small dedicated utility task rather than embedding the logic in a large execution task |
| 65 | + - **Input validation placement** |
| 66 | + - Validate all user-facing inputs at the workflow level using `ErrorWithMessage` or a dedicated input-checking task (e.g. `checkOptimusInput`), not inside execution tasks |
| 67 | + - Consolidate validation for a pipeline into a single task or workflow section so there is one place to check for all constraints |
| 68 | + - Do not duplicate validation in both the workflow and the task — validate once upstream, then trust the inputs downstream |
| 69 | + - **Derived values with embedded spaces** |
| 70 | + - When a derived string contains spaces (e.g. `"GeneFull_Ex50pAS Gene"` for STAR's `--soloFeatures`), add a comment at the declaration site noting that the value is intentionally multi-word and must remain unquoted in the command block |
49 | 71 |
|
50 | 72 | ## 6. Task Structure |
51 | 73 |
|
|
60 | 82 | - Runtime parameter specification |
61 | 83 | - Docker image handling for multi-cloud |
62 | 84 | - Memory, CPU, disk sizing |
| 85 | +- **Task purity principle** |
| 86 | + - Tasks should execute their tool with the parameters they are given, not decide *what* to run based on mode flags |
| 87 | + - Bash conditionals in command blocks are appropriate for post-execution file handling (moving outputs, renaming files) but not for deriving tool parameters or validating inputs |
| 88 | + - If a task currently branches on a mode input to select different tool flags, refactor by computing the flag values at the workflow level and passing them as explicit inputs |
| 89 | + - This makes tasks reusable across workflows without carrying pipeline-specific validation logic |
63 | 90 |
|
64 | 91 | ## 7. Docker Handling |
65 | 92 |
|
|
0 commit comments