Skip to content

Commit c9716ff

Browse files
Merge branch 'dev' into modules-install-no-tty
2 parents f220287 + ab2f4fc commit c9716ff

33 files changed

Lines changed: 844 additions & 56 deletions

.github/workflows/branch.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
# If the above check failed, post a comment on the PR explaining the failure
1919
- name: Post PR comment
2020
if: failure()
21-
uses: mshick/add-pr-comment@ffd016c7e151d97d69d21a843022fd4cd5b96fe5 # v3
21+
uses: mshick/add-pr-comment@64b8e914979889d746c99dea15a76e77ef64580a # v3
2222
with:
2323
message: |
2424
## This PR is against the `main` branch :x:

.github/workflows/create-test-lint-wf-template.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
version: latest-everything
7878

7979
- name: Install nf-test
80-
uses: nf-core/setup-nf-test@v1
80+
uses: nf-core/setup-nf-test@ce65500579e8587607aab289ecb3a9c343c32e79 # v2
8181
with:
8282
version: "0.9.4"
8383
install-pdiff: true

.github/workflows/create-test-wf.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
version: ${{ matrix.NXF_VER }}
6464

6565
- name: Install nf-test
66-
uses: nf-core/setup-nf-test@v1
66+
uses: nf-core/setup-nf-test@ce65500579e8587607aab289ecb3a9c343c32e79 # v2
6767
with:
6868
version: "0.9.4"
6969
install-pdiff: true

.github/workflows/push_dockerhub.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
4444

4545
- name: Log in to Docker Hub
46-
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
46+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
4747
with:
4848
username: ${{ secrets.DOCKERHUB_USERNAME }}
4949
password: ${{ secrets.DOCKERHUB_PASS }}

.github/workflows/pytest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595
uses: nf-core/setup-nextflow@v2
9696

9797
- name: Install nf-test
98-
uses: nf-core/setup-nf-test@v1
98+
uses: nf-core/setup-nf-test@ce65500579e8587607aab289ecb3a9c343c32e79 # v2
9999

100100
- name: move coveragerc file up
101101
run: |

.github/workflows/update-template-snapshots.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ jobs:
7474
version: latest-everything
7575

7676
- name: Install nf-test
77-
uses: nf-core/setup-nf-test@v1
77+
uses: nf-core/setup-nf-test@ce65500579e8587607aab289ecb3a9c343c32e79 # v2
7878
with:
7979
version: "0.9.4"
8080
install-pdiff: true

.pre-commit-config.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ repos:
4444
- types-setuptools
4545
- pydantic
4646
- repo: https://github.com/astral-sh/uv-pre-commit
47-
rev: 0.10.7
47+
rev: 0.11.3
4848
hooks:
4949
- id: uv-lock
50+
- repo: local
51+
hooks:
52+
- id: lint-test-docstrings
53+
name: Check lint test names are documented in docstrings
54+
language: system
55+
entry: python3 docs/api/check_lint_docstrings.py
56+
files: ^nf_core/(modules|subworkflows)/lint/.*\.py$

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@
4242
- nf-core bot: collect all snapshots before commiting ([#4082](https://github.com/nf-core/tools/pull/4082))
4343
- Update GitHub Actions to v4 (major) ([#4081](https://github.com/nf-core/tools/pull/4081))
4444
- fix nf-core bot snapshot action ([#4083](https://github.com/nf-core/tools/pull/4083))
45+
- Fix GHA notification for AWS full tests job ([#4092](https://github.com/nf-core/tools/pull/4092))
4546
- sync: don't overwrite the defaultBranch if already set in nextflow.config ([#3939](https://github.com/nf-core/tools/pull/3939))
4647

4748
### Linting
4849

4950
- fix failing pytest for lint after samtools topic conversion ([#4026](https://github.com/nf-core/tools/pull/4026))
5051
- fix incorrect unqoting of `val()` version numbers ([#4042](https://github.com/nf-core/tools/pull/4042))
52+
- capture correct error for invalid .nf-core.yml ([#4080](https://github.com/nf-core/tools/pull/4080))
5153
- allow versions.yml in the version topics ([#4094](https://github.com/nf-core/tools/pull/4094))
5254
- Ensure release linting happens on branch named main ([#4121](https://github.com/nf-core/tools/pull/4121))
5355
- Add linting for meta and ext keys ([#4127](https://github.com/nf-core/tools/pull/4127))
5456
- Add strict syntax linting to template with pre-commit ([#4128](https://github.com/nf-core/tools/pull/4128))
57+
- Lint meta variable names ([#4129](https://github.com/nf-core/tools/pull/4129))
5558
- Lint against the correct repo ([#4140](https://github.com/nf-core/tools/pull/4140))
5659
- Fix false positive matches to words like text in ext key linting ([#4142](https://github.com/nf-core/tools/pull/4142))
5760
- Fix changelog bot failing after linting step ([#4155](https://github.com/nf-core/tools/pull/4155))

docs/api/check_lint_docstrings.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Pre-commit hook: verify that every lint test name used in a result tuple is
4+
mentioned in the docstring of its enclosing function.
5+
6+
Applies to nf-core component lint files where results are accumulated as:
7+
8+
component.passed.append(("category", "test_name", "message", path))
9+
component.warned.append(("category", "test_name", "message", path))
10+
component.failed.append(("category", "test_name", "message", path))
11+
12+
Usage (called by pre-commit with the changed files as arguments):
13+
14+
python scripts/check_lint_docstrings.py nf_core/modules/lint/module_tests.py ...
15+
"""
16+
17+
import ast
18+
import sys
19+
from pathlib import Path
20+
21+
22+
def collect_test_names(func_node: ast.FunctionDef | ast.AsyncFunctionDef) -> dict[str, list[int]]:
23+
"""Return {test_name: [line_numbers]} for all result-tuple appends in the function."""
24+
results: dict[str, list[int]] = {}
25+
# Walk only the direct body — do not descend into nested function definitions.
26+
nodes_to_visit: list[ast.AST] = list(func_node.body)
27+
while nodes_to_visit:
28+
node = nodes_to_visit.pop()
29+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
30+
continue # skip nested scopes
31+
if (
32+
isinstance(node, ast.Call)
33+
and isinstance(node.func, ast.Attribute)
34+
and node.func.attr == "append"
35+
and isinstance(node.func.value, ast.Attribute)
36+
and node.func.value.attr in ("passed", "warned", "failed")
37+
and len(node.args) == 1
38+
and isinstance(node.args[0], ast.Tuple)
39+
and len(node.args[0].elts) >= 2
40+
and isinstance(node.args[0].elts[1], ast.Constant)
41+
and isinstance(node.args[0].elts[1].value, str)
42+
):
43+
test_name = node.args[0].elts[1].value
44+
results.setdefault(test_name, []).append(node.lineno)
45+
nodes_to_visit.extend(ast.iter_child_nodes(node))
46+
return results
47+
48+
49+
def check_file(path: Path) -> list[str]:
50+
errors = []
51+
try:
52+
source = path.read_text()
53+
except OSError as e:
54+
return [f"{path}: could not read file: {e}"]
55+
56+
try:
57+
tree = ast.parse(source, filename=str(path))
58+
except SyntaxError as e:
59+
return [f"{path}: SyntaxError: {e}"]
60+
61+
module_stem = path.stem # e.g. "module_tests" from "module_tests.py"
62+
63+
for node in ast.walk(tree):
64+
if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
65+
continue
66+
if node.name != module_stem:
67+
continue
68+
docstring = ast.get_docstring(node) or ""
69+
test_names = collect_test_names(node)
70+
for test_name, lines in sorted(test_names.items()):
71+
if test_name not in docstring:
72+
errors.append(
73+
f"{path}:{lines[0]}: '{test_name}' used in {node.name}() but not documented in its docstring"
74+
)
75+
break # only one function per file can match the stem
76+
return errors
77+
78+
79+
def main() -> int:
80+
files = [Path(f) for f in sys.argv[1:] if f.endswith(".py")]
81+
all_errors: list[str] = []
82+
for path in files:
83+
all_errors.extend(check_file(path))
84+
for error in all_errors:
85+
print(error, file=sys.stderr)
86+
return 1 if all_errors else 0
87+
88+
89+
if __name__ == "__main__":
90+
sys.exit(main())

nf_core/commands_modules.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def modules_update(
113113
exit_status = module_install.update(tool)
114114
if not exit_status and install_all:
115115
sys.exit(1)
116-
except (UserWarning, LookupError) as e:
116+
except (UserWarning, LookupError, AssertionError) as e:
117117
log.error(e)
118118
sys.exit(1)
119119

0 commit comments

Comments
 (0)