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

Add command nf-core subworkflows lint #2379

Merged
merged 16 commits into from
Jul 26, 2023
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

### Linting

- Add new command `nf-core subworkflows lint` ([#2379](https://github.com/nf-core/tools/pull/2379))

### Modules

### Subworkflows
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ A python package with helper tools for the nf-core community.
- [`subworkflows remove` - Remove a subworkflow from a pipeline](#remove-a-subworkflow-from-a-pipeline)
- [`subworkflows create` - Create a subworkflow from the template](#create-a-new-subworkflow)
- [`subworkflows create-test-yml` - Create the `test.yml` file for a subworkflow](#create-a-subworkflow-test-config-file)
- [`subworkflows lint` - Check a subworkflow against nf-core guidelines](#check-a-subworkflow-against-nf-core-guidelines)
- [`subworkflows test` - Run the tests for a subworkflow](#run-the-tests-for-a-subworkflow-using-pytest)
- [Citation](#citation)

Expand Down Expand Up @@ -1218,6 +1219,20 @@ extra_env:

![`nf-core subworkflows create-test-yml bam_stats_samtools --no-prompts --force`](docs/images/nf-core-subworkflows-create-test.svg)

### Check a subworkflow against nf-core guidelines

Run the `nf-core subworkflows lint` command to check subworkflows in the current working directory (a pipeline or a clone of nf-core/modules) against nf-core guidelines.

Use the `--all` flag to run linting on all subworkflows found. Use `--dir <pipeline_dir>` to specify a different directory than the current working directory.

<!-- RICH-CODEX
working_dir: tmp/modules
extra_env:
PROFILE: 'conda'
-->

![`nf-core subworkflows lint bam_stats_samtools`](docs/images/nf-core-subworkflows-lint.svg)

### Run the tests for a subworkflow using pytest

To run unit tests of a subworkflow that you have installed or the test created by the command [`nf-core subworkflow create-test-yml`](#create-a-subworkflow-test-config-file), you can use `nf-core subworkflows test` command. This command runs the tests specified in `tests/subworkflows/<subworkflow_name>/test.yml` file using [pytest](https://pytest-workflow.readthedocs.io/en/stable/).
Expand Down
18 changes: 18 additions & 0 deletions docs/api/make_lint_md.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import nf_core.lint
import nf_core.modules.lint
import nf_core.subworkflows.lint


def make_docs(docs_basedir, lint_tests, md_template):
Expand Down Expand Up @@ -55,3 +56,20 @@ def make_docs(docs_basedir, lint_tests, md_template):
```
""",
)

# Create the subworkflows lint docs
subworkflows_docs_basedir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "_src", "subworkflow_lint_tests")
make_docs(
subworkflows_docs_basedir,
list(
set(nf_core.subworkflows.lint.SubworkflowLint.get_all_lint_tests(is_pipeline=True)).union(
nf_core.subworkflows.lint.SubworkflowLint.get_all_lint_tests(is_pipeline=False)
)
),
"""# {0}

```{{eval-rst}}
.. automethod:: nf_core.subworkflows.lint.SubworkflowLint.{0}
```
""",
)
74 changes: 72 additions & 2 deletions nf_core/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,8 +912,8 @@ def lint(
Test modules within a pipeline or a clone of the
nf-core/modules repository.
"""
from nf_core.components.lint import LintException
from nf_core.modules import ModuleLint
from nf_core.modules.lint import ModuleLintException

try:
module_lint = ModuleLint(
Expand All @@ -938,7 +938,7 @@ def lint(
)
if len(module_lint.failed) > 0:
sys.exit(1)
except ModuleLintException as e:
except LintException as e:
log.error(e)
sys.exit(1)
except (UserWarning, LookupError) as e:
Expand Down Expand Up @@ -1170,6 +1170,76 @@ def local(ctx, keywords, json, dir): # pylint: disable=redefined-builtin
sys.exit(1)


# nf-core subworkflows lint
@subworkflows.command()
@click.pass_context
@click.argument("subworkflow", type=str, required=False, metavar="subworkflow name")
@click.option("-d", "--dir", type=click.Path(exists=True), default=".", metavar="<pipeline/modules directory>")
@click.option(
"-r",
"--registry",
type=str,
metavar="<registry>",
default=None,
help="Registry to use for containers. If not specified it will use docker.registry value in the nextflow.config file",
)
@click.option("-k", "--key", type=str, metavar="<test>", multiple=True, help="Run only these lint tests")
@click.option("-a", "--all", is_flag=True, help="Run on all subworkflows")
@click.option("-w", "--fail-warned", is_flag=True, help="Convert warn tests to failures")
@click.option("--local", is_flag=True, help="Run additional lint tests for local subworkflows")
@click.option("--passed", is_flag=True, help="Show passed tests")
@click.option(
"--sort-by",
type=click.Choice(["subworkflow", "test"]),
default="test",
help="Sort lint output by subworkflow or test name.",
show_default=True,
)
def lint(
ctx, subworkflow, dir, registry, key, all, fail_warned, local, passed, sort_by
): # pylint: disable=redefined-outer-name
"""
Lint one or more subworkflows in a directory.

Checks DSL2 subworkflow code against nf-core guidelines to ensure
that all subworkflows follow the same standards.

Test subworkflows within a pipeline or a clone of the
nf-core/modules repository.
"""
from nf_core.components.lint import LintException
from nf_core.subworkflows import SubworkflowLint

try:
subworkflow_lint = SubworkflowLint(
dir,
fail_warned=fail_warned,
registry=ctx.params["registry"],
remote_url=ctx.obj["modules_repo_url"],
branch=ctx.obj["modules_repo_branch"],
no_pull=ctx.obj["modules_repo_no_pull"],
hide_progress=ctx.obj["hide_progress"],
)
subworkflow_lint.lint(
subworkflow=subworkflow,
registry=registry,
key=key,
all_subworkflows=all,
print_results=True,
local=local,
show_passed=passed,
sort_by=sort_by,
)
if len(subworkflow_lint.failed) > 0:
sys.exit(1)
except LintException as e:
log.error(e)
sys.exit(1)
except (UserWarning, LookupError) as e:
log.critical(e)
sys.exit(1)


# nf-core subworkflows info
@subworkflows.command()
@click.pass_context
Expand Down
2 changes: 1 addition & 1 deletion nf_core/components/components_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def prompt_component_version_sha(component_name, component_type, modules_repo, i

def get_components_to_install(subworkflow_dir):
"""
Parse the subworkflow test main.nf file to retrieve all imported modules and subworkflows.
Parse the subworkflow main.nf file to retrieve all imported modules and subworkflows.
"""
modules = []
subworkflows = []
Expand Down
Loading