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

[Feature] Flexible linting for actionsci and multiqc_config #1461

Merged
merged 15 commits into from
Mar 17, 2022
Merged
2 changes: 1 addition & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ New features should also come with new tests, to keep the test-coverage high (we
You can try running the tests locally before pushing code using the following command:

```bash
pytest --color=yes tests/
pytest --color=yes
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
```

### Lint Tests
Expand Down
4 changes: 4 additions & 0 deletions docs/api/_src/pipeline_lint_tests/multiqc_config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
multiqc_config
ewels marked this conversation as resolved.
Show resolved Hide resolved
===============

.. automethod:: nf_core.lint.PipelineLint.multiqc_config
4 changes: 1 addition & 3 deletions nf_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@
Shouldn't do much, as everything is under subcommands.
"""

import pkg_resources

__version__ = pkg_resources.get_distribution("nf_core").version
from .version import __version__
2 changes: 2 additions & 0 deletions nf_core/lint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ class PipelineLint(nf_core.utils.Pipeline):
from .files_unchanged import files_unchanged
from .merge_markers import merge_markers
from .modules_json import modules_json
from .multiqc_config import multiqc_config
from .nextflow_config import nextflow_config
from .pipeline_name_conventions import pipeline_name_conventions
from .pipeline_todos import pipeline_todos
Expand Down Expand Up @@ -205,6 +206,7 @@ def _get_all_lint_tests(release_mode):
"actions_schema_validation",
"merge_markers",
"modules_json",
"multiqc_config",
] + (["version_consistency"] if release_mode else [])

def _load(self):
Expand Down
10 changes: 8 additions & 2 deletions nf_core/lint/actions_ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,15 @@ def actions_ci(self):

# Check that the action is turned on for the correct events
try:
expected = {"push": {"branches": ["dev"]}, "pull_request": None, "release": {"types": ["published"]}}
# NB: YAML dict key 'on' is evaluated to a Python dict key True
assert ciwf[True] == expected
assert "dev" in ciwf[True]["push"]["branches"]
pr_subtree = ciwf[True]["pull_request"]
assert (
pr_subtree == None
or ("branches" in pr_subtree and "dev" in pr_subtree["branches"])
or ("ignore_branches" in pr_subtree and not "dev" in pr_subtree["ignore_branches"])
)
assert "published" in ciwf[True]["release"]["types"]
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
except (AssertionError, KeyError, TypeError):
failed.append("'.github/workflows/ci.yml' is not triggered on expected events")
else:
Expand Down
3 changes: 0 additions & 3 deletions nf_core/lint/files_unchanged.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def files_unchanged(self):
Files that can have additional content but must include the template contents::

.gitignore
assets/multiqc_config.yaml

.. tip:: You can configure the ``nf-core lint`` tests to ignore any of these checks by setting
the ``files_unchanged`` key as follows in your linting config file. For example:
Expand All @@ -54,7 +53,6 @@ def files_unchanged(self):

files_unchanged:
- .github/workflows/branch.yml
- assets/multiqc_config.yaml

"""

Expand Down Expand Up @@ -102,7 +100,6 @@ def files_unchanged(self):
]
files_partial = [
[".gitignore", "foo"],
[os.path.join("assets", "multiqc_config.yaml")],
]

# Only show error messages from pipeline creation
Expand Down
91 changes: 91 additions & 0 deletions nf_core/lint/multiqc_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/env python

import os
import yaml


def multiqc_config(self):
"""Make sure basic multiQC plugins are installed and plots are exported
Basic template:
report_comment: >
This report has been generated by the <a href="https://github.com/nf-core/quantms" target="_blank">nf-core/quantms</a>
analysis pipeline. For information about how to interpret these results, please see the
<a href="https://nf-co.re/quantms" target="_blank">documentation</a>.
report_section_order:
software_versions:
order: -1000
nf-core-quantms-summary:
order: -1001

export_plots: true
ewels marked this conversation as resolved.
Show resolved Hide resolved
"""
passed = []
failed = []

fn = os.path.join(self.wf_path, "assets", "multiqc_config.yaml")

# Return a failed status if we can't find the file
if not os.path.isfile(fn):
return {"failed": ["'assets/multiqc_config.yaml' not found"]}
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved

try:
with open(fn, "r") as fh:
mqc_yml = yaml.safe_load(fh)
except Exception as e:
return {"failed": ["Could not parse yaml file: {}, {}".format(fn, e)]}

# Check that the report_comment exists and matches
try:
assert "report_section_order" in mqc_yml
orders = dict()
summary_plugin_name = "nf-core-" + self.pipeline_name + "-summary"
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
min_plugins = ["software_versions", summary_plugin_name]
for plugin in min_plugins:
assert plugin in mqc_yml["report_section_order"]
assert "order" in mqc_yml["report_section_order"][plugin]
plugin_order = mqc_yml["report_section_order"][plugin]["order"]
assert plugin_order < 0
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved

for plugin in mqc_yml["report_section_order"]:
if "order" in mqc_yml["report_section_order"][plugin]:
orders[plugin] = mqc_yml["report_section_order"][plugin]["order"]

assert orders[summary_plugin_name] == min(orders.values())
orders.pop(summary_plugin_name)
assert orders["software_versions"] == min(orders.values())
except (AssertionError, KeyError, TypeError):
failed.append(
"'assets/multiqc_config.yaml' does not follow the ordering scheme of the minimally required plugins."
)
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
else:
passed.append("'assets/multiqc_config.yaml' follows the ordering scheme of the minimally required plugins.")

# Check that the minimum plugins exist and are coming first in the summary
try:
assert "report_comment" in mqc_yml
assert (
mqc_yml["report_comment"].strip()
== 'This report has been generated by the <a href="https://github.com/nf-core/%s" target="_blank">nf-core/%s</a> '
"analysis pipeline. For information about how to interpret these results, please see the "
'<a href="https://nf-co.re/%s" target="_blank">documentation</a>.'
% (
self.pipeline_name,
self.pipeline_name,
self.pipeline_name,
)
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
)
except (AssertionError, KeyError, TypeError):
failed.append("'assets/multiqc_config.yaml' does not contain a matching report_comment.")
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
else:
passed.append("'assets/multiqc_config.yaml' contains a matching report_comment.")

# Check that export_plots is activated
try:
assert "export_plots" in mqc_yml
assert mqc_yml["export_plots"] == True
except (AssertionError, KeyError, TypeError):
failed.append("'assets/multiqc_config.yaml' does not contain 'export_plots: true'.")
else:
passed.append("'assets/multiqc_config.yaml' contains 'export_plots: true'.")

return {"passed": passed, "failed": failed}
1 change: 1 addition & 0 deletions nf_core/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "2.4dev"
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[pytest]
filterwarnings =
ignore::pytest.PytestRemovedIn8Warning:_pytest.nodes:140
testpaths =
tests
jpfeuffer marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 7 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

from setuptools import setup, find_packages

version = "2.4dev"
versionfile = "nf_core/version.py"
try:
execfile(versionfile)
except:
exec(open(versionfile).read())

version = __version__

with open("README.md") as f:
readme = f.read()
Expand Down