Skip to content

Commit 34bc338

Browse files
authored
Merge pull request #3406 from nf-core/dev
dev -> main for 3.1.2
2 parents 45c7879 + e481084 commit 34bc338

24 files changed

+327
-57
lines changed

.github/workflows/sync.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797

9898
run: |
9999
pushd nf-core/${{ matrix.pipeline }}
100-
defaultBranch=$(grep -B5 -A5 "nextflowVersion" nextflow.config | grep "defaultBranch" | cut -d"=" -f2)
100+
defaultBranch=$(grep -B5 -A5 "nextflowVersion" nextflow.config | grep "defaultBranch" | cut -d"=" -f2 | sed "s/'//g")
101101
if [ -z "$defaultBranch" ]; then
102102
defaultBranch="master"
103103
fi

.pre-commit-config.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.8.2
3+
rev: v0.8.6
44
hooks:
55
- id: ruff # linter
66
args: [--fix, --exit-non-zero-on-fix] # sort imports and fix
@@ -19,7 +19,7 @@ repos:
1919
alias: ec
2020

2121
- repo: https://github.com/pre-commit/mirrors-mypy
22-
rev: "v1.13.0"
22+
rev: "v1.14.1"
2323
hooks:
2424
- id: mypy
2525
additional_dependencies:

CHANGELOG.md

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
# nf-core/tools: Changelog
22

3+
## [v3.1.2 - Brass Boxfish Patch](https://github.com/nf-core/tools/releases/tag/3.1.2) - [2025-01-20]
4+
5+
### Template
6+
7+
- Bump nf-schema to `2.3.0` ([#3401](https://github.com/nf-core/tools/pull/3401))
8+
- Remove jinja formatting which was deleting line breaks ([#3405](https://github.com/nf-core/tools/pull/3405))
9+
10+
### Download
11+
12+
- Allow `nf-core pipelines download -r` to download commits ([#3374](https://github.com/nf-core/tools/pull/3374))
13+
- Fix faulty Download Test Action to ensure that setup and test run as one job and on the same runner ([#3389](https://github.com/nf-core/tools/pull/3389))
14+
15+
### Modules
16+
17+
- Fix bump-versions: only append module name if it is a dir and contains `main.nf` ([#3384](https://github.com/nf-core/tools/pull/3384))
18+
19+
### General
20+
21+
- `manifest.author` is not required anymore ([#3397](https://github.com/nf-core/tools/pull/3397))
22+
- Parameters schema validation: allow `oneOf`, `anyOf` and `allOf` with `required` ([#3386](https://github.com/nf-core/tools/pull/3386))
23+
- Run pre-comit when rendering template for pipelines sync ([#3371](https://github.com/nf-core/tools/pull/3371))
24+
- Fix sync GHA by removing quotes from parsed branch name ([#3394](https://github.com/nf-core/tools/pull/3394))
25+
326
## [v3.1.1 - Brass Boxfish Patch](https://github.com/nf-core/tools/releases/tag/3.1.1) - [2024-12-20]
427

528
### Template

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.12-slim@sha256:2b0079146a74e23bf4ae8f6a28e1b484c6292f6fb904cbb51825b4a19812fcd8
1+
FROM python:3.12-slim@sha256:10f3aaab98db50cba827d3b33a91f39dc9ec2d02ca9b85cbc5008220d07b17f3
22
33
description="Docker image containing requirements for nf-core/tools"
44

nf_core/modules/modules_utils.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,20 @@ def get_installed_modules(directory: Path, repo_type="modules") -> Tuple[List[st
6565
local_modules = sorted([x for x in local_modules if x.endswith(".nf")])
6666

6767
# Get nf-core modules
68-
if os.path.exists(nfcore_modules_dir):
69-
for m in sorted([m for m in os.listdir(nfcore_modules_dir) if not m == "lib"]):
70-
if not os.path.isdir(os.path.join(nfcore_modules_dir, m)):
68+
if nfcore_modules_dir.exists():
69+
for m in sorted([m for m in nfcore_modules_dir.iterdir() if not m == "lib"]):
70+
if not m.is_dir():
7171
raise ModuleExceptionError(
7272
f"File found in '{nfcore_modules_dir}': '{m}'! This directory should only contain module directories."
7373
)
74-
m_content = os.listdir(os.path.join(nfcore_modules_dir, m))
74+
m_content = [d.name for d in m.iterdir()]
7575
# Not a module, but contains sub-modules
7676
if "main.nf" not in m_content:
7777
for tool in m_content:
78-
nfcore_modules_names.append(os.path.join(m, tool))
78+
if (m / tool).is_dir() and "main.nf" in [d.name for d in (m / tool).iterdir()]:
79+
nfcore_modules_names.append(str(Path(m.name, tool)))
7980
else:
80-
nfcore_modules_names.append(m)
81+
nfcore_modules_names.append(m.name)
8182

8283
# Make full (relative) file paths and create NFCoreComponent objects
8384
if local_modules_dir:

nf_core/pipeline-template/.github/workflows/ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ jobs:
4646
steps:
4747
- name: Check out pipeline code
4848
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
49+
with:
50+
fetch-depth: 0
4951

5052
- name: Set up Nextflow
5153
uses: nf-core/setup-nextflow@v2

nf_core/pipeline-template/.github/workflows/download_pipeline.yml

+19-15
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,18 @@ jobs:
3535
REPOTITLE_LOWERCASE: ${{ steps.get_repo_properties.outputs.REPOTITLE_LOWERCASE }}
3636
REPO_BRANCH: ${{ steps.get_repo_properties.outputs.REPO_BRANCH }}
3737
steps:
38-
- name: Install Nextflow{% endraw %}
38+
- name: Get the repository name and current branch
39+
id: get_repo_properties
40+
run: |
41+
echo "REPO_LOWERCASE=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
42+
echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> "$GITHUB_OUTPUT"
43+
echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> "$GITHUB_OUTPUT{% endraw %}"
44+
45+
download:
46+
runs-on: ubuntu-latest
47+
needs: configure
48+
steps:
49+
- name: Install Nextflow
3950
uses: nf-core/setup-nextflow@v2
4051

4152
- name: Disk space cleanup
@@ -56,24 +67,13 @@ jobs:
5667
python -m pip install --upgrade pip
5768
pip install git+https://github.com/nf-core/tools.git@dev
5869
59-
- name: Get the repository name and current branch set as environment variable
60-
id: get_repo_properties
61-
run: |
62-
echo "REPO_LOWERCASE=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
63-
echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> "$GITHUB_OUTPUT"
64-
echo "{% raw %}REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> "$GITHUB_OUTPUT"
65-
6670
- name: Make a cache directory for the container images
6771
run: |
6872
mkdir -p ./singularity_container_images
6973
70-
download:
71-
runs-on: ubuntu-latest
72-
needs: configure
73-
steps:
7474
- name: Download the pipeline
7575
env:
76-
NXF_SINGULARITY_CACHEDIR: ./singularity_container_images
76+
NXF_SINGULARITY_CACHEDIR: ./singularity_container_images{% raw %}
7777
run: |
7878
nf-core pipelines download ${{ needs.configure.outputs.REPO_LOWERCASE }} \
7979
--revision ${{ needs.configure.outputs.REPO_BRANCH }} \
@@ -85,7 +85,10 @@ jobs:
8585
--download-configuration 'yes'
8686
8787
- name: Inspect download
88-
run: tree ./${{ needs.configure.outputs.REPOTITLE_LOWERCASE }}{% endraw %}{% if test_config %}{% raw %}
88+
run: tree ./${{ needs.configure.outputs.REPOTITLE_LOWERCASE }}{% endraw %}
89+
90+
- name: Inspect container images
91+
run: tree ./singularity_container_images | tee ./container_initial{% if test_config %}{% raw %}
8992

9093
- name: Count the downloaded number of container images
9194
id: count_initial
@@ -123,7 +126,8 @@ jobs:
123126
final_count=${{ steps.count_afterwards.outputs.IMAGE_COUNT_AFTER }}
124127
difference=$((final_count - initial_count))
125128
echo "$difference additional container images were \n downloaded at runtime . The pipeline has no support for offline runs!"
126-
tree ./singularity_container_images
129+
tree ./singularity_container_images > ./container_afterwards
130+
diff ./container_initial ./container_afterwards
127131
exit 1
128132
else
129133
echo "The pipeline can be downloaded successfully!"

nf_core/pipeline-template/CITATIONS.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
1919
{%- endif %}
2020

21-
{%- if multiqc %}- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/)
21+
{% if multiqc %}- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/)
2222

2323
> Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924.
2424

nf_core/pipeline-template/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</picture>
88
</h1>
99

10-
{%- else -%}
10+
{% else -%}
1111

1212
# {{ name }}
1313

@@ -54,7 +54,7 @@
5454
## Usage
5555

5656
> [!NOTE]
57-
> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. {%- if test_config %}Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data.{% endif %}
57+
> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. {% if test_config %}Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data.{% endif %}
5858
5959
<!-- TODO nf-core: Describe the minimum required steps to execute the pipeline, e.g. how to prepare samplesheets.
6060
Explain what rows and columns represent. For instance (please edit as appropriate):
@@ -120,7 +120,7 @@ For further information or help, don't hesitate to get in touch on the [Slack `#
120120
<!-- TODO nf-core: Add citation for pipeline after first release. Uncomment lines below and update Zenodo doi and badge at the top of this file. -->
121121
<!-- If you use {{ name }} for your analysis, please cite it using the following doi: [10.5281/zenodo.XXXXXX](https://doi.org/10.5281/zenodo.XXXXXX) -->
122122

123-
{%- if citations %}<!-- TODO nf-core: Add bibliography of tools and data used in your pipeline -->
123+
{% if citations %}<!-- TODO nf-core: Add bibliography of tools and data used in your pipeline -->
124124

125125
An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.
126126
{%- endif %}

nf_core/pipeline-template/conf/test.config

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ params {
2727
// TODO nf-core: Give any required params for the test so that command line flags are not needed
2828
input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv'
2929

30-
{% if igenomes -%}
30+
{%- if igenomes -%}
31+
3132
// Genome references
3233
genome = 'R64-1-1'
3334
{%- endif %}

nf_core/pipeline-template/nextflow.config

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ manifest {
295295
{% if nf_schema -%}
296296
// Nextflow plugins
297297
plugins {
298-
id 'nf-schema@2.1.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet
298+
id 'nf-schema@2.3.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet
299299
}
300300

301301
validation {

nf_core/pipelines/create/create.py

+4
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,10 @@ def render_template(self) -> None:
386386
yaml.dump(config_yml.model_dump(exclude_none=True), fh, Dumper=custom_yaml_dumper())
387387
log.debug(f"Dumping pipeline template yml to pipeline config file '{config_fn.name}'")
388388

389+
# Run prettier on files for pipelines sync
390+
log.debug("Running prettier on pipeline files")
391+
run_prettier_on_file([str(f) for f in self.outdir.glob("**/*")])
392+
389393
def fix_linting(self):
390394
"""
391395
Updates the .nf-core.yml with linting configurations

nf_core/pipelines/download.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -374,30 +374,37 @@ def prompt_revision(self) -> None:
374374
raise AssertionError(f"No revisions of {self.pipeline} available for download.")
375375

376376
def get_revision_hash(self):
377-
"""Find specified revision / branch hash"""
377+
"""Find specified revision / branch / commit hash"""
378378

379379
for revision in self.revision: # revision is a list of strings, but may be of length 1
380380
# Branch
381381
if revision in self.wf_branches.keys():
382382
self.wf_sha = {**self.wf_sha, revision: self.wf_branches[revision]}
383383

384-
# Revision
385384
else:
385+
# Revision
386386
for r in self.wf_revisions:
387387
if r["tag_name"] == revision:
388388
self.wf_sha = {**self.wf_sha, revision: r["tag_sha"]}
389389
break
390390

391-
# Can't find the revisions or branch - throw an error
392391
else:
392+
# Commit - full or short hash
393+
if commit_id := nf_core.utils.get_repo_commit(self.pipeline, revision):
394+
self.wf_sha = {**self.wf_sha, revision: commit_id}
395+
continue
396+
397+
# Can't find the revisions or branch - throw an error
393398
log.info(
394399
"Available {} revisions: '{}'".format(
395400
self.pipeline,
396401
"', '".join([r["tag_name"] for r in self.wf_revisions]),
397402
)
398403
)
399404
log.info("Available {} branches: '{}'".format(self.pipeline, "', '".join(self.wf_branches.keys())))
400-
raise AssertionError(f"Not able to find revision / branch '{revision}' for {self.pipeline}")
405+
raise AssertionError(
406+
f"Not able to find revision / branch / commit '{revision}' for {self.pipeline}"
407+
)
401408

402409
# Set the outdir
403410
if not self.outdir:
@@ -1536,7 +1543,7 @@ def singularity_pull_image(
15361543

15371544
progress.remove_task(task)
15381545

1539-
def compress_download(self) -> None:
1546+
def compress_download(self):
15401547
"""Take the downloaded files and make a compressed .tar.gz archive."""
15411548
log.debug(f"Creating archive: {self.output_filename}")
15421549

nf_core/pipelines/lint/files_unchanged.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import filecmp
22
import logging
33
import os
4+
import re
45
import shutil
56
import tempfile
67
from pathlib import Path
@@ -68,7 +69,10 @@ def files_unchanged(self) -> Dict[str, Union[List[str], bool]]:
6869
could_fix: bool = False
6970

7071
# Check that we have the minimum required config
71-
required_pipeline_config = {"manifest.name", "manifest.description", "manifest.author"}
72+
required_pipeline_config = {
73+
"manifest.name",
74+
"manifest.description",
75+
} # TODO: add "manifest.contributors" when minimum nextflow version is >=24.10.0
7276
missing_pipeline_config = required_pipeline_config.difference(self.nf_config)
7377
if missing_pipeline_config:
7478
return {"ignored": [f"Required pipeline config not found - {missing_pipeline_config}"]}
@@ -117,10 +121,15 @@ def files_unchanged(self) -> Dict[str, Union[List[str], bool]]:
117121
tmp_dir.mkdir(parents=True)
118122

119123
# Create a template.yaml file for the pipeline creation
124+
if "manifest.author" in self.nf_config:
125+
names = self.nf_config["manifest.author"].strip("\"'")
126+
if "manifest.contributors" in self.nf_config:
127+
contributors = self.nf_config["manifest.contributors"]
128+
names = ", ".join(re.findall(r"name:'([^']+)'", contributors))
120129
template_yaml = {
121130
"name": short_name,
122131
"description": self.nf_config["manifest.description"].strip("\"'"),
123-
"author": self.nf_config["manifest.author"].strip("\"'"),
132+
"author": names,
124133
"org": prefix,
125134
}
126135

nf_core/pipelines/lint_utils.py

+29-15
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ def print_fixes(lint_obj):
7070
)
7171

7272

73+
def check_git_repo() -> bool:
74+
"""Check if the current directory is a git repository."""
75+
try:
76+
subprocess.check_output(["git", "rev-parse", "--is-inside-work-tree"])
77+
return True
78+
except subprocess.CalledProcessError:
79+
return False
80+
81+
7382
def run_prettier_on_file(file: Union[Path, str, List[str]]) -> None:
7483
"""Run the pre-commit hook prettier on a file.
7584
@@ -80,28 +89,33 @@ def run_prettier_on_file(file: Union[Path, str, List[str]]) -> None:
8089
If Prettier is not installed, a warning is logged.
8190
"""
8291

92+
is_git = check_git_repo()
93+
8394
nf_core_pre_commit_config = Path(nf_core.__file__).parent / ".pre-commit-prettier-config.yaml"
8495
args = ["pre-commit", "run", "--config", str(nf_core_pre_commit_config), "prettier"]
8596
if isinstance(file, List):
8697
args.extend(["--files", *file])
8798
else:
8899
args.extend(["--files", str(file)])
89100

90-
try:
91-
subprocess.run(args, capture_output=True, check=True)
92-
log.debug(f"${subprocess.STDOUT}")
93-
except subprocess.CalledProcessError as e:
94-
if ": SyntaxError: " in e.stdout.decode():
95-
log.critical(f"Can't format {file} because it has a syntax error.\n{e.stdout.decode()}")
96-
elif "files were modified by this hook" in e.stdout.decode():
97-
all_lines = [line for line in e.stdout.decode().split("\n")]
98-
files = "\n".join(all_lines[3:])
99-
log.debug(f"The following files were modified by prettier:\n {files}")
100-
else:
101-
log.warning(
102-
"There was an error running the prettier pre-commit hook.\n"
103-
f"STDOUT: {e.stdout.decode()}\nSTDERR: {e.stderr.decode()}"
104-
)
101+
if is_git:
102+
try:
103+
proc = subprocess.run(args, capture_output=True, check=True)
104+
log.debug(f"{proc.stdout.decode()}")
105+
except subprocess.CalledProcessError as e:
106+
if ": SyntaxError: " in e.stdout.decode():
107+
log.critical(f"Can't format {file} because it has a syntax error.\n{e.stdout.decode()}")
108+
elif "files were modified by this hook" in e.stdout.decode():
109+
all_lines = [line for line in e.stdout.decode().split("\n")]
110+
files = "\n".join(all_lines[3:])
111+
log.debug(f"The following files were modified by prettier:\n {files}")
112+
else:
113+
log.warning(
114+
"There was an error running the prettier pre-commit hook.\n"
115+
f"STDOUT: {e.stdout.decode()}\nSTDERR: {e.stderr.decode()}"
116+
)
117+
else:
118+
log.debug("Not in a git repository, skipping pre-commit hook.")
105119

106120

107121
def dump_json_with_prettier(file_name, file_content):

nf_core/pipelines/rocrate.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def add_main_authors(self, wf_file: rocrate.model.entity.Entity) -> None:
287287
try:
288288
git_contributors: Set[str] = set()
289289
if self.pipeline_obj.repo is None:
290-
log.info("No git repository found. No git contributors will be added as authors.")
290+
log.debug("No git repository found. No git contributors will be added as authors.")
291291
return
292292
commits_touching_path = list(self.pipeline_obj.repo.iter_commits(paths="main.nf"))
293293

0 commit comments

Comments
 (0)