{"id":43371992,"url":"https://github.com/common-workflow-lab/wdl-cwl-translator","last_synced_at":"2026-02-02T05:54:52.220Z","repository":{"id":38314178,"uuid":"346530481","full_name":"common-workflow-lab/wdl-cwl-translator","owner":"common-workflow-lab","description":"A translator from WDL to CWL v1.2","archived":false,"fork":false,"pushed_at":"2026-01-19T08:15:53.000Z","size":15628,"stargazers_count":27,"open_issues_count":24,"forks_count":7,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-01-19T16:38:27.146Z","etag":null,"topics":["commonwl","cwl","wdl"],"latest_commit_sha":null,"homepage":"","language":"Common Workflow Language","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/common-workflow-lab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-03-11T00:27:41.000Z","updated_at":"2026-01-19T08:14:50.000Z","dependencies_parsed_at":"2024-01-29T18:16:27.985Z","dependency_job_id":"aab1dc29-505a-4cbb-8951-bad4e75206c5","html_url":"https://github.com/common-workflow-lab/wdl-cwl-translator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/common-workflow-lab/wdl-cwl-translator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/common-workflow-lab%2Fwdl-cwl-translator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/common-workflow-lab%2Fwdl-cwl-translator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/common-workflow-lab%2Fwdl-cwl-translator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/common-workflow-lab%2Fwdl-cwl-translator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/common-workflow-lab","download_url":"https://codeload.github.com/common-workflow-lab/wdl-cwl-translator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/common-workflow-lab%2Fwdl-cwl-translator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29006550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-02T04:25:24.522Z","status":"ssl_error","status_checked_at":"2026-02-02T04:24:51.069Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonwl","cwl","wdl"],"created_at":"2026-02-02T05:54:51.601Z","updated_at":"2026-02-02T05:54:52.211Z","avatar_url":"https://github.com/common-workflow-lab.png","language":"Common Workflow Language","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A translator from [WDL](https://openwdl.org/) to [CWL v1.2](https://w3id.org/cwl/v1.2/)\n\n[![codecov](https://codecov.io/gh/common-workflow-lab/wdl-cwl-translator/branch/main/graph/badge.svg?token=lvcnJHP1hj)](https://codecov.io/gh/common-workflow-lab/wdl-cwl-translator)\n\n## Background\n\nWorkflow Definition Language (WDL) and Common Workflow Language (CWL)\nare high-level languages for describing how to run a sequence of\nprograms to perform a data analysis task.  A workflow consists of a\nseries of steps that are connected by input/output dependencies.\n\nCWL is the product of community-based open source standards process,\nand workflows written in CWL are portable across a number of different\nsoftware platforms (e.g. Arvados, Toil, CWL-Airflow, Seven Bridges).  WDL is also\nopen source, but based largely around a single implementation\n(Cromwell), however some workflows that are important to the\nbioinformatics community are only maintained in WDL.\n\nThe goal of this project is to develop a translator that takes a WDL\nworkflow and produces an equivalent workflow in CWL.  When executed\nwith the same input, the translated workflow should produce equivalent\nresults to the original workflow.  An ideal demonstration of\ncapability would be to translate the Broad Institute WDL Analysis\nResearch Pipelines (WARP) Whole Genome Germline Single Sample\nworkflow, run it on a scale-out, production CWL runner (such as\nArvados or Toil), and show that the results are equivalent.\n\nMore background reading on CWL:\n\n- A recent paper: https://arxiv.org/abs/2105.07028 ([Full PDF](https://arxiv.org/pdf/2105.07028.pdf))\n- https://www.commonwl.org/user_guide/\n\nThis project uses the CWL parser and objects from [`cwl_utils.parser.cwl_v1_2`](https://cwl-utils.readthedocs.io/en/latest/autoapi/cwl_utils/parser/cwl_v1_2/index.html)\n\n[miniwdl](https://github.com/chanzuckerberg/miniwdl) is used for WDL parsing,\nand while we target OpenWDL 1.1, earlier versions of (Open)WDL seem to work\nthanks to the flexibility of the `miniwdl` parser.\n\nFor some discussion comparing the two languages (mainly from the perspective of translating in the other direction, CWL to WDL), see this document:\n\nhttps://github.com/dnanexus/dxCompiler/blob/main/doc/CWL_v1.2.0_to_WDL_v1.md\n\n## Installation\n\n### Prerequisites\n\nPython 3.7+\n\n### Instructions\n\nThese instructions assume a Linux / macOS operating system.\n\n``` shell\ngit clone https://github.com/common-workflow-lab/wdl-cwl-translator/\ncd wdl-cwl-translator\npython3 -m venv env\nsource env/bin/activate\npip install -U pip setuptools wheel\npip install -e .\n```\n\n## Usage\n\n``` shell\nwdl2cwl path_to_wdl_file\n```\nTo output the CWL version to your terminal/stdout.\n\n``` shell\nwdl2cwl path_to_workflow.wdl --output path_to_new_workflow.cwl\n```\n\n## Temporary Limitations\n\nWDL features not yet supported\n- Advanced [Scatter](https://github.com/common-workflow-lab/wdl-cwl-translator/issues/183)\n\nWDL types not yet supported\n- Non-static [Map](https://github.com/common-workflow-lab/wdl-cwl-translator/issues/77) types\n- [Nested structs](https://github.com/common-workflow-lab/wdl-cwl-translator/issues/158)\n- [Pair](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#pairx-y)\n- [Object](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-object)\n\nOpenWDL 1.1 standard library functions to be implemented\n- [floor](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#int-floorfloat-int-ceilfloat-and-int-roundfloat)\n- [min](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-int-minint-int-float-minfloat-float-float-minint-float-float-minfloat-int)\n- [max](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-int-maxint-int-float-maxfloat-float-float-maxint-float-float-maxfloat-int)\n- [stderr](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#file-stderr)\n- [read_map](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#mapstring-string-read_mapstringfile)\n- [read_object](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-object-read_objectstringfile)\n- [read_objects](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-arrayobject-read_objectsstringfile)\n- [read_json](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#r-read_jsonstringfile)\n- [write_lines](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#file-write_linesarraystring)\n- [write_tsv](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#file-write_tsvarrayarraystring)\n- [write_map](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#file-write_mapmapstring-string)\n- [write_object](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-file-write_objectobject)\n- [write_objects](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-file-write_objectsarrayobject)\n- [write_json](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#file-write_jsonx)\n- [range](https://github.com/common-workflow-lab/wdl-cwl-translator/issues/176)\n- [transpose](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#arrayarrayx-transposearrayarrayx)\n- [zip](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#arraypairxy-ziparrayx-arrayy)\n- [unzip](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-pairarrayx-arrayy-unziparraypairx-y)\n- [cross](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#arraypairxy-crossarrayx-arrayy)\n- [prefix](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#arraystring-prefixstring-arrayp)\n- [suffix](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-arraystring-suffixstring-arrayp)\n- [squote](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-arraystring-squotearrayp)\n- [as_pairs](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-arraypairp-y-as_pairsmapp-y)\n- [as_map](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-mapp-y-as_maparraypairp-y)\n- [keys](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-arrayp-keysmapp-y)\n- [collect_by_keys](https://github.com/openwdl/wdl/blob/main/versions/1.1/SPEC.md#-mapp-arrayy-collect_by_keyarraypairp-y)\n\nMany of the above are straightforward to implement, but we haven't needed them yet.\nSo if you are unable to translate a particular WDL document due to lackof a standard library\nfunction, please [open an issue](https://github.com/common-workflow-lab/wdl-cwl-translator/issues/new/choose)\nand share your example!\n\n## Incompatibilities possibly requiring manual intervention\n\n1. Dynamic specification of Docker containers.\n   As of CWL v1.2, CWL's `DockerRequirement` has no support for dynamic\nspecifications, only fixed values. If a WDL task has a `runtime.docker` that\nreferences an input with a default value, then `wdl2cwl` does try to copy that\ndefault value to the CWL `DockerRequirement.dockerPull`.\n\nIf changing the software container is needed, there are several workarounds:\n1. Use workflow runner/engine provided overrides: many CWL runners\n(including those based upon the CWL reference runner, `cwltool`) support overriding\nrequirements at any level at run time. See\nhttps://github.com/common-workflow-language/cwltool#overriding-workflow-requirements-at-load-time\n2. Manually override the `DockerRequirement` in `hints` by specifying your own container\nat the CWL workflow step level under `requirements`\n3. Manually editing the CommandLineTool definition yourself.\n\n### File Localization\n\n(Open)WDL assumes that users will configure localization by placing\ninput files in the same directory. Descriptions that require this will need\nmodification before conversion to CWL, as CWL has explicit constructs for\nachieving localization (`secondaryFiles`, `InitialWorkDirRequirement`, and/or\nexplicit staging).\n\nSee [this example](https://github.com/mr-c/biowdl_tasks_cwlcompat/commit/0dd4704ec8969e491e6358fe2e8283272cafde21#diff-c76c01f3ca967cdb9c157a75e7fb1a08d0037543b455c2107398601a2f526ebfR45)\nfor one method using explicit staging of input files in the `command` block to\nachieve the localization required by the tool(s) being called.\n\n## Tips for manually improving the CWL outputs\n\nIf you are converting a WDL workflow to the CWL format and the original WDL\ndocument is the \"source of truth\", then one should avoid making manual changes\nto the CWL as you will need to maintain those changes as the source WDL\ndocument(s) changes.\n\nOtherwise, for those users looking to convert from WDL to CWL and then continue\nto modify the CWL directly, then we have the following advice:\n\nConsider swapping the `wdl2cwl` translation of the WDL tasks for\n[community maintained CWL descriptions for popular tools](https://github.com/common-workflow-library/bio-cwl-tools)\nwhen possible. Follow the [instructions on usage](https://github.com/common-workflow-library/bio-cwl-tools#how-to-use-these-descriptions-in-your-own-repository)\nand update the `run` line to refer to a local path or a \"raw\" GitHub URL of the\ncommunity-maintained tool description. You may need to adjust a few input names to\nmatch. Of course, we are happy to [receive your enhancements and additional CWL\nbio\\* tool descriptions](https://github.com/common-workflow-library/bio-cwl-tools#how-to-donate-your-tool-descriptions)!\n\nFor the resulting CWL `Workflow` and any CWL `CommandLineTool`s not swapped for\nidiomatic CWL descriptions, consider using the following CWL features absent in WDL\n\n### CWL `Workflow` Tips\n1. Consider collapsing nested WDL scatters in a single [multi-dimensional CWL scatter](https://www.commonwl.org/v1.2/Workflow.html#Scatter/gather)\n\n### CWL `CommandLineTool` Tips\n\n1. Use `secondaryFiles` instead of implicit file co-localizaton for when you\n   have a file and its index(es).\n2. Adding [`format`](https://www.commonwl.org/user_guide/16-file-formats/index.html)\n   specifiers to input and output `File`s and arrays of `File`s both at the\n   `Workflow` and `CommandLineTool` levels. This helps improve the type checking\n   of the workflow and anyone wanting to re-use or adapt the individual `CommandLineTool`s.\n3. In addition to the `minCores` in ResourceRequirement, consider setting the `maxCores`\n   if the tool is known to not benefit from additional cores after a certain amount.\n4. Retrieving the actual number of cores allocated via `$(runtime.cores)` to pass\n   to your tools.\n5. Need the absolute path of the working directory? You can use `$(runtime.outdir)`.\n6. Only running a single command and are redirecting a file into in (`my_tool \u003c input_file`)?\n   You can change the input to be [`type: stdin`](https://www.commonwl.org/v1.2/CommandLineTool.html#stdin)\n   instead of `type: File` and drop the `\u003c input_file` as a shortcut.\n7. Specify the underlying tool(s) required beyond a `DockerRequirement` via\n   [`SoftwareRequirement`](https://www.commonwl.org/v1.2/CommandLineTool.html#SoftwareRequirement).\n   This makes for good documentation, helps give credit to the authors of the tool(s),\n   and makes it easier for those who want to run with local software, conda packages,\n   and other non-containerized environments.\n8. Moving any environment variable settings (`export FOO=bar`) present in the `script.bash` to an\n   [`EnvVarRequirement`](https://www.commonwl.org/user_guide/12-env/index.html)\n   Be careful, if the `script.bash` runs many commands and the environment variables\n   are not set at the beginning, that may be due to them not being appropriate for\n   all the commands; so test to confirm that they are safe to move to an `EnvVarRequirement`\n   and if you aren't sure, leave them there.\n   Per-tool invocations with environment variables like `FOO=bar name_of_tool.pl --option`\n   are also a candidate if (1) there are no other tools invoked or (2) they all\n   have the same environment variables set or (3) they other tools ignore the\n   environment variables.\n9. Many WDL `command` sections create output directories and perform other\n   \"housekeeping\" that is not necessary in CWL, like symlinking files to change\n   names or otherwise arrange the input files. Output directories that themselves\n   don't become a `Directory` type are likely removable. If a\n   [specific arrangement of inputs files is needed](https://www.commonwl.org/user_guide/15-staging/index.html),\n   or [additional files need to created dynamically](https://www.commonwl.org/user_guide/14-runtime/index.html),\n   then consider using `InitialWorkDirRequirement`.\n10. Some WDL `command` sections include copying input files to obtain writable versions.\n    This can be quite slow on many systems, and from a CWL perspective it is better\n    to use [`InitialWorkDirRequirement`](https://www.commonwl.org/user_guide/15-staging/index.html)\n    to achieve the same results by marking those inputs as being `writable: true`.\n11. Most CWL runners provide methods to monitor task execution in real time,\n    so monitoring scripts and other similar techniques can be removed.\n12. If the `script.bash` (which comes from the WDL `command` section) meets the\n    following criteria, then consider removing it (and the `InitialWorkDirRequirement`\n    if otherwise unused) in favor of directly calling your tool using `baseCommand`\n    with the name of the executable and any static command line arguments\n    and [`arguments`](https://www.commonwl.org/user_guide/08-arguments/index.html)\n    with the remaining mix of dynamic and static command line arguments.\n    - No `bash` features like `for` loops and `if` statements\n    - A single tool is invoked just once; check for un-escaped semicolons `;` which\n      means there are multiple commands on a single line.\n    - no input/output redirection, use `stdin`, `stdout`, and `stderr` as need be.\n    - no pipelining `|`.\n\n## Development\n\n### Running the tests\n\n```\nmake install-dep\nmake test  # just the unit tests\nmake help # to list major makefile targets\nmake diff_pydocstyle_report # run a diff to show how much changes where made in the docstyle\n\ntox  # all the code checks\ntox -l # list of all configured tox environments\ntox -e py39-pydocstyle # perform only pydocstyle tests (py39 is the version of the python interpreter you have installed)\n```\n\n### Adding Test Cases\n\n1. Find a WDL workflow. Given below are some links that can be used to find these workflows: \n    1. https://github.com/broadinstitute/warp\n    2. https://github.com/broadinstitute/viral-pipelines/tree/master/pipes/WDL\n    3. https://github.com/biowdl/tasks\n2. Use the translator to convert the WDL file and save the result to a .cwl file at a specified location.\n   `python wdl2cwl/main.py path_to_wdl_file -o specified_location`.\n3. If a problem is encountered during the translation or if the WDL workflow has a feature that has not been\n   implemented yet, submit a new issue with a description of the issue at\n   https://github.com/common-workflow-lab/wdl-cwl-translator/issues\n4. Check whether the outputs of the WDL workflow and the resultant CWL file are equivalent upon giving the required\n   inputs. The required inputs can usually be found in the repository of the workflow itself through a keyword search.\n   (eg: name of the workflow, name of the tool used in the command section) The WDL workflow can be run using a workflow\n   runner like miniwdl. (Refer the documentation https://github.com/chanzuckerberg/miniwdl) The CWL file can be run\n   using cwltool (Refer the documentation https://github.com/common-workflow-language/cwltool)\n5. Add the WDL workflow to `wdl2cwl/tests/wdl_files` and the resultant CWL file to `wdl2cwl/tests/cwl_files`.\n   Include the licence and the original location of the WDL file as a comment at the beginning of the document. \n6. Add the name of the added WDL file to `wdl2cwl/tests/test_cwl.py` as an argument under the\n  `@pytest.mark.parametrize()` function.\n7. Please run the code checks via `tox`, and fix as many issue as you can on your own. `make format` will fix many things for you!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcommon-workflow-lab%2Fwdl-cwl-translator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcommon-workflow-lab%2Fwdl-cwl-translator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcommon-workflow-lab%2Fwdl-cwl-translator/lists"}