From 3e0821a00cc7fd9afbf0812f67f666bf30f3983a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 2 Dec 2025 12:44:45 +0100 Subject: [PATCH 01/19] initial functions to generate pipeline container config files --- nf_core/pipelines/containers_utils.py | 55 +++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 nf_core/pipelines/containers_utils.py diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py new file mode 100644 index 0000000000..de672d25f4 --- /dev/null +++ b/nf_core/pipelines/containers_utils.py @@ -0,0 +1,55 @@ +import logging +from pathlib import Path + +from nf_core.utils import NF_INSPECT_MIN_NF_VERSION, check_nextflow_version, pretty_nf_version, run_cmd + +log = logging.getLogger(__name__) + + +class ContainerConfigs: + """Generates the container configuration files for a pipeline. + + Args: + workflow_directory (str | Path): The directory containing the workflow files. + """ + + def __init__( + self, + workflow_directory: str | Path = ".", + ): + self.workflow_directory = Path(workflow_directory) + + def check_nextflow_version(self) -> None: + """Check if the Nextflow version is sufficient to run `nextflow inspect`.""" + if not check_nextflow_version(NF_INSPECT_MIN_NF_VERSION): + raise UserWarning( + f"To use Seqera containers Nextflow version >= {pretty_nf_version(NF_INSPECT_MIN_NF_VERSION)} is required.\n" + f"Please update your Nextflow version with [magenta]'nextflow self-update'[/]\n" + ) + + def generate_default_container_config(self) -> None: + """ + Generate the default container configuration file for a pipeline. + Requires Nextflow >= 25.04.4 + """ + self.check_nextflow_version() + log.debug("Generating container config file with [magenta bold]nextflow inspect[/].") + try: + # Run nextflow inspect + executable = "nextflow" + cmd_params = f"inspect -format config {self.workflow_directory}" + cmd_out = run_cmd(executable, cmd_params) + if cmd_out is None: + raise UserWarning("Failed to run `nextflow inspect`. Please check your Nextflow installation.") + + out, _ = cmd_out + out_str = str(out, encoding="utf-8") + with open(self.workflow_directory / "configs" / "containers_docker_amd64.config", "w") as fh: + fh.write(out_str) + log.info( + f"Generated container config file for Docker AMD64: {self.workflow_directory / 'configs' / 'containers_docker_amd64.config'}" + ) + + except RuntimeError as e: + log.error("Running 'nextflow inspect' failed with the following error:") + raise UserWarning(e) From f3bd12cce584c6989abab8a47b24ac9cf013180f Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 2 Dec 2025 11:46:35 +0000 Subject: [PATCH 02/19] [automated] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c45c8ffde..e13f32cb07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - add pre-commit hook to keep uv.lock in sync ([#3933](https://github.com/nf-core/tools/pull/3933)) - Update mcr.microsoft.com/devcontainers/miniconda Docker digest to 2be0f5a ([#3946](https://github.com/nf-core/tools/pull/3946)) - Fix docker errors in test ([#3924](https://github.com/nf-core/tools/pull/3924)) +- Add new command to generate pipeline container config files ([#3955](https://github.com/nf-core/tools/pull/3955)) ### Template From 682f140a8bebab1de221713ea6062e015edd138e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 2 Dec 2025 15:13:25 +0100 Subject: [PATCH 03/19] generate all config files --- nf_core/pipelines/containers_utils.py | 113 +++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 4 deletions(-) diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index de672d25f4..4f3eae4493 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -1,6 +1,9 @@ import logging +import re from pathlib import Path +import yaml + from nf_core.utils import NF_INSPECT_MIN_NF_VERSION, check_nextflow_version, pretty_nf_version, run_cmd log = logging.getLogger(__name__) @@ -19,6 +22,12 @@ def __init__( ): self.workflow_directory = Path(workflow_directory) + def generate_container_configs(self) -> None: + """Generate the container configuration files for a pipeline.""" + self.check_nextflow_version() + default_config = self.generate_default_container_config() + self.generate_all_container_configs(default_config) + def check_nextflow_version(self) -> None: """Check if the Nextflow version is sufficient to run `nextflow inspect`.""" if not check_nextflow_version(NF_INSPECT_MIN_NF_VERSION): @@ -27,12 +36,11 @@ def check_nextflow_version(self) -> None: f"Please update your Nextflow version with [magenta]'nextflow self-update'[/]\n" ) - def generate_default_container_config(self) -> None: + def generate_default_container_config(self) -> str: """ Generate the default container configuration file for a pipeline. Requires Nextflow >= 25.04.4 """ - self.check_nextflow_version() log.debug("Generating container config file with [magenta bold]nextflow inspect[/].") try: # Run nextflow inspect @@ -44,12 +52,109 @@ def generate_default_container_config(self) -> None: out, _ = cmd_out out_str = str(out, encoding="utf-8") - with open(self.workflow_directory / "configs" / "containers_docker_amd64.config", "w") as fh: + with open(self.workflow_directory / "conf" / "containers_docker_amd64.config", "w") as fh: fh.write(out_str) log.info( - f"Generated container config file for Docker AMD64: {self.workflow_directory / 'configs' / 'containers_docker_amd64.config'}" + f"Generated container config file for Docker AMD64: {self.workflow_directory / 'conf' / 'containers_docker_amd64.config'}" ) + return out_str except RuntimeError as e: log.error("Running 'nextflow inspect' failed with the following error:") raise UserWarning(e) + + def generate_all_container_configs(self, default_config: str) -> None: + """Generate the container configuration files for all platforms.""" + containers: dict[str, dict[str, str]] = { + "docker_amd64": {}, + "docker_arm64": {}, + "singularity_oras_amd64": {}, + "singularity_oras_arm64": {}, + "singularity_https_amd64": {}, + "singularity_https_arm64": {}, + "conda_amd64_lockfile": {}, + "conda_arm64_lockfile": {}, + } + for line in default_config.split("\n"): + if line.startswith("process"): + pattern = r"process { withName: \'(.*)\' { container = \'(.*)\' } }\n" + match = re.search(pattern, line) + if match: + try: + module_name = match.group(1) + container = match.group(2) + except AttributeError: + log.warning(f"Could not parse container for process {line}") + continue + else: + continue + containers["docker_amd64"][module_name] = container + for module_name in containers["docker_amd64"].keys(): + # Find module containers in meta.yml + if "_" in module_name: + module_path = Path(module_name.split("_")[0].lower()) / module_name.split("_")[1].lower() + else: + module_path = Path(module_name.lower()) + + try: + with open(self.workflow_directory / "modules" / module_path / "meta.yml") as fh: + meta = yaml.safe_load(fh) + except FileNotFoundError: + log.warning(f"Could not find meta.yml for {module_name}") + continue + + try: + containers["docker_arm64"][module_name] = meta["containers"]["docker"]["linux_arm64"]["name"] + except KeyError: + log.warning(f"Could not find docker linux_arm64 container for {module_name}") + continue + try: + containers["singularity_oras_amd64"][module_name] = meta["containers"]["singularity"]["linux_amd64"][ + "name" + ] + except KeyError: + log.warning(f"Could not find singularity linux_amd64 oras container for {module_name}") + continue + try: + containers["singularity_oras_arm64"][module_name] = meta["containers"]["singularity"]["linux_arm64"][ + "name" + ] + except KeyError: + log.warning(f"Could not find singularity linux_arm64 oras container for {module_name}") + continue + try: + containers["singularity_https_amd64"][module_name] = meta["containers"]["singularity"]["linux_amd64"][ + "https" + ] + except KeyError: + log.warning(f"Could not find singularity linux_amd64 https URL for {module_name}") + continue + try: + containers["singularity_https_arm64"][module_name] = meta["containers"]["singularity"]["linux_arm64"][ + "https" + ] + except KeyError: + log.warning(f"Could not find singularity linux_arm64 https URL for {module_name}") + continue + try: + containers["conda_amd64_lockfile"][module_name] = meta["containers"]["conda"]["linux_amd64"][ + "lock_file" + ] + except KeyError: + log.warning(f"Could not find conda linux_amd64 lock file for {module_name}") + continue + try: + containers["conda_arm64_lockfile"][module_name] = meta["containers"]["conda"]["linux_arm64"][ + "lock_file" + ] + except KeyError: + log.warning(f"Could not find conda linux_arm64 lock file for {module_name}") + continue + + # write config files + for platform in containers.keys(): + with open(self.workflow_directory / "conf" / f"containers_{platform}.config", "w") as fh: + for module_name in containers[platform].keys(): + fh.write( + f"process {{ withName: '{module_name}' {{ container = {containers[platform][module_name]}' }} }}\n" + ) From 54acc5a436dda0bdf062664f2ea1ad91de1cb34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 2 Dec 2025 15:28:44 +0100 Subject: [PATCH 04/19] regenerate container config files when modules install, remove, update --- nf_core/components/install.py | 10 +++++++++- nf_core/components/remove.py | 8 ++++++++ nf_core/components/update.py | 8 ++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/nf_core/components/install.py b/nf_core/components/install.py index 61e088ef16..f15ecda537 100644 --- a/nf_core/components/install.py +++ b/nf_core/components/install.py @@ -22,6 +22,7 @@ ) from nf_core.modules.modules_json import ModulesJson from nf_core.modules.modules_repo import ModulesRepo +from nf_core.pipelines.containers_utils import ContainerConfigs log = logging.getLogger(__name__) @@ -157,7 +158,7 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool if not self.install_component_files(component, version, self.modules_repo, install_folder): return False - # Update module.json with newly installed subworkflow + # Update module.json with newly installed component modules_json.load() modules_json.update( self.component_type, self.modules_repo, component, version, self.installed_by, install_track @@ -167,6 +168,13 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool # Install included modules and subworkflows self.install_included_components(component_dir) + # Regenerate container configuration files for the pipeline when modules are installed + if self.component_type == "modules": + try: + ContainerConfigs(self.directory).generate_container_configs() + except UserWarning as e: + log.warning(f"Could not regenerate container configuration files: {e}") + if not silent: modules_json.load() modules_json.dump(run_prettier=True) diff --git a/nf_core/components/remove.py b/nf_core/components/remove.py index afe12c88a9..5710e71189 100644 --- a/nf_core/components/remove.py +++ b/nf_core/components/remove.py @@ -9,6 +9,7 @@ import nf_core.utils from nf_core.components.components_command import ComponentCommand from nf_core.modules.modules_json import ModulesJson +from nf_core.pipelines.containers_utils import ContainerConfigs from .install import ComponentInstall @@ -172,6 +173,13 @@ def remove(self, component, repo_url=None, repo_path=None, removed_by=None, remo # remember removed dependencies if dependency_removed: removed_components.append(component_name.replace("/", "_")) + # Regenerate container configuration files for the pipeline when modules are removed + if self.component_type == "modules": + try: + ContainerConfigs(self.directory).generate_container_configs() + except UserWarning as e: + log.warning(f"Could not regenerate container configuration files: {e}") + # print removed dependencies if removed_components: log.info(f"Removed files for '{component}' and its dependencies '{', '.join(removed_components)}'.") diff --git a/nf_core/components/update.py b/nf_core/components/update.py index fcdb005e9f..4854ad1f86 100644 --- a/nf_core/components/update.py +++ b/nf_core/components/update.py @@ -18,6 +18,7 @@ from nf_core.components.remove import ComponentRemove from nf_core.modules.modules_json import ModulesJson from nf_core.modules.modules_repo import ModulesRepo +from nf_core.pipelines.containers_utils import ContainerConfigs from nf_core.utils import plural_es, plural_s, plural_y log = logging.getLogger(__name__) @@ -298,6 +299,13 @@ def update(self, component=None, silent=False, updated=None, check_diff_exist=Tr # Update modules.json with newly installed component self.modules_json.update(self.component_type, modules_repo, component, version, installed_by=None) updated.append(component) + + # Regenerate container configuration files for the pipeline when modules are updated + if self.component_type == "modules": + try: + ContainerConfigs(self.directory).generate_container_configs() + except UserWarning as e: + log.warning(f"Could not regenerate container configuration files: {e}") recursive_update = True modules_to_update, subworkflows_to_update = self.get_components_to_update(component) if not silent and len(modules_to_update + subworkflows_to_update) > 0: From b8004aa0d2c6ac8559169711dc390d08400f46f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 2 Dec 2025 15:41:20 +0100 Subject: [PATCH 05/19] pass repo_path --- nf_core/components/install.py | 2 +- nf_core/components/remove.py | 2 +- nf_core/components/update.py | 2 +- nf_core/pipelines/containers_utils.py | 5 ++++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/nf_core/components/install.py b/nf_core/components/install.py index f15ecda537..5fc6135410 100644 --- a/nf_core/components/install.py +++ b/nf_core/components/install.py @@ -171,7 +171,7 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool # Regenerate container configuration files for the pipeline when modules are installed if self.component_type == "modules": try: - ContainerConfigs(self.directory).generate_container_configs() + ContainerConfigs(self.directory, self.modules_repo.repo_path).generate_container_configs() except UserWarning as e: log.warning(f"Could not regenerate container configuration files: {e}") diff --git a/nf_core/components/remove.py b/nf_core/components/remove.py index 5710e71189..cf8566ff71 100644 --- a/nf_core/components/remove.py +++ b/nf_core/components/remove.py @@ -176,7 +176,7 @@ def remove(self, component, repo_url=None, repo_path=None, removed_by=None, remo # Regenerate container configuration files for the pipeline when modules are removed if self.component_type == "modules": try: - ContainerConfigs(self.directory).generate_container_configs() + ContainerConfigs(self.directory, repo_path).generate_container_configs() except UserWarning as e: log.warning(f"Could not regenerate container configuration files: {e}") diff --git a/nf_core/components/update.py b/nf_core/components/update.py index 4854ad1f86..c24331b142 100644 --- a/nf_core/components/update.py +++ b/nf_core/components/update.py @@ -303,7 +303,7 @@ def update(self, component=None, silent=False, updated=None, check_diff_exist=Tr # Regenerate container configuration files for the pipeline when modules are updated if self.component_type == "modules": try: - ContainerConfigs(self.directory).generate_container_configs() + ContainerConfigs(self.directory, modules_repo.repo_path).generate_container_configs() except UserWarning as e: log.warning(f"Could not regenerate container configuration files: {e}") recursive_update = True diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 4f3eae4493..459cfa875e 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -14,13 +14,16 @@ class ContainerConfigs: Args: workflow_directory (str | Path): The directory containing the workflow files. + org (str): Organisation path. """ def __init__( self, workflow_directory: str | Path = ".", + org: str = "nf-core", ): self.workflow_directory = Path(workflow_directory) + self.org: str = org def generate_container_configs(self) -> None: """Generate the container configuration files for a pipeline.""" @@ -97,7 +100,7 @@ def generate_all_container_configs(self, default_config: str) -> None: module_path = Path(module_name.lower()) try: - with open(self.workflow_directory / "modules" / module_path / "meta.yml") as fh: + with open(self.workflow_directory / "modules" / module_path / self.org / "meta.yml") as fh: meta = yaml.safe_load(fh) except FileNotFoundError: log.warning(f"Could not find meta.yml for {module_name}") From 015daa512eab055c498fa3811b9ac7e30fd69dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 2 Dec 2025 16:33:20 +0100 Subject: [PATCH 06/19] add tests --- nf_core/pipelines/containers_utils.py | 10 +- tests/pipelines/test_container_configs.py | 159 ++++++++++++++++++++++ 2 files changed, 164 insertions(+), 5 deletions(-) create mode 100644 tests/pipelines/test_container_configs.py diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 459cfa875e..36a8c884bf 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -27,11 +27,11 @@ def __init__( def generate_container_configs(self) -> None: """Generate the container configuration files for a pipeline.""" - self.check_nextflow_version() + self.check_nextflow_version_sufficient() default_config = self.generate_default_container_config() self.generate_all_container_configs(default_config) - def check_nextflow_version(self) -> None: + def check_nextflow_version_sufficient(self) -> None: """Check if the Nextflow version is sufficient to run `nextflow inspect`.""" if not check_nextflow_version(NF_INSPECT_MIN_NF_VERSION): raise UserWarning( @@ -80,7 +80,7 @@ def generate_all_container_configs(self, default_config: str) -> None: } for line in default_config.split("\n"): if line.startswith("process"): - pattern = r"process { withName: \'(.*)\' { container = \'(.*)\' } }\n" + pattern = r"process { withName: \'(.*)\' { container = \'(.*)\' } }" match = re.search(pattern, line) if match: try: @@ -100,7 +100,7 @@ def generate_all_container_configs(self, default_config: str) -> None: module_path = Path(module_name.lower()) try: - with open(self.workflow_directory / "modules" / module_path / self.org / "meta.yml") as fh: + with open(self.workflow_directory / "modules" / self.org / module_path / "meta.yml") as fh: meta = yaml.safe_load(fh) except FileNotFoundError: log.warning(f"Could not find meta.yml for {module_name}") @@ -159,5 +159,5 @@ def generate_all_container_configs(self, default_config: str) -> None: with open(self.workflow_directory / "conf" / f"containers_{platform}.config", "w") as fh: for module_name in containers[platform].keys(): fh.write( - f"process {{ withName: '{module_name}' {{ container = {containers[platform][module_name]}' }} }}\n" + f"process {{ withName: '{module_name}' {{ container = '{containers[platform][module_name]}' }} }}\n" ) diff --git a/tests/pipelines/test_container_configs.py b/tests/pipelines/test_container_configs.py new file mode 100644 index 0000000000..285444a66d --- /dev/null +++ b/tests/pipelines/test_container_configs.py @@ -0,0 +1,159 @@ +"""Tests for the ContainerConfigs helper used by pipelines.""" + +from pathlib import Path +from unittest.mock import patch + +import pytest +import yaml + +from nf_core.pipelines.containers_utils import ContainerConfigs +from nf_core.utils import NF_INSPECT_MIN_NF_VERSION, pretty_nf_version + +from ..test_pipelines import TestPipelines + + +class TestContainerConfigs(TestPipelines): + """Tests for ContainerConfigs using a test pipeline.""" + + def setUp(self) -> None: + super().setUp() + self.container_configs = ContainerConfigs(self.pipeline_dir, "nf-core") + + def test_check_nextflow_version_sufficient_ok(self) -> None: + """check_nextflow_version should return silently when version is sufficient.""" + with patch( + "nf_core.pipelines.containers_utils.check_nextflow_version", + return_value=True, + ) as mocked_check: + self.container_configs.check_nextflow_version_sufficient() + + mocked_check.assert_called_once_with(NF_INSPECT_MIN_NF_VERSION) + + def test_check_nextflow_version_sufficient_too_low(self) -> None: + """check_nextflow_version should raise UserWarning when version is too low.""" + with patch( + "nf_core.pipelines.containers_utils.check_nextflow_version", + return_value=False, + ): + with pytest.raises(UserWarning) as excinfo: + self.container_configs.check_nextflow_version_sufficient() + + # Error message should mention the minimal required version + assert pretty_nf_version(NF_INSPECT_MIN_NF_VERSION) in str(excinfo.value) + + def test_generate_default_container_config(self) -> None: + """Run generate_default_container_config with mocking.""" + mock_config_bytes = b"process { withName: 'FOO_BAR' { container = 'docker://foo/bar:amd64' } }\n" + + with patch( + "nf_core.pipelines.containers_utils.run_cmd", + return_value=(mock_config_bytes, b""), + ) as mocked_run_cmd: + out = self.container_configs.generate_default_container_config() + + expected_cmd_params = f"inspect -format config {self.pipeline_dir}" + mocked_run_cmd.assert_called_once_with("nextflow", expected_cmd_params) + + conf_path = Path(self.pipeline_dir / "conf" / "containers_docker_amd64.config") + assert conf_path.exists() + conf_path_content = conf_path.read_text(encoding="utf-8") + assert conf_path_content == mock_config_bytes.decode("utf-8") + assert out == conf_path_content + + def test_generate_default_container_config_in_pipeline(self) -> None: + """Run generate_default_container_config in a pipeline.""" + out = self.container_configs.generate_default_container_config() + conf_path = Path(self.pipeline_dir / "conf" / "containers_docker_amd64.config") + assert conf_path.exists() + conf_path_content = conf_path.read_text(encoding="utf-8") + # FASTQC and MULTIQC should be present in the config file + # Don't check for the exact version + assert "process { withName: 'FASTQC' { container = 'quay.io/biocontainers/fastqc" in conf_path_content + assert "process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc" in out + + def test_generate_all_container_configs(self) -> None: + """Run generate_all_container_configs in a pipeline.""" + # Mock generate_default_container_config() output + default_config = ( + "process { withName: 'FASTQC' { container = 'quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0' } }\n" + "process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf' } }\n" + ) + + # TODO: Test with real meata.yml files once they are available in the template + # Update meta.yml files + fastqc_dir = self.pipeline_dir / "modules" / "nf-core" / "fastqc" + meta = { + "containers": { + "docker": { + "linux_amd64": { + "name": "quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0", + }, + "linux_arm64": { + "name": "community.wave.seqera.io/library/fastqc:0.12.1--d3caca66b4f3d3b0", + }, + }, + "singularity": { + "linux_amd64": { + "name": "oras://community.wave.seqera.io/library/fastqc:0.12.1--0827550dd72a3745", + "https": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/b2/b280a35770a70ed67008c1d6b6db118409bc3adbb3a98edcd55991189e5116f6/data", + }, + "linux_arm64": { + "name": "oras://community.wave.seqera.io/library/fastqc:0.12.1--b2ccdee5305e5859", + "https": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/76/76e744b425a6b4c7eb8f12e03fa15daf7054de36557d2f0c4eb53ad952f9b0e3/data", + }, + }, + "conda": { + "linux_amd64": { + "lock_file": "https://wave.seqera.io/v1alpha1/builds/5cfd0f3cb6760c42_1/condalock", + }, + "linux_arm64": { + "lock_file": "https://wave.seqera.io/v1alpha1/builds/d3caca66b4f3d3b0_1/condalock", + }, + }, + }, + } + with (fastqc_dir / "meta.yml").open("r") as fh: + current_meta = yaml.safe_load(fh) + current_meta.update(meta) + with (fastqc_dir / "meta.yml").open("w") as fh: + yaml.safe_dump(current_meta, fh) + + self.container_configs.generate_all_container_configs(default_config) + + conf_dir = self.pipeline_dir / "conf" + # Expected platforms and one expected container + expected_platforms = { + "docker_arm64": { + "FASTQC": "community.wave.seqera.io/library/fastqc:0.12.1--d3caca66b4f3d3b0", + }, + "singularity_oras_amd64": { + "FASTQC": "oras://community.wave.seqera.io/library/fastqc:0.12.1--0827550dd72a3745", + }, + "singularity_oras_arm64": { + "FASTQC": "oras://community.wave.seqera.io/library/fastqc:0.12.1--b2ccdee5305e5859", + }, + "singularity_https_amd64": { + "FASTQC": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/b2/b280a35770a70ed67008c1d6b6db118409bc3adbb3a98edcd55991189e5116f6/data", + }, + "singularity_https_arm64": { + "FASTQC": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/76/76e744b425a6b4c7eb8f12e03fa15daf7054de36557d2f0c4eb53ad952f9b0e3/data", + }, + "conda_amd64_lockfile": { + "FASTQC": "https://wave.seqera.io/v1alpha1/builds/5cfd0f3cb6760c42_1/condalock", + }, + "conda_arm64_lockfile": { + "FASTQC": "https://wave.seqera.io/v1alpha1/builds/d3caca66b4f3d3b0_1/condalock", + }, + } + + for platform in expected_platforms.keys(): + cfg_path = conf_dir / f"containers_{platform}.config" + print(cfg_path) + assert cfg_path.exists() + with cfg_path.open("r") as fh: + content = fh.readlines() + print(content) + assert ( + f"process {{ withName: 'FASTQC' {{ container = '{expected_platforms[platform]['FASTQC']}' }} }}\n" + in content + ) From b8cf374c631d5b1debac5535a89a60b8a0d7b51a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Wed, 3 Dec 2025 10:33:09 +0100 Subject: [PATCH 07/19] less lines --- nf_core/components/components_utils.py | 8 ++++ nf_core/components/install.py | 7 +-- nf_core/components/remove.py | 7 +-- nf_core/components/update.py | 7 +-- nf_core/pipelines/containers_utils.py | 63 +++++++------------------- 5 files changed, 30 insertions(+), 62 deletions(-) diff --git a/nf_core/components/components_utils.py b/nf_core/components/components_utils.py index 7423de7f2b..55c1cd84e0 100644 --- a/nf_core/components/components_utils.py +++ b/nf_core/components/components_utils.py @@ -9,6 +9,7 @@ import nf_core.utils from nf_core.modules.modules_repo import ModulesRepo +from nf_core.pipelines.containers_utils import ContainerConfigs log = logging.getLogger(__name__) @@ -279,3 +280,10 @@ def _iterate_input_output(type) -> DictWithStrAndTuple: # If the tool name was not found in the response log.warning(f"Could not find an EDAM ontology term for '{tool_name}'") return None + + +def try_generate_container_configs(directory: str | Path, path: str): + try: + ContainerConfigs(directory, path).generate_container_configs() + except UserWarning as e: + log.warning(f"Could not regenerate container configuration files: {e}") diff --git a/nf_core/components/install.py b/nf_core/components/install.py index 5fc6135410..c5392c364a 100644 --- a/nf_core/components/install.py +++ b/nf_core/components/install.py @@ -16,13 +16,13 @@ from nf_core.components.components_utils import ( get_components_to_install, prompt_component_version_sha, + try_generate_container_configs, ) from nf_core.components.constants import ( NF_CORE_MODULES_NAME, ) from nf_core.modules.modules_json import ModulesJson from nf_core.modules.modules_repo import ModulesRepo -from nf_core.pipelines.containers_utils import ContainerConfigs log = logging.getLogger(__name__) @@ -170,10 +170,7 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool # Regenerate container configuration files for the pipeline when modules are installed if self.component_type == "modules": - try: - ContainerConfigs(self.directory, self.modules_repo.repo_path).generate_container_configs() - except UserWarning as e: - log.warning(f"Could not regenerate container configuration files: {e}") + try_generate_container_configs(self.directory, self.modules_repo.repo_path) if not silent: modules_json.load() diff --git a/nf_core/components/remove.py b/nf_core/components/remove.py index cf8566ff71..ef0668ddd8 100644 --- a/nf_core/components/remove.py +++ b/nf_core/components/remove.py @@ -8,8 +8,8 @@ import nf_core.utils from nf_core.components.components_command import ComponentCommand +from nf_core.components.components_utils import try_generate_container_configs from nf_core.modules.modules_json import ModulesJson -from nf_core.pipelines.containers_utils import ContainerConfigs from .install import ComponentInstall @@ -175,10 +175,7 @@ def remove(self, component, repo_url=None, repo_path=None, removed_by=None, remo removed_components.append(component_name.replace("/", "_")) # Regenerate container configuration files for the pipeline when modules are removed if self.component_type == "modules": - try: - ContainerConfigs(self.directory, repo_path).generate_container_configs() - except UserWarning as e: - log.warning(f"Could not regenerate container configuration files: {e}") + try_generate_container_configs(self.directory, repo_path) # print removed dependencies if removed_components: diff --git a/nf_core/components/update.py b/nf_core/components/update.py index c24331b142..af97625730 100644 --- a/nf_core/components/update.py +++ b/nf_core/components/update.py @@ -13,12 +13,12 @@ from nf_core.components.components_utils import ( get_components_to_install, prompt_component_version_sha, + try_generate_container_configs, ) from nf_core.components.install import ComponentInstall from nf_core.components.remove import ComponentRemove from nf_core.modules.modules_json import ModulesJson from nf_core.modules.modules_repo import ModulesRepo -from nf_core.pipelines.containers_utils import ContainerConfigs from nf_core.utils import plural_es, plural_s, plural_y log = logging.getLogger(__name__) @@ -302,10 +302,7 @@ def update(self, component=None, silent=False, updated=None, check_diff_exist=Tr # Regenerate container configuration files for the pipeline when modules are updated if self.component_type == "modules": - try: - ContainerConfigs(self.directory, modules_repo.repo_path).generate_container_configs() - except UserWarning as e: - log.warning(f"Could not regenerate container configuration files: {e}") + try_generate_container_configs(self.directory, modules_repo.repo_path) recursive_update = True modules_to_update, subworkflows_to_update = self.get_components_to_update(component) if not silent and len(modules_to_update + subworkflows_to_update) > 0: diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 36a8c884bf..ec898a4140 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -106,53 +106,22 @@ def generate_all_container_configs(self, default_config: str) -> None: log.warning(f"Could not find meta.yml for {module_name}") continue - try: - containers["docker_arm64"][module_name] = meta["containers"]["docker"]["linux_arm64"]["name"] - except KeyError: - log.warning(f"Could not find docker linux_arm64 container for {module_name}") - continue - try: - containers["singularity_oras_amd64"][module_name] = meta["containers"]["singularity"]["linux_amd64"][ - "name" - ] - except KeyError: - log.warning(f"Could not find singularity linux_amd64 oras container for {module_name}") - continue - try: - containers["singularity_oras_arm64"][module_name] = meta["containers"]["singularity"]["linux_arm64"][ - "name" - ] - except KeyError: - log.warning(f"Could not find singularity linux_arm64 oras container for {module_name}") - continue - try: - containers["singularity_https_amd64"][module_name] = meta["containers"]["singularity"]["linux_amd64"][ - "https" - ] - except KeyError: - log.warning(f"Could not find singularity linux_amd64 https URL for {module_name}") - continue - try: - containers["singularity_https_arm64"][module_name] = meta["containers"]["singularity"]["linux_arm64"][ - "https" - ] - except KeyError: - log.warning(f"Could not find singularity linux_arm64 https URL for {module_name}") - continue - try: - containers["conda_amd64_lockfile"][module_name] = meta["containers"]["conda"]["linux_amd64"][ - "lock_file" - ] - except KeyError: - log.warning(f"Could not find conda linux_amd64 lock file for {module_name}") - continue - try: - containers["conda_arm64_lockfile"][module_name] = meta["containers"]["conda"]["linux_arm64"][ - "lock_file" - ] - except KeyError: - log.warning(f"Could not find conda linux_arm64 lock file for {module_name}") - continue + platforms: dict[str, list[str]] = { + "docker_arm64": ["docker", "linux_arm64", "name"], + "singularity_oras_amd64": ["singularity", "linux_amd64", "name"], + "singularity_oras_arm64": ["singularity", "linux_arm64", "name"], + "singularity_https_amd64": ["singularity", "linux_amd64", "https"], + "singularity_https_arm64": ["singularity", "linux_arm64", "https"], + "conda_amd64_lockfile": ["conda", "linux_amd64", "lock_file"], + "conda_arm64_lockfile": ["conda", "linux_arm64", "lock_file"], + } + + for p_name, p_keys in platforms.items(): + try: + containers[p_name][module_name] = meta["containers"][p_keys[0]][p_keys[1]][p_keys[2]] + except KeyError: + log.warning(f"Could not find {p_name} container for {module_name}") + continue # write config files for platform in containers.keys(): From 0954ee68b2bfd78f1276f0ae3d93b544b3f283d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Thu, 4 Dec 2025 14:59:17 +0100 Subject: [PATCH 08/19] always update docker amd64 --- nf_core/pipelines/containers_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index ec898a4140..9ad3d7b8fc 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -107,6 +107,7 @@ def generate_all_container_configs(self, default_config: str) -> None: continue platforms: dict[str, list[str]] = { + "docker_amd64": ["docker", "linux_amd64", "name"], "docker_arm64": ["docker", "linux_arm64", "name"], "singularity_oras_amd64": ["singularity", "linux_amd64", "name"], "singularity_oras_arm64": ["singularity", "linux_arm64", "name"], From f5502c9e004c65a8fd9ac26dad39e944d4df8395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Thu, 4 Dec 2025 15:00:20 +0100 Subject: [PATCH 09/19] Update nf_core/pipelines/containers_utils.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Hörtenhuber --- nf_core/pipelines/containers_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 9ad3d7b8fc..54ce6c1590 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -117,9 +117,9 @@ def generate_all_container_configs(self, default_config: str) -> None: "conda_arm64_lockfile": ["conda", "linux_arm64", "lock_file"], } - for p_name, p_keys in platforms.items(): - try: - containers[p_name][module_name] = meta["containers"][p_keys[0]][p_keys[1]][p_keys[2]] + for p_name, (runtime, arch, protocol) in platforms.items(): + try: + containers[p_name][module_name] = meta["containers"][runtime][arch][protocol] except KeyError: log.warning(f"Could not find {p_name} container for {module_name}") continue From 7d2586d6a035531cf71a5767a2fcffcb99091bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Thu, 4 Dec 2025 15:01:31 +0100 Subject: [PATCH 10/19] spaces --- nf_core/pipelines/containers_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 54ce6c1590..07169efdd2 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -118,8 +118,8 @@ def generate_all_container_configs(self, default_config: str) -> None: } for p_name, (runtime, arch, protocol) in platforms.items(): - try: - containers[p_name][module_name] = meta["containers"][runtime][arch][protocol] + try: + containers[p_name][module_name] = meta["containers"][runtime][arch][protocol] except KeyError: log.warning(f"Could not find {p_name} container for {module_name}") continue From 0ab8425d0261537b49a3dadc54609e00c33a4e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Mon, 15 Dec 2025 15:04:58 +0100 Subject: [PATCH 11/19] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Hörtenhuber --- nf_core/components/components_utils.py | 2 +- nf_core/pipelines/containers_utils.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nf_core/components/components_utils.py b/nf_core/components/components_utils.py index 55c1cd84e0..05ce235841 100644 --- a/nf_core/components/components_utils.py +++ b/nf_core/components/components_utils.py @@ -282,7 +282,7 @@ def _iterate_input_output(type) -> DictWithStrAndTuple: return None -def try_generate_container_configs(directory: str | Path, path: str): +def try_generate_container_configs(directory: Path, path: Path): try: ContainerConfigs(directory, path).generate_container_configs() except UserWarning as e: diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 07169efdd2..88bb19df51 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -19,10 +19,10 @@ class ContainerConfigs: def __init__( self, - workflow_directory: str | Path = ".", + workflow_directory: Path = Path("."), org: str = "nf-core", ): - self.workflow_directory = Path(workflow_directory) + self.workflow_directory = workflow_directory self.org: str = org def generate_container_configs(self) -> None: From 0eb93230cc382f647f441522e903f7146efc7f73 Mon Sep 17 00:00:00 2001 From: mashehu Date: Mon, 15 Dec 2025 18:07:59 +0100 Subject: [PATCH 12/19] fix types --- nf_core/components/components_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nf_core/components/components_utils.py b/nf_core/components/components_utils.py index 05ce235841..5ec89d1c40 100644 --- a/nf_core/components/components_utils.py +++ b/nf_core/components/components_utils.py @@ -284,6 +284,6 @@ def _iterate_input_output(type) -> DictWithStrAndTuple: def try_generate_container_configs(directory: Path, path: Path): try: - ContainerConfigs(directory, path).generate_container_configs() + ContainerConfigs(directory, str(path)).generate_container_configs() except UserWarning as e: log.warning(f"Could not regenerate container configuration files: {e}") From 815102a69becf1f272a422b8b04870b29b634b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 16 Dec 2025 10:59:11 +0100 Subject: [PATCH 13/19] update fastqc and multiqc --- nf_core/pipeline-template/modules.json | 4 +- .../modules/nf-core/fastqc/main.nf | 16 +- .../modules/nf-core/fastqc/meta.yml | 51 +++- .../modules/nf-core/fastqc/tests/main.nf.test | 12 +- .../nf-core/fastqc/tests/main.nf.test.snap | 228 ++++++++++++------ .../modules/nf-core/multiqc/environment.yml | 2 +- .../modules/nf-core/multiqc/main.nf | 44 ++-- .../modules/nf-core/multiqc/meta.yml | 43 +++- .../multiqc/tests/custom_prefix.config | 5 + .../nf-core/multiqc/tests/main.nf.test | 32 ++- .../nf-core/multiqc/tests/main.nf.test.snap | 52 ++-- 11 files changed, 336 insertions(+), 153 deletions(-) create mode 100644 nf_core/pipeline-template/modules/nf-core/multiqc/tests/custom_prefix.config diff --git a/nf_core/pipeline-template/modules.json b/nf_core/pipeline-template/modules.json index caec6d9d75..a5923bc563 100644 --- a/nf_core/pipeline-template/modules.json +++ b/nf_core/pipeline-template/modules.json @@ -8,12 +8,12 @@ {%- if fastqc %} "fastqc": { "branch": "master", - "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", + "git_sha": "5bdb098216aaf5df9c3b6343e6204cd932503c16", "installed_by": ["modules"] }{% endif %}{%- if multiqc %}{% if fastqc %},{% endif %} "multiqc": { "branch": "master", - "git_sha": "af27af1be706e6a2bb8fe454175b0cdf77f47b49", + "git_sha": "5bdb098216aaf5df9c3b6343e6204cd932503c16", "installed_by": ["modules"] } {%- endif %} diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf b/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf index 23e16634c3..4b3041dc53 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf @@ -11,9 +11,9 @@ process FASTQC { tuple val(meta), path(reads) output: - tuple val(meta), path("*.html"), emit: html - tuple val(meta), path("*.zip") , emit: zip - path "versions.yml" , emit: versions + tuple val(meta) , path("*.html") , emit: html + tuple val(meta) , path("*.zip") , emit: zip + tuple val("${task.process}"), val('fastqc'), eval('fastqc --version | sed "/FastQC v/!d; s/.*v//"'), emit: versions_fastqc, topic: versions when: task.ext.when == null || task.ext.when @@ -43,11 +43,6 @@ process FASTQC { --threads ${task.cpus} \\ --memory ${fastqc_memory} \\ ${renamed_files} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ stub: @@ -55,10 +50,5 @@ process FASTQC { """ touch ${prefix}.html touch ${prefix}.zip - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ } diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml b/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml index c8d9d025ac..49164c88fb 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml @@ -53,13 +53,28 @@ output: description: FastQC report archive pattern: "*_{fastqc.zip}" ontologies: [] + versions_fastqc: + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool authors: - "@drpatelh" - "@grst" @@ -70,3 +85,27 @@ maintainers: - "@grst" - "@ewels" - "@FelixKrueger" +containers: + conda: + linux_amd64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-af7a5314d5015c29_1/condalock + linux_arm64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-df99cb252670875a_2/condalock + docker: + linux_amd64: + build_id: bd-af7a5314d5015c29_1 + name: community.wave.seqera.io/library/fastqc:0.12.1--af7a5314d5015c29 + scanId: sc-a618548acbee5a8a_30 + linux_arm64: + build_id: bd-df99cb252670875a_2 + name: community.wave.seqera.io/library/fastqc:0.12.1--df99cb252670875a + scanId: sc-b5913ed5d42b22d2_18 + singularity: + linux_amd64: + build_id: bd-104d26ddd9519960_1 + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--104d26ddd9519960 + https: https://community.wave.seqera.io/v2/library/fastqc/blobs/sha256:e0c976cb2eca5fee72618a581537a4f8ea42fcae24c9b201e2e0f764fd28648a + linux_arm64: + build_id: bd-d56b505a93aef38a_1 + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--d56b505a93aef38a + https: https://community.wave.seqera.io/v2/library/fastqc/blobs/sha256:fd39534bf298698cbe3ee4d4a6f1e73330ec4bca44c38dd9a4d06cb5ea838017 diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test index e9d79a074e..66c44da9bf 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test @@ -30,7 +30,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -58,7 +58,7 @@ nextflow_process { { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -82,7 +82,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -106,7 +106,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -142,7 +142,7 @@ nextflow_process { { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -166,7 +166,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap index d5db3092fb..c8ee120f56 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -1,15 +1,21 @@ { "sarscov2 custom_prefix": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:16.374038" + "timestamp": "2025-10-28T16:39:14.518503" }, "sarscov2 single-end [fastq] - stub": { "content": [ @@ -33,7 +39,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -44,8 +54,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -59,10 +73,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:24.993809" + "timestamp": "2025-10-28T16:39:19.309008" }, "sarscov2 custom_prefix - stub": { "content": [ @@ -86,7 +100,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -97,8 +115,12 @@ "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -112,58 +134,82 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:10.93942" + "timestamp": "2025-10-28T16:39:44.94888" }, "sarscov2 interleaved [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:42.355718" + "timestamp": "2025-10-28T16:38:45.168496" }, "sarscov2 paired-end [bam]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:53.276274" + "timestamp": "2025-10-28T16:38:53.268919" }, "sarscov2 multiple [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:05.527626" + "timestamp": "2025-10-28T16:39:05.050305" }, "sarscov2 paired-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:31.188871" + "timestamp": "2025-10-28T16:38:37.2373" }, "sarscov2 paired-end [fastq] - stub": { "content": [ @@ -187,7 +233,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -198,8 +248,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -213,10 +267,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:34.273566" + "timestamp": "2025-10-28T16:39:24.450398" }, "sarscov2 multiple [fastq] - stub": { "content": [ @@ -240,7 +294,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -251,8 +309,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -266,22 +328,28 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:02.304411" + "timestamp": "2025-10-28T16:39:39.758762" }, "sarscov2 single-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:19.095607" + "timestamp": "2025-10-28T16:38:29.555068" }, "sarscov2 interleaved [fastq] - stub": { "content": [ @@ -305,7 +373,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -316,8 +388,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -331,10 +407,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:44.640184" + "timestamp": "2025-10-28T16:39:29.193136" }, "sarscov2 paired-end [bam] - stub": { "content": [ @@ -358,7 +434,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -369,8 +449,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -384,9 +468,9 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:53.550742" + "timestamp": "2025-10-28T16:39:34.144919" } } \ No newline at end of file diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml b/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml index d02016a009..009874d4c0 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.32 + - bioconda::multiqc=1.33 diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf b/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf index c1158fb08c..3b0e975be6 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf @@ -3,11 +3,11 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c6c120d559d7ee04c7442b61ad7cf5a9e8970be5feefb37d68eeaa60c1034eb/data' : - 'community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf' }" + 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34e733a9ae16a27e80fe00f863ea1479c96416017f24a907996126283e7ecd4d/data' : + 'community.wave.seqera.io/library/multiqc:1.33--ee7739d47738383b' }" input: - path multiqc_files, stageAs: "?/*" + path multiqc_files, stageAs: "?/*" path(multiqc_config) path(extra_multiqc_config) path(multiqc_logo) @@ -15,10 +15,11 @@ process MULTIQC { path(sample_names) output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions + path "*.html" , emit: report + path "*_data" , emit: data + path "*_plots" , optional:true, emit: plots + tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions + // MultiQC should not push its versions to the `versions` topic. Its input depends on the versions topic to be resolved thus outputting to the topic will let the pipeline hang forever when: task.ext.when == null || task.ext.when @@ -26,38 +27,29 @@ process MULTIQC { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' - def config = multiqc_config ? "--config $multiqc_config" : '' - def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def config = multiqc_config ? "--config ${multiqc_config}" : '' + def extra_config = extra_multiqc_config ? "--config ${extra_multiqc_config}" : '' def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' def replace = replace_names ? "--replace-names ${replace_names}" : '' def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ - $args \\ - $config \\ - $prefix \\ - $extra_config \\ - $logo \\ - $replace \\ - $samples \\ + ${args} \\ + ${config} \\ + ${prefix} \\ + ${extra_config} \\ + ${logo} \\ + ${replace} \\ + ${samples} \\ . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ stub: """ mkdir multiqc_data + touch multiqc_data/.stub mkdir multiqc_plots touch multiqc_report.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ } diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml b/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml index ce30eb732b..f790cab0ff 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml @@ -57,10 +57,10 @@ input: - edam: http://edamontology.org/format_3475 # TSV output: report: - - "*multiqc_report.html": + - "*.html": type: file description: MultiQC report file - pattern: "multiqc_report.html" + pattern: ".html" ontologies: [] data: - "*_data": @@ -74,12 +74,15 @@ output: pattern: "*_data" ontologies: [] versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - multiqc: + type: string + description: The tool name + - multiqc --version | sed "s/.* //g": + type: eval + description: The expression to obtain the version of the tool authors: - "@abhi18av" - "@bunop" @@ -90,3 +93,27 @@ maintainers: - "@bunop" - "@drpatelh" - "@jfy133" +containers: + conda: + linux_amd64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-d58f60e4deb769bf_1/condalock + linux_arm64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-193776baee4194db_1/condalock + docker: + linux_amd64: + build_id: bd-d58f60e4deb769bf_1 + name: community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf + scanId: sc-d76ac07493e940b4_6 + linux_arm64: + build_id: bd-193776baee4194db_1 + name: community.wave.seqera.io/library/multiqc:1.32--193776baee4194db + scanId: sc-86caded0bff8246e_3 + singularity: + linux_amd64: + build_id: bd-e649ffa094d1ef4a_1 + name: oras://community.wave.seqera.io/library/multiqc:1.32--e649ffa094d1ef4a + https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:8c6c120d559d7ee04c7442b61ad7cf5a9e8970be5feefb37d68eeaa60c1034eb + linux_arm64: + build_id: bd-aee0064f5570ef22_1 + name: oras://community.wave.seqera.io/library/multiqc:1.32--aee0064f5570ef22 + https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:f02c59ebf6e9a00aa954ee8188a4ecc5c743e18f40b9215a242f67606a00f9cf diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/custom_prefix.config b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/custom_prefix.config new file mode 100644 index 0000000000..b30b1358b0 --- /dev/null +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/custom_prefix.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = "custom_prefix" + } +} diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test index 33316a7ddb..d1ae8b06c1 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test @@ -30,7 +30,33 @@ nextflow_process { { assert process.success }, { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_single") } + { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } + ) + } + + } + + test("sarscov2 single-end [fastqc] - custom prefix") { + config "./custom_prefix.config" + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = [] + input[2] = [] + input[3] = [] + input[4] = [] + input[5] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/custom_prefix.html" }, + { assert process.out.data[0] ==~ ".*/custom_prefix_data" } ) } @@ -56,7 +82,7 @@ nextflow_process { { assert process.success }, { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_config") } + { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } ) } } @@ -84,7 +110,7 @@ nextflow_process { { assert snapshot(process.out.report.collect { file(it).getName() } + process.out.data.collect { file(it).getName() } + process.out.plots.collect { file(it).getName() } + - process.out.versions ).match("multiqc_stub") } + process.out.findAll { key, val -> key.startsWith("versions")} ).match() } ) } diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap index a88bafd679..d72d35b747 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -1,41 +1,61 @@ { - "multiqc_versions_single": { + "sarscov2 single-end [fastqc]": { "content": [ - [ - "versions.yml:md5,737bb2c7cad54ffc2ec020791dc48b8f" - ] + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], "meta": { "nf-test": "0.9.3", - "nextflow": "24.10.4" + "nextflow": "25.10.2" }, - "timestamp": "2025-10-27T13:33:24.356715" + "timestamp": "2025-12-09T10:10:43.020315838" }, - "multiqc_stub": { + "sarscov2 single-end [fastqc] - stub": { "content": [ [ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,737bb2c7cad54ffc2ec020791dc48b8f" + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ] ], "meta": { "nf-test": "0.9.3", - "nextflow": "24.10.4" + "nextflow": "25.10.2" }, - "timestamp": "2025-10-27T13:34:11.103619" + "timestamp": "2025-12-09T10:11:14.131950776" }, - "multiqc_versions_config": { + "sarscov2 single-end [fastqc] [config]": { "content": [ - [ - "versions.yml:md5,737bb2c7cad54ffc2ec020791dc48b8f" - ] + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], "meta": { "nf-test": "0.9.3", - "nextflow": "24.10.4" + "nextflow": "25.10.2" }, - "timestamp": "2025-10-27T13:34:04.615233" + "timestamp": "2025-12-09T10:11:07.15692209" } } \ No newline at end of file From 426f319b8c1dc0ff83d4e2e44b7c40d0338e30d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 16 Dec 2025 12:31:57 +0100 Subject: [PATCH 14/19] inspect in json format and fix tests --- nf_core/pipelines/containers_utils.py | 35 ++---- tests/pipelines/test_container_configs.py | 140 ++++++++-------------- 2 files changed, 62 insertions(+), 113 deletions(-) diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 88bb19df51..8cfa74cdab 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -1,5 +1,5 @@ +import json import logging -import re from pathlib import Path import yaml @@ -39,7 +39,7 @@ def check_nextflow_version_sufficient(self) -> None: f"Please update your Nextflow version with [magenta]'nextflow self-update'[/]\n" ) - def generate_default_container_config(self) -> str: + def generate_default_container_config(self) -> dict: """ Generate the default container configuration file for a pipeline. Requires Nextflow >= 25.04.4 @@ -48,25 +48,20 @@ def generate_default_container_config(self) -> str: try: # Run nextflow inspect executable = "nextflow" - cmd_params = f"inspect -format config {self.workflow_directory}" + cmd_params = f"inspect -format json {self.workflow_directory}" cmd_out = run_cmd(executable, cmd_params) if cmd_out is None: raise UserWarning("Failed to run `nextflow inspect`. Please check your Nextflow installation.") out, _ = cmd_out - out_str = str(out, encoding="utf-8") - with open(self.workflow_directory / "conf" / "containers_docker_amd64.config", "w") as fh: - fh.write(out_str) - log.info( - f"Generated container config file for Docker AMD64: {self.workflow_directory / 'conf' / 'containers_docker_amd64.config'}" - ) - return out_str + out_json = json.loads(out) + return out_json except RuntimeError as e: log.error("Running 'nextflow inspect' failed with the following error:") raise UserWarning(e) - def generate_all_container_configs(self, default_config: str) -> None: + def generate_all_container_configs(self, default_config: dict) -> None: """Generate the container configuration files for all platforms.""" containers: dict[str, dict[str, str]] = { "docker_amd64": {}, @@ -78,20 +73,10 @@ def generate_all_container_configs(self, default_config: str) -> None: "conda_amd64_lockfile": {}, "conda_arm64_lockfile": {}, } - for line in default_config.split("\n"): - if line.startswith("process"): - pattern = r"process { withName: \'(.*)\' { container = \'(.*)\' } }" - match = re.search(pattern, line) - if match: - try: - module_name = match.group(1) - container = match.group(2) - except AttributeError: - log.warning(f"Could not parse container for process {line}") - continue - else: - continue - containers["docker_amd64"][module_name] = container + for module in default_config["processes"]: + module_name = module["name"] + m_container = module["container"] + containers["docker_amd64"][module_name] = m_container for module_name in containers["docker_amd64"].keys(): # Find module containers in meta.yml if "_" in module_name: diff --git a/tests/pipelines/test_container_configs.py b/tests/pipelines/test_container_configs.py index 285444a66d..d81b7368b0 100644 --- a/tests/pipelines/test_container_configs.py +++ b/tests/pipelines/test_container_configs.py @@ -1,16 +1,19 @@ """Tests for the ContainerConfigs helper used by pipelines.""" -from pathlib import Path +import json from unittest.mock import patch import pytest -import yaml +import ruamel.yaml +from nf_core.modules.install import ModuleInstall from nf_core.pipelines.containers_utils import ContainerConfigs from nf_core.utils import NF_INSPECT_MIN_NF_VERSION, pretty_nf_version from ..test_pipelines import TestPipelines +yaml = ruamel.yaml.YAML() + class TestContainerConfigs(TestPipelines): """Tests for ContainerConfigs using a test pipeline.""" @@ -43,7 +46,15 @@ def test_check_nextflow_version_sufficient_too_low(self) -> None: def test_generate_default_container_config(self) -> None: """Run generate_default_container_config with mocking.""" - mock_config_bytes = b"process { withName: 'FOO_BAR' { container = 'docker://foo/bar:amd64' } }\n" + mock_config = { + "processes": [ + { + "name": "FOO_BAR", + "container": "docker://foo/bar:amd64", + } + ] + } + mock_config_bytes = json.dumps(mock_config).encode() with patch( "nf_core.pipelines.containers_utils.run_cmd", @@ -51,109 +62,62 @@ def test_generate_default_container_config(self) -> None: ) as mocked_run_cmd: out = self.container_configs.generate_default_container_config() - expected_cmd_params = f"inspect -format config {self.pipeline_dir}" + expected_cmd_params = f"inspect -format json {self.pipeline_dir}" mocked_run_cmd.assert_called_once_with("nextflow", expected_cmd_params) - conf_path = Path(self.pipeline_dir / "conf" / "containers_docker_amd64.config") - assert conf_path.exists() - conf_path_content = conf_path.read_text(encoding="utf-8") - assert conf_path_content == mock_config_bytes.decode("utf-8") - assert out == conf_path_content + assert out == mock_config def test_generate_default_container_config_in_pipeline(self) -> None: """Run generate_default_container_config in a pipeline.""" out = self.container_configs.generate_default_container_config() - conf_path = Path(self.pipeline_dir / "conf" / "containers_docker_amd64.config") - assert conf_path.exists() - conf_path_content = conf_path.read_text(encoding="utf-8") - # FASTQC and MULTIQC should be present in the config file - # Don't check for the exact version - assert "process { withName: 'FASTQC' { container = 'quay.io/biocontainers/fastqc" in conf_path_content - assert "process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc" in out + assert isinstance(out, dict) + assert "processes" in out + + process_names = {proc["name"] for proc in out["processes"]} + assert "FASTQC" in process_names + assert "MULTIQC" in process_names def test_generate_all_container_configs(self) -> None: """Run generate_all_container_configs in a pipeline.""" # Mock generate_default_container_config() output - default_config = ( - "process { withName: 'FASTQC' { container = 'quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0' } }\n" - "process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf' } }\n" - ) - - # TODO: Test with real meata.yml files once they are available in the template - # Update meta.yml files - fastqc_dir = self.pipeline_dir / "modules" / "nf-core" / "fastqc" - meta = { - "containers": { - "docker": { - "linux_amd64": { - "name": "quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0", - }, - "linux_arm64": { - "name": "community.wave.seqera.io/library/fastqc:0.12.1--d3caca66b4f3d3b0", - }, - }, - "singularity": { - "linux_amd64": { - "name": "oras://community.wave.seqera.io/library/fastqc:0.12.1--0827550dd72a3745", - "https": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/b2/b280a35770a70ed67008c1d6b6db118409bc3adbb3a98edcd55991189e5116f6/data", - }, - "linux_arm64": { - "name": "oras://community.wave.seqera.io/library/fastqc:0.12.1--b2ccdee5305e5859", - "https": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/76/76e744b425a6b4c7eb8f12e03fa15daf7054de36557d2f0c4eb53ad952f9b0e3/data", - }, - }, - "conda": { - "linux_amd64": { - "lock_file": "https://wave.seqera.io/v1alpha1/builds/5cfd0f3cb6760c42_1/condalock", - }, - "linux_arm64": { - "lock_file": "https://wave.seqera.io/v1alpha1/builds/d3caca66b4f3d3b0_1/condalock", - }, - }, - }, + default_config = { + "processes": [ + {"name": "FASTQC", "container": "community.wave.seqera.io/library/fastqc:0.12.1--af7a5314d5015c29"}, + {"name": "MULTIQC", "container": "community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf"}, + ] } - with (fastqc_dir / "meta.yml").open("r") as fh: - current_meta = yaml.safe_load(fh) - current_meta.update(meta) - with (fastqc_dir / "meta.yml").open("w") as fh: - yaml.safe_dump(current_meta, fh) + + # Install fastqc and multiqc from gitlub seqera-containers test branch + mods_install = ModuleInstall( + self.pipeline_dir, + prompt=False, + force=False, + ) + mods_install.install("fastqc") + mods_install.install("multiqc") self.container_configs.generate_all_container_configs(default_config) conf_dir = self.pipeline_dir / "conf" # Expected platforms and one expected container - expected_platforms = { - "docker_arm64": { - "FASTQC": "community.wave.seqera.io/library/fastqc:0.12.1--d3caca66b4f3d3b0", - }, - "singularity_oras_amd64": { - "FASTQC": "oras://community.wave.seqera.io/library/fastqc:0.12.1--0827550dd72a3745", - }, - "singularity_oras_arm64": { - "FASTQC": "oras://community.wave.seqera.io/library/fastqc:0.12.1--b2ccdee5305e5859", - }, - "singularity_https_amd64": { - "FASTQC": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/b2/b280a35770a70ed67008c1d6b6db118409bc3adbb3a98edcd55991189e5116f6/data", - }, - "singularity_https_arm64": { - "FASTQC": "https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/76/76e744b425a6b4c7eb8f12e03fa15daf7054de36557d2f0c4eb53ad952f9b0e3/data", - }, - "conda_amd64_lockfile": { - "FASTQC": "https://wave.seqera.io/v1alpha1/builds/5cfd0f3cb6760c42_1/condalock", - }, - "conda_arm64_lockfile": { - "FASTQC": "https://wave.seqera.io/v1alpha1/builds/d3caca66b4f3d3b0_1/condalock", - }, + platforms: dict[str, list[str]] = { + "docker_amd64": ["docker", "linux_amd64", "name"], + "docker_arm64": ["docker", "linux_arm64", "name"], + "singularity_oras_amd64": ["singularity", "linux_amd64", "name"], + "singularity_oras_arm64": ["singularity", "linux_arm64", "name"], + "singularity_https_amd64": ["singularity", "linux_amd64", "https"], + "singularity_https_arm64": ["singularity", "linux_arm64", "https"], + "conda_amd64_lockfile": ["conda", "linux_amd64", "lock_file"], + "conda_arm64_lockfile": ["conda", "linux_arm64", "lock_file"], } - for platform in expected_platforms.keys(): - cfg_path = conf_dir / f"containers_{platform}.config" - print(cfg_path) + with open(self.pipeline_dir / "modules" / "nf-core" / "fastqc" / "meta.yml") as fh: + fastqc_meta_yml = yaml.load(fh) + + for p_name, (runtime, arch, protocol) in platforms.items(): + cfg_path = conf_dir / f"containers_{p_name}.config" assert cfg_path.exists() with cfg_path.open("r") as fh: content = fh.readlines() - print(content) - assert ( - f"process {{ withName: 'FASTQC' {{ container = '{expected_platforms[platform]['FASTQC']}' }} }}\n" - in content - ) + value = fastqc_meta_yml["containers"][runtime][arch][protocol] + assert f"process {{ withName: 'FASTQC' {{ container = '{value}' }} }}\n" in content From 51eb99baa5134724994f5d179eef31e69c1a385b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 16 Dec 2025 13:01:47 +0100 Subject: [PATCH 15/19] fix template after updating modules with topics --- nf_core/pipeline-template/workflows/pipeline.nf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nf_core/pipeline-template/workflows/pipeline.nf b/nf_core/pipeline-template/workflows/pipeline.nf index 4e91263d01..d293842657 100644 --- a/nf_core/pipeline-template/workflows/pipeline.nf +++ b/nf_core/pipeline-template/workflows/pipeline.nf @@ -43,14 +43,13 @@ workflow {{ short_name|upper }} { FASTQC ( ch_samplesheet ) - {% if multiqc %}ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}){% endif %} - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + {% if multiqc %}ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it -> it[1]}){% endif %} {%- endif %} // // Collate and save software versions // - def topic_versions = Channel.topic("versions") + def topic_versions = channel.topic("versions") .distinct() .branch { entry -> versions_file: entry instanceof Path From d2a797c55295b2a2edb6af9bf4ea80beaf73022f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 16 Dec 2025 13:12:00 +0100 Subject: [PATCH 16/19] update nf-test snapshots --- .github/snapshots/adaptivecard.nf.test.snap | 3 +++ .github/snapshots/changelog.nf.test.snap | 3 +++ .github/snapshots/ci.nf.test.snap | 3 +++ .github/snapshots/citations.nf.test.snap | 3 +++ .github/snapshots/code_linters.nf.test.snap | 3 +++ .github/snapshots/codespaces.nf.test.snap | 3 +++ .github/snapshots/default.nf.test.snap | 3 +++ .github/snapshots/documentation.nf.test.snap | 3 +++ .github/snapshots/email.nf.test.snap | 3 +++ .github/snapshots/github_badges.nf.test.snap | 3 +++ .github/snapshots/gitpod.nf.test.snap | 3 +++ .github/snapshots/gpu.nf.test.snap | 3 +++ .github/snapshots/igenomes.nf.test.snap | 3 +++ .github/snapshots/license.nf.test.snap | 3 +++ .github/snapshots/nf_core_configs.nf.test.snap | 3 +++ .github/snapshots/nf_schema.nf.test.snap | 3 +++ .github/snapshots/rocrate.nf.test.snap | 3 +++ .github/snapshots/seqera_platform.nf.test.snap | 3 +++ .github/snapshots/slackreport.nf.test.snap | 3 +++ .github/snapshots/vscode.nf.test.snap | 3 +++ 20 files changed, 60 insertions(+) diff --git a/.github/snapshots/adaptivecard.nf.test.snap b/.github/snapshots/adaptivecard.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/adaptivecard.nf.test.snap +++ b/.github/snapshots/adaptivecard.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/changelog.nf.test.snap b/.github/snapshots/changelog.nf.test.snap index aa731135a1..31ac663350 100644 --- a/.github/snapshots/changelog.nf.test.snap +++ b/.github/snapshots/changelog.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/ci.nf.test.snap b/.github/snapshots/ci.nf.test.snap index 79ff07945a..149d63a836 100644 --- a/.github/snapshots/ci.nf.test.snap +++ b/.github/snapshots/ci.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/citations.nf.test.snap b/.github/snapshots/citations.nf.test.snap index a135c5586e..44255f0aed 100644 --- a/.github/snapshots/citations.nf.test.snap +++ b/.github/snapshots/citations.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/code_linters.nf.test.snap b/.github/snapshots/code_linters.nf.test.snap index a135c5586e..44255f0aed 100644 --- a/.github/snapshots/code_linters.nf.test.snap +++ b/.github/snapshots/code_linters.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/codespaces.nf.test.snap b/.github/snapshots/codespaces.nf.test.snap index a135c5586e..44255f0aed 100644 --- a/.github/snapshots/codespaces.nf.test.snap +++ b/.github/snapshots/codespaces.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/default.nf.test.snap b/.github/snapshots/default.nf.test.snap index 0af1896079..10d9f99d25 100644 --- a/.github/snapshots/default.nf.test.snap +++ b/.github/snapshots/default.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/documentation.nf.test.snap b/.github/snapshots/documentation.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/documentation.nf.test.snap +++ b/.github/snapshots/documentation.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/email.nf.test.snap b/.github/snapshots/email.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/email.nf.test.snap +++ b/.github/snapshots/email.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/github_badges.nf.test.snap b/.github/snapshots/github_badges.nf.test.snap index a0da86f7bf..a8205a87fe 100644 --- a/.github/snapshots/github_badges.nf.test.snap +++ b/.github/snapshots/github_badges.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/gitpod.nf.test.snap b/.github/snapshots/gitpod.nf.test.snap index a135c5586e..44255f0aed 100644 --- a/.github/snapshots/gitpod.nf.test.snap +++ b/.github/snapshots/gitpod.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/gpu.nf.test.snap b/.github/snapshots/gpu.nf.test.snap index 0d51c52abf..4df8faa93a 100644 --- a/.github/snapshots/gpu.nf.test.snap +++ b/.github/snapshots/gpu.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/igenomes.nf.test.snap b/.github/snapshots/igenomes.nf.test.snap index 8d57911ba9..be95b1ea6d 100644 --- a/.github/snapshots/igenomes.nf.test.snap +++ b/.github/snapshots/igenomes.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/license.nf.test.snap b/.github/snapshots/license.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/license.nf.test.snap +++ b/.github/snapshots/license.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/nf_core_configs.nf.test.snap b/.github/snapshots/nf_core_configs.nf.test.snap index a135c5586e..44255f0aed 100644 --- a/.github/snapshots/nf_core_configs.nf.test.snap +++ b/.github/snapshots/nf_core_configs.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/nf_schema.nf.test.snap b/.github/snapshots/nf_schema.nf.test.snap index 6ccaacba0b..60a5d97d58 100644 --- a/.github/snapshots/nf_schema.nf.test.snap +++ b/.github/snapshots/nf_schema.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/rocrate.nf.test.snap b/.github/snapshots/rocrate.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/rocrate.nf.test.snap +++ b/.github/snapshots/rocrate.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/seqera_platform.nf.test.snap b/.github/snapshots/seqera_platform.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/seqera_platform.nf.test.snap +++ b/.github/snapshots/seqera_platform.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/slackreport.nf.test.snap b/.github/snapshots/slackreport.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/slackreport.nf.test.snap +++ b/.github/snapshots/slackreport.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/vscode.nf.test.snap b/.github/snapshots/vscode.nf.test.snap index c8ebafde24..b00bca3471 100644 --- a/.github/snapshots/vscode.nf.test.snap +++ b/.github/snapshots/vscode.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", From c3d04f008036eb7c749cf4aeba8dc46be5a1df3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 16 Dec 2025 13:28:04 +0100 Subject: [PATCH 17/19] add missing commas --- .github/snapshots/adaptivecard.nf.test.snap | 6 +++--- .github/snapshots/changelog.nf.test.snap | 6 +++--- .github/snapshots/ci.nf.test.snap | 6 +++--- .github/snapshots/citations.nf.test.snap | 6 +++--- .github/snapshots/code_linters.nf.test.snap | 6 +++--- .github/snapshots/codespaces.nf.test.snap | 6 +++--- .github/snapshots/default.nf.test.snap | 6 +++--- .github/snapshots/documentation.nf.test.snap | 6 +++--- .github/snapshots/email.nf.test.snap | 6 +++--- .github/snapshots/github_badges.nf.test.snap | 6 +++--- .github/snapshots/gitpod.nf.test.snap | 6 +++--- .github/snapshots/gpu.nf.test.snap | 6 +++--- .github/snapshots/igenomes.nf.test.snap | 6 +++--- .github/snapshots/license.nf.test.snap | 6 +++--- .github/snapshots/nf_core_configs.nf.test.snap | 6 +++--- .github/snapshots/nf_schema.nf.test.snap | 6 +++--- .github/snapshots/rocrate.nf.test.snap | 6 +++--- .github/snapshots/seqera_platform.nf.test.snap | 6 +++--- .github/snapshots/slackreport.nf.test.snap | 6 +++--- .github/snapshots/vscode.nf.test.snap | 6 +++--- 20 files changed, 60 insertions(+), 60 deletions(-) diff --git a/.github/snapshots/adaptivecard.nf.test.snap b/.github/snapshots/adaptivecard.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/adaptivecard.nf.test.snap +++ b/.github/snapshots/adaptivecard.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/changelog.nf.test.snap b/.github/snapshots/changelog.nf.test.snap index 31ac663350..dce153ef5e 100644 --- a/.github/snapshots/changelog.nf.test.snap +++ b/.github/snapshots/changelog.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/ci.nf.test.snap b/.github/snapshots/ci.nf.test.snap index 149d63a836..f327e5b10c 100644 --- a/.github/snapshots/ci.nf.test.snap +++ b/.github/snapshots/ci.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/citations.nf.test.snap b/.github/snapshots/citations.nf.test.snap index 44255f0aed..860baca828 100644 --- a/.github/snapshots/citations.nf.test.snap +++ b/.github/snapshots/citations.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/code_linters.nf.test.snap b/.github/snapshots/code_linters.nf.test.snap index 44255f0aed..860baca828 100644 --- a/.github/snapshots/code_linters.nf.test.snap +++ b/.github/snapshots/code_linters.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/codespaces.nf.test.snap b/.github/snapshots/codespaces.nf.test.snap index 44255f0aed..860baca828 100644 --- a/.github/snapshots/codespaces.nf.test.snap +++ b/.github/snapshots/codespaces.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/default.nf.test.snap b/.github/snapshots/default.nf.test.snap index 10d9f99d25..522cb600b6 100644 --- a/.github/snapshots/default.nf.test.snap +++ b/.github/snapshots/default.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/documentation.nf.test.snap b/.github/snapshots/documentation.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/documentation.nf.test.snap +++ b/.github/snapshots/documentation.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/email.nf.test.snap b/.github/snapshots/email.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/email.nf.test.snap +++ b/.github/snapshots/email.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/github_badges.nf.test.snap b/.github/snapshots/github_badges.nf.test.snap index a8205a87fe..44dd973359 100644 --- a/.github/snapshots/github_badges.nf.test.snap +++ b/.github/snapshots/github_badges.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/gitpod.nf.test.snap b/.github/snapshots/gitpod.nf.test.snap index 44255f0aed..860baca828 100644 --- a/.github/snapshots/gitpod.nf.test.snap +++ b/.github/snapshots/gitpod.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/gpu.nf.test.snap b/.github/snapshots/gpu.nf.test.snap index 4df8faa93a..8ab9a90bf6 100644 --- a/.github/snapshots/gpu.nf.test.snap +++ b/.github/snapshots/gpu.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/igenomes.nf.test.snap b/.github/snapshots/igenomes.nf.test.snap index be95b1ea6d..7d3d0951f8 100644 --- a/.github/snapshots/igenomes.nf.test.snap +++ b/.github/snapshots/igenomes.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/license.nf.test.snap b/.github/snapshots/license.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/license.nf.test.snap +++ b/.github/snapshots/license.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/nf_core_configs.nf.test.snap b/.github/snapshots/nf_core_configs.nf.test.snap index 44255f0aed..860baca828 100644 --- a/.github/snapshots/nf_core_configs.nf.test.snap +++ b/.github/snapshots/nf_core_configs.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/nf_schema.nf.test.snap b/.github/snapshots/nf_schema.nf.test.snap index 60a5d97d58..25eb8c5dba 100644 --- a/.github/snapshots/nf_schema.nf.test.snap +++ b/.github/snapshots/nf_schema.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/rocrate.nf.test.snap b/.github/snapshots/rocrate.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/rocrate.nf.test.snap +++ b/.github/snapshots/rocrate.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/seqera_platform.nf.test.snap b/.github/snapshots/seqera_platform.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/seqera_platform.nf.test.snap +++ b/.github/snapshots/seqera_platform.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/slackreport.nf.test.snap b/.github/snapshots/slackreport.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/slackreport.nf.test.snap +++ b/.github/snapshots/slackreport.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/vscode.nf.test.snap b/.github/snapshots/vscode.nf.test.snap index b00bca3471..e45193040a 100644 --- a/.github/snapshots/vscode.nf.test.snap +++ b/.github/snapshots/vscode.nf.test.snap @@ -47,7 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf" + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -60,7 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png" + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -73,7 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg" + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", From df715e2808ff36ba6ce2fd7faeff1e0f7547de7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Tue, 16 Dec 2025 16:04:25 +0100 Subject: [PATCH 18/19] simplify functions, thanks @mashehu --- nf_core/pipelines/containers_utils.py | 93 ++++++++++------------- tests/pipelines/test_container_configs.py | 44 +---------- 2 files changed, 42 insertions(+), 95 deletions(-) diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py index 8cfa74cdab..0a9722cc78 100644 --- a/nf_core/pipelines/containers_utils.py +++ b/nf_core/pipelines/containers_utils.py @@ -25,12 +25,6 @@ def __init__( self.workflow_directory = workflow_directory self.org: str = org - def generate_container_configs(self) -> None: - """Generate the container configuration files for a pipeline.""" - self.check_nextflow_version_sufficient() - default_config = self.generate_default_container_config() - self.generate_all_container_configs(default_config) - def check_nextflow_version_sufficient(self) -> None: """Check if the Nextflow version is sufficient to run `nextflow inspect`.""" if not check_nextflow_version(NF_INSPECT_MIN_NF_VERSION): @@ -39,11 +33,12 @@ def check_nextflow_version_sufficient(self) -> None: f"Please update your Nextflow version with [magenta]'nextflow self-update'[/]\n" ) - def generate_default_container_config(self) -> dict: + def generate_container_configs(self) -> None: """ - Generate the default container configuration file for a pipeline. + Generate the container configuration files for a pipeline. Requires Nextflow >= 25.04.4 """ + self.check_nextflow_version_sufficient() log.debug("Generating container config file with [magenta bold]nextflow inspect[/].") try: # Run nextflow inspect @@ -55,64 +50,58 @@ def generate_default_container_config(self) -> dict: out, _ = cmd_out out_json = json.loads(out) - return out_json except RuntimeError as e: log.error("Running 'nextflow inspect' failed with the following error:") raise UserWarning(e) - def generate_all_container_configs(self, default_config: dict) -> None: - """Generate the container configuration files for all platforms.""" - containers: dict[str, dict[str, str]] = { - "docker_amd64": {}, - "docker_arm64": {}, - "singularity_oras_amd64": {}, - "singularity_oras_arm64": {}, - "singularity_https_amd64": {}, - "singularity_https_arm64": {}, - "conda_amd64_lockfile": {}, - "conda_arm64_lockfile": {}, + module_names = [p.get("name") for p in out_json["processes"] if p.get("name")] + + platforms: dict[str, list[str]] = { + "docker_amd64": ["docker", "linux_amd64", "name"], + "docker_arm64": ["docker", "linux_arm64", "name"], + "singularity_oras_amd64": ["singularity", "linux_amd64", "name"], + "singularity_oras_arm64": ["singularity", "linux_arm64", "name"], + "singularity_https_amd64": ["singularity", "linux_amd64", "https"], + "singularity_https_arm64": ["singularity", "linux_arm64", "https"], + "conda_amd64_lockfile": ["conda", "linux_amd64", "lock_file"], + "conda_arm64_lockfile": ["conda", "linux_arm64", "lock_file"], } - for module in default_config["processes"]: - module_name = module["name"] - m_container = module["container"] - containers["docker_amd64"][module_name] = m_container - for module_name in containers["docker_amd64"].keys(): - # Find module containers in meta.yml - if "_" in module_name: - module_path = Path(module_name.split("_")[0].lower()) / module_name.split("_")[1].lower() + + # Build containers dict from module meta.yml files + # Pre-initialize all platforms to avoid repeated existence checks + containers: dict[str, dict[str, str]] = {platform: {} for platform in platforms} + for m_name in module_names: + # Parse module path once with maxsplit to handle edge cases + parts = m_name.split("_", 1) + if len(parts) == 2: + module_path = Path(parts[0].lower()) / parts[1].lower() else: - module_path = Path(module_name.lower()) + module_path = Path(m_name.lower()) try: - with open(self.workflow_directory / "modules" / self.org / module_path / "meta.yml") as fh: + meta_path = self.workflow_directory / "modules" / self.org / module_path / "meta.yml" + with open(meta_path) as fh: meta = yaml.safe_load(fh) except FileNotFoundError: - log.warning(f"Could not find meta.yml for {module_name}") + log.warning(f"Could not find meta.yml for {m_name}") continue - platforms: dict[str, list[str]] = { - "docker_amd64": ["docker", "linux_amd64", "name"], - "docker_arm64": ["docker", "linux_arm64", "name"], - "singularity_oras_amd64": ["singularity", "linux_amd64", "name"], - "singularity_oras_arm64": ["singularity", "linux_arm64", "name"], - "singularity_https_amd64": ["singularity", "linux_amd64", "https"], - "singularity_https_arm64": ["singularity", "linux_arm64", "https"], - "conda_amd64_lockfile": ["conda", "linux_amd64", "lock_file"], - "conda_arm64_lockfile": ["conda", "linux_arm64", "lock_file"], - } - - for p_name, (runtime, arch, protocol) in platforms.items(): + # Extract containers for all platforms + for platform_name, (runtime, arch, protocol) in platforms.items(): try: - containers[p_name][module_name] = meta["containers"][runtime][arch][protocol] - except KeyError: - log.warning(f"Could not find {p_name} container for {module_name}") + containers[platform_name][m_name] = meta["containers"][runtime][arch][protocol] + except (KeyError, TypeError): + log.warning(f"Could not find {platform_name} container for {m_name}") continue # write config files - for platform in containers.keys(): - with open(self.workflow_directory / "conf" / f"containers_{platform}.config", "w") as fh: - for module_name in containers[platform].keys(): - fh.write( - f"process {{ withName: '{module_name}' {{ container = '{containers[platform][module_name]}' }} }}\n" - ) + for platform, module_containers in containers.items(): + if not module_containers: + continue + lines = [ + f"process {{ withName: '{module_name}' {{ container = '{container}' }} }}\n" + for module_name, container in module_containers.items() + ] + config_path = self.workflow_directory / "conf" / f"containers_{platform}.config" + config_path.write_text("".join(lines)) diff --git a/tests/pipelines/test_container_configs.py b/tests/pipelines/test_container_configs.py index d81b7368b0..4001027d89 100644 --- a/tests/pipelines/test_container_configs.py +++ b/tests/pipelines/test_container_configs.py @@ -1,6 +1,5 @@ """Tests for the ContainerConfigs helper used by pipelines.""" -import json from unittest.mock import patch import pytest @@ -44,49 +43,8 @@ def test_check_nextflow_version_sufficient_too_low(self) -> None: # Error message should mention the minimal required version assert pretty_nf_version(NF_INSPECT_MIN_NF_VERSION) in str(excinfo.value) - def test_generate_default_container_config(self) -> None: - """Run generate_default_container_config with mocking.""" - mock_config = { - "processes": [ - { - "name": "FOO_BAR", - "container": "docker://foo/bar:amd64", - } - ] - } - mock_config_bytes = json.dumps(mock_config).encode() - - with patch( - "nf_core.pipelines.containers_utils.run_cmd", - return_value=(mock_config_bytes, b""), - ) as mocked_run_cmd: - out = self.container_configs.generate_default_container_config() - - expected_cmd_params = f"inspect -format json {self.pipeline_dir}" - mocked_run_cmd.assert_called_once_with("nextflow", expected_cmd_params) - - assert out == mock_config - - def test_generate_default_container_config_in_pipeline(self) -> None: - """Run generate_default_container_config in a pipeline.""" - out = self.container_configs.generate_default_container_config() - assert isinstance(out, dict) - assert "processes" in out - - process_names = {proc["name"] for proc in out["processes"]} - assert "FASTQC" in process_names - assert "MULTIQC" in process_names - def test_generate_all_container_configs(self) -> None: """Run generate_all_container_configs in a pipeline.""" - # Mock generate_default_container_config() output - default_config = { - "processes": [ - {"name": "FASTQC", "container": "community.wave.seqera.io/library/fastqc:0.12.1--af7a5314d5015c29"}, - {"name": "MULTIQC", "container": "community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf"}, - ] - } - # Install fastqc and multiqc from gitlub seqera-containers test branch mods_install = ModuleInstall( self.pipeline_dir, @@ -96,7 +54,7 @@ def test_generate_all_container_configs(self) -> None: mods_install.install("fastqc") mods_install.install("multiqc") - self.container_configs.generate_all_container_configs(default_config) + self.container_configs.generate_container_configs() conf_dir = self.pipeline_dir / "conf" # Expected platforms and one expected container From bd982090f3e5a0e855cc5bb52e8d3172bd1d825d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlia=20Mir=20Pedrol?= Date: Wed, 17 Dec 2025 12:42:03 +0100 Subject: [PATCH 19/19] Update tests/pipelines/test_container_configs.py --- tests/pipelines/test_container_configs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pipelines/test_container_configs.py b/tests/pipelines/test_container_configs.py index 4001027d89..54d70def6f 100644 --- a/tests/pipelines/test_container_configs.py +++ b/tests/pipelines/test_container_configs.py @@ -45,7 +45,7 @@ def test_check_nextflow_version_sufficient_too_low(self) -> None: def test_generate_all_container_configs(self) -> None: """Run generate_all_container_configs in a pipeline.""" - # Install fastqc and multiqc from gitlub seqera-containers test branch + # Install fastqc and multiqc mods_install = ModuleInstall( self.pipeline_dir, prompt=False,