Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions docs/api/_src/api/nf_core_yml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# .nf-core.yml configuration

The `.nf-core.yml` file at the root of any nf-core repository controls how nf-core
tools behaves for that repository. It is read by `load_tools_config()` and validated
against the `NFCoreYamlConfig` Pydantic model.

## Minimal examples

Pipeline repository:

```yaml
repository_type: pipeline
nf_core_version: "3.2.0"
```

Modules repository:

```yaml
repository_type: modules
nf_core_version: "3.2.0"
container-registry:
- community.wave.seqera.io/library/
```

## Schema

### Top-level `.nf-core.yml` schema (`NFCoreYamlConfig`)

```{eval-rst}
.. autopydantic_model:: nf_core.utils.NFCoreYamlConfig
:members:
:undoc-members:
:show-inheritance:
:model-show-json: false
:model-show-config-summary: false
:model-show-validator-members: false
:model-show-field-summary: true
:field-show-alias: true
```

### `lint` block (`NFCoreYamlLintConfig`)

```{eval-rst}
.. autopydantic_model:: nf_core.utils.NFCoreYamlLintConfig
:members:
:undoc-members:
:show-inheritance:
:model-show-json: false
:model-show-config-summary: false
:model-show-validator-members: false
:model-show-field-summary: true
:field-show-alias: true
```

### `template` block (`NFCoreTemplateConfig`)

```{eval-rst}
.. autopydantic_model:: nf_core.utils.NFCoreTemplateConfig
:members:
:undoc-members:
:show-inheritance:
:model-show-json: false
:model-show-config-summary: false
:model-show-validator-members: false
:model-show-field-summary: true
:field-show-alias: true
```
1 change: 1 addition & 0 deletions docs/api/_src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ This API documentation is for the [`nf-core/tools`](https://github.com/nf-core/t
- [Module code lint tests](./module_lint_tests/environment_yml.md) (run by `nf-core modules lint`)
- [Subworkflow code lint tests](./subworkflow_lint_tests/main_nf.md) (run by `nf-core subworkflows lint`)
- [nf-core/tools Python package API reference](./api/utils.md)
- [`.nf-core.yml` configuration reference](./api/nf_core_yml.md)
8 changes: 4 additions & 4 deletions nf_core/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1316,8 +1316,8 @@ def command_modules_test(ctx, tool, directory, no_prompts, update, once, profile
"--registry",
type=str,
metavar="<registry>",
default=None,
help="Registry to use for containers. If not specified it will use docker.registry value in the nextflow.config file",
default="quay.io,community.wave.seqera.io/library/",
help="Comma-separated list of allowed container registry prefixes.",
)
@click.option(
"-k",
Expand Down Expand Up @@ -1608,8 +1608,8 @@ def command_subworkflows_list_local(ctx, keywords, json, directory): # pylint:
"--registry",
type=str,
metavar="<registry>",
default=None,
help="Registry to use for containers. If not specified it will use docker.registry value in the nextflow.config file",
default="quay.io,community.wave.seqera.io/library/",
help="Comma-separated list of allowed container registry prefixes.",
)
@click.option(
"-k",
Expand Down
1 change: 0 additions & 1 deletion nf_core/commands_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ def modules_lint(
)
module_lint.lint(
module=tool,
registry=registry,
key=key,
all_modules=all_modules,
print_results=True,
Expand Down
1 change: 0 additions & 1 deletion nf_core/commands_subworkflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ def subworkflows_lint(
)
subworkflow_lint.lint(
subworkflow=subworkflow,
registry=registry,
key=key,
all_subworkflows=all_subworkflows,
print_results=True,
Expand Down
13 changes: 6 additions & 7 deletions nf_core/components/lint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __init__(
remote_url: str | None = None,
branch: str | None = None,
no_pull: bool = False,
registry: str | None = None,
registry: str = "quay.io,community.wave.seqera.io/library/",
hide_progress: bool = False,
):
super().__init__(
Expand Down Expand Up @@ -156,12 +156,11 @@ def __init__(
def __repr__(self) -> str:
return f"ComponentLint({self.component_type}, {self.directory})"

def _set_registry(self, registry) -> None:
if registry is None:
self.registry = self.config.get("docker.registry", "quay.io")
else:
self.registry = registry
log.debug(f"Registry set to {self.registry}")
def _set_registry(self, registry: str) -> None:
_, tools_config = nf_core.utils.load_tools_config(self.directory)
user_registries: list[str] = (tools_config.container_registry or []) if tools_config else []
self.registry: tuple[str, ...] = (*registry.split(","), *user_registries)
log.debug(f"Registries set to {self.registry}")

@property
def local_module_exclude_tests(self):
Expand Down
12 changes: 4 additions & 8 deletions nf_core/modules/lint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __init__(
remote_url: str | None = None,
branch: str | None = None,
no_pull: bool = False,
registry: str | None = None,
registry: str = "quay.io,community.wave.seqera.io/library/",
hide_progress: bool = False,
):
super().__init__(
Expand All @@ -88,7 +88,6 @@ def __init__(
def lint(
self,
module=None,
registry="quay.io",
key=(),
all_modules=False,
print_results=True,
Expand Down Expand Up @@ -173,25 +172,22 @@ def lint(

# Lint local modules
if local and len(local_modules) > 0:
self.lint_modules(local_modules, registry=registry, local=True, fix_version=fix_version)
self.lint_modules(local_modules, local=True, fix_version=fix_version)

# Lint nf-core modules
if not local and len(remote_modules) > 0:
self.lint_modules(remote_modules, registry=registry, local=False, fix_version=fix_version)
self.lint_modules(remote_modules, local=False, fix_version=fix_version)

if print_results:
self._print_results(show_passed=show_passed, sort_by=sort_by, plain_text=plain_text)
self.print_summary(plain_text=plain_text)

def lint_modules(
self, modules: list[NFCoreComponent], registry: str = "quay.io", local: bool = False, fix_version: bool = False
) -> None:
def lint_modules(self, modules: list[NFCoreComponent], local: bool = False, fix_version: bool = False) -> None:
"""
Lint a list of modules

Args:
modules ([NFCoreComponent]): A list of module objects
registry (str): The container registry to use. Should be quay.io in most situations.
local (boolean): Whether the list consist of local or nf-core modules
fix_version (boolean): Fix the module version if a newer version is available
"""
Expand Down
31 changes: 17 additions & 14 deletions nf_core/modules/lint/main_nf.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


def main_nf(
module_lint_object, module: NFCoreComponent, fix_version: bool, registry: str, progress_bar: Progress
module_lint_object, module: NFCoreComponent, fix_version: bool, registry: tuple[str, ...], progress_bar: Progress
) -> tuple[list[str], list[str]]:
"""Lint a ``main.nf`` module file

Expand Down Expand Up @@ -359,15 +359,17 @@ def check_when_section(self, lines):
self.passed.append(("main_nf", "when_condition", "when: condition is unchanged", self.main_nf))


def check_process_section(self, lines, registry, fix_version, progress_bar):
def check_process_section(
self, lines: list[str], registry: tuple[str, ...], fix_version: bool, progress_bar: Progress | None
):
"""Lint the section of a module between the process definition
and the 'input:' definition
Specifically checks for correct software versions
and containers

Args:
lines (List[str]): Content of process.
registry (str): Base Docker registry for containers. Typically quay.io.
lines (list[str]): Content of process.
registry (tuple[str, ...]): Allowed container registry prefixes.
fix_version (bool): Fix software version
progress_bar (ProgressBar): Progress bar to update.

Expand All @@ -384,6 +386,7 @@ def check_process_section(self, lines, registry, fix_version, progress_bar):
singularity_tag = None
docker_tag = None
bioconda_packages = []
allowed_registries = registry

# Process name should be all capital letters
if all(x.upper() for x in self.process_name):
Expand Down Expand Up @@ -450,7 +453,7 @@ def check_process_section(self, lines, registry, fix_version, progress_bar):
else:
self.failed.append(("main_nf", "docker_tag", "Unable to parse docker tag", self.main_nf))
docker_tag = None
if line.startswith((registry, "community.wave.seqera.io/library/")):
if line.startswith(allowed_registries):
l_stripped = re.sub(r"\W+$", "", line)
self.passed.append(
(
Expand All @@ -465,15 +468,11 @@ def check_process_section(self, lines, registry, fix_version, progress_bar):
(
"main_nf",
"container_links",
"Container prefix is not correct. Please add the registry prefix (e.g. 'quay.io/')",
f"Container prefix is not correct. Please add one of the allowed registry prefixes: {', '.join(f'{r}' for r in allowed_registries)}",
self.main_nf,
)
)

# Guess if container name is simple one (e.g. nfcore/ubuntu:20.04)
# If so, add quay.io as default container prefix
if line.count("/") == 1 and line.count(":") == 1:
line = "/".join([registry, line]).replace("//", "/")
url = urlparse(line.split("'")[0])

if line.startswith("container") or _container_type(line) == "docker" or _container_type(line) == "singularity":
Expand Down Expand Up @@ -564,7 +563,10 @@ def check_process_section(self, lines, registry, fix_version, progress_bar):
log.debug(f"Unable to update package {package} due to error: {e}")
else:
if fixed:
progress_bar.print(f"[blue]INFO[/blue]\t Updating package '{package}' {ver} -> {last_ver}")
if progress_bar is not None:
progress_bar.print(
f"[blue]INFO[/blue]\t Updating package '{package}' {ver} -> {last_ver}"
)
log.debug(f"Updating package {package} {ver} -> {last_ver}")
self.passed.append(
(
Expand All @@ -575,9 +577,10 @@ def check_process_section(self, lines, registry, fix_version, progress_bar):
)
)
else:
progress_bar.print(
f"[blue]INFO[/blue]\t Tried to update package. Unable to update package '{package}' {ver} -> {last_ver}"
)
if progress_bar is not None:
progress_bar.print(
f"[blue]INFO[/blue]\t Tried to update package. Unable to update package '{package}' {ver} -> {last_ver}"
)
log.debug(f"Unable to update package {package} {ver} -> {last_ver}")
self.warned.append(
(
Expand Down
4 changes: 2 additions & 2 deletions nf_core/pipelines/lint/nfcore_yml.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ def nfcore_yml(self) -> dict[str, list[str]]:

The ``.nf-core.yml`` contains metadata for nf-core tools to correctly apply its features.

* repository type:
* ``repository_type``:

Check that the repository type is set.

* nf core version:
* ``nf_core_version``:

Check if the nf-core version is set to the latest version.

Expand Down
14 changes: 6 additions & 8 deletions nf_core/subworkflows/lint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def __init__(
remote_url=None,
branch=None,
no_pull=False,
registry=None,
registry: str = "quay.io,community.wave.seqera.io/library/",
hide_progress=False,
):
super().__init__(
Expand All @@ -69,7 +69,6 @@ def __init__(
def lint(
self,
subworkflow=None,
registry="quay.io",
key=(),
all_subworkflows=False,
print_results=True,
Expand Down Expand Up @@ -152,23 +151,22 @@ def lint(

# Lint local subworkflows
if local and len(local_subworkflows) > 0:
self.lint_subworkflows(local_subworkflows, registry=registry, local=True)
self.lint_subworkflows(local_subworkflows, local=True)

# Lint nf-core subworkflows
if not local and len(remote_subworkflows) > 0:
self.lint_subworkflows(remote_subworkflows, registry=registry, local=False)
self.lint_subworkflows(remote_subworkflows, local=False)

if print_results:
self._print_results(show_passed=show_passed, sort_by=sort_by, plain_text=plain_text)
self.print_summary(plain_text=plain_text)

def lint_subworkflows(self, subworkflows, registry="quay.io", local=False):
def lint_subworkflows(self, subworkflows, local=False):
"""
Lint a list of subworkflows

Args:
subworkflows ([NFCoreComponent]): A list of subworkflow objects
registry (str): The container registry to use. Should be quay.io in most situations.
local (boolean): Whether the list consist of local or nf-core subworkflows
"""
# TODO: consider unifying modules and subworkflows lint_subworkflows() function and add it to the ComponentLint class
Expand All @@ -189,9 +187,9 @@ def lint_subworkflows(self, subworkflows, registry="quay.io", local=False):

for swf in subworkflows:
progress_bar.update(lint_progress, advance=1, test_name=swf.component_name)
self.lint_subworkflow(swf, progress_bar, registry=registry, local=local)
self.lint_subworkflow(swf, progress_bar, local=local)

def lint_subworkflow(self, swf, progress_bar, registry, local=False):
def lint_subworkflow(self, swf, progress_bar, local=False):
"""
Perform linting on one subworkflow

Expand Down
6 changes: 5 additions & 1 deletion nf_core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import rich.markup
import yaml
from packaging.version import Version
from pydantic import BaseModel, ValidationError, field_validator
from pydantic import BaseModel, ConfigDict, Field, ValidationError, field_validator
from rich.live import Live
from rich.spinner import Spinner

Expand Down Expand Up @@ -1388,6 +1388,8 @@ def __setitem__(self, item: str, value: Any) -> None:
class NFCoreYamlConfig(BaseModel):
""".nf-core.yml configuration file schema"""

model_config = ConfigDict(populate_by_name=True)

repository_type: Literal["pipeline", "modules"] | None = None
""" Type of repository """
nf_core_version: str | None = None
Expand All @@ -1402,6 +1404,8 @@ class NFCoreYamlConfig(BaseModel):
""" Disable bumping of the version for a module/subworkflow (when repository_type is modules). See https://nf-co.re/docs/nf-core-tools/modules/bump-versions for more information. """
update: dict[str, str | bool | dict[str, str | dict[str, str | bool]]] | None = None
""" Disable updating specific modules/subworkflows (when repository_type is pipeline). See https://nf-co.re/docs/nf-core-tools/modules/update for more information. """
container_registry: list[str] | None = Field(default=None, alias="container-registry")
""" Additional container registry prefixes allowed when linting container directives. """

def __getitem__(self, item: str) -> Any:
return getattr(self, item)
Expand Down
Loading
Loading