Skip to content

Commit 7284262

Browse files
authored
Merge pull request #3240 from mashehu/add-rocreate
2 parents ba332b6 + 43287c6 commit 7284262

File tree

17 files changed

+956
-283
lines changed

17 files changed

+956
-283
lines changed

.github/actions/create-lint-wf/action.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ runs:
6565
run: find nf-core-testpipeline -type f -exec sed -i 's/zenodo.XXXXXX/zenodo.123456/g' {} \;
6666
working-directory: create-lint-wf
6767

68+
# Add empty ro-crate file
69+
- name: add empty ro-crate file
70+
shell: bash
71+
run: touch nf-core-testpipeline/ro-crate-metadata.json
72+
working-directory: create-lint-wf
73+
6874
# Run nf-core pipelines linting
6975
- name: nf-core pipelines lint
7076
shell: bash

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ jobs:
147147
run: find my-prefix-testpipeline -type f -exec sed -i 's/zenodo.XXXXXX/zenodo.123456/g' {} \;
148148
working-directory: create-test-lint-wf
149149

150+
# Add empty ro-crate file
151+
- name: add empty ro-crate file
152+
run: touch my-prefix-testpipeline/ro-crate-metadata.json
153+
working-directory: create-test-lint-wf
154+
150155
# Run nf-core linting
151156
- name: nf-core pipelines lint
152157
run: nf-core --log-file log.txt --hide-progress pipelines lint --dir my-prefix-testpipeline --fail-warned

.github/workflows/pytest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ jobs:
132132
133133
- name: Test with pytest
134134
run: |
135-
python3 -m pytest tests/${{matrix.test}} --color=yes --cov --durations=0 && exit_code=0|| exit_code=$?
135+
python3 -m pytest tests/${{matrix.test}} --color=yes --cov --cov-config=.coveragerc --durations=0 && exit_code=0|| exit_code=$?
136136
# don't fail if no tests were collected, e.g. for test_licence.py
137137
if [ "${exit_code}" -eq 5 ]; then
138138
echo "No tests were collected"

nf_core/__main__.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
pipelines_launch,
3737
pipelines_lint,
3838
pipelines_list,
39+
pipelines_rocrate,
3940
pipelines_schema_build,
4041
pipelines_schema_docs,
4142
pipelines_schema_lint,
@@ -86,7 +87,7 @@
8687
},
8788
{
8889
"name": "For developers",
89-
"commands": ["create", "lint", "bump-version", "sync", "schema", "create-logo"],
90+
"commands": ["create", "lint", "bump-version", "sync", "schema", "rocrate", "create-logo"],
9091
},
9192
],
9293
"nf-core modules": [
@@ -570,6 +571,44 @@ def command_pipelines_list(ctx, keywords, sort, json, show_archived):
570571
pipelines_list(ctx, keywords, sort, json, show_archived)
571572

572573

574+
# nf-core pipelines rocrate
575+
@pipelines.command("rocrate")
576+
@click.argument(
577+
"pipeline_dir",
578+
type=click.Path(exists=True),
579+
default=Path.cwd(),
580+
required=True,
581+
metavar="<pipeline directory>",
582+
)
583+
@click.option(
584+
"-j",
585+
"--json_path",
586+
default=Path.cwd(),
587+
type=str,
588+
help="Path to save RO Crate metadata json file to",
589+
)
590+
@click.option("-z", "--zip_path", type=str, help="Path to save RO Crate zip file to")
591+
@click.option(
592+
"-pv",
593+
"--pipeline_version",
594+
type=str,
595+
help="Version of pipeline to use for RO Crate",
596+
default="",
597+
)
598+
@click.pass_context
599+
def rocrate(
600+
ctx,
601+
pipeline_dir: str,
602+
json_path: str,
603+
zip_path: str,
604+
pipeline_version: str,
605+
):
606+
"""
607+
Make an Research Object Crate
608+
"""
609+
pipelines_rocrate(ctx, pipeline_dir, json_path, zip_path, pipeline_version)
610+
611+
573612
# nf-core pipelines sync
574613
@pipelines.command("sync")
575614
@click.pass_context
@@ -1758,7 +1797,7 @@ def command_schema_validate(pipeline, params):
17581797
@click.option(
17591798
"--url",
17601799
type=str,
1761-
default="https://nf-co.re/pipeline_schema_builder",
1800+
default="https://oldsite.nf-co.re/pipeline_schema_builder",
17621801
help="Customise the builder URL (for development work)",
17631802
)
17641803
def command_schema_build(directory, no_prompts, web_only, url):

nf_core/commands_pipelines.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import sys
44
from pathlib import Path
5+
from typing import Optional, Union
56

67
import rich
78

@@ -277,6 +278,33 @@ def pipelines_list(ctx, keywords, sort, json, show_archived):
277278
stdout.print(list_workflows(keywords, sort, json, show_archived))
278279

279280

281+
# nf-core pipelines rocrate
282+
def pipelines_rocrate(
283+
ctx,
284+
pipeline_dir: Union[str, Path],
285+
json_path: Optional[Union[str, Path]],
286+
zip_path: Optional[Union[str, Path]],
287+
pipeline_version: str,
288+
) -> None:
289+
from nf_core.pipelines.rocrate import ROCrate
290+
291+
if json_path is None and zip_path is None:
292+
log.error("Either `--json_path` or `--zip_path` must be specified.")
293+
sys.exit(1)
294+
else:
295+
pipeline_dir = Path(pipeline_dir)
296+
if json_path is not None:
297+
json_path = Path(json_path)
298+
if zip_path is not None:
299+
zip_path = Path(zip_path)
300+
try:
301+
rocrate_obj = ROCrate(pipeline_dir, pipeline_version)
302+
rocrate_obj.create_rocrate(json_path=json_path, zip_path=zip_path)
303+
except (UserWarning, LookupError, FileNotFoundError) as e:
304+
log.error(e)
305+
sys.exit(1)
306+
307+
280308
# nf-core pipelines sync
281309
def pipelines_sync(ctx, directory, from_branch, pull_request, github_repository, username, template_yaml, force_pr):
282310
"""

nf_core/components/info.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ def get_local_yaml(self) -> Optional[Dict]:
211211
return yaml.safe_load(fh)
212212
log.debug(f"{self.component_type[:-1].title()} '{self.component}' meta.yml not found locally")
213213

214-
return None
214+
return {}
215215

216-
def get_remote_yaml(self) -> Optional[dict]:
216+
def get_remote_yaml(self) -> Optional[Dict]:
217217
"""Attempt to get the meta.yml file from a remote repo.
218218
219219
Returns:

nf_core/modules/modules_json.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,8 +1129,10 @@ def dump(self, run_prettier: bool = False) -> None:
11291129
"""
11301130
Sort the modules.json, and write it to file
11311131
"""
1132+
# Sort the modules.json
1133+
if self.modules_json is None:
1134+
self.load()
11321135
if self.modules_json is not None:
1133-
# Sort the modules.json
11341136
self.modules_json["repos"] = nf_core.utils.sort_dictionary(self.modules_json["repos"])
11351137
if run_prettier:
11361138
dump_json_with_prettier(self.modules_json_path, self.modules_json)

nf_core/pipelines/create/create.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from nf_core.pipelines.create.utils import CreateConfig, features_yml_path, load_features_yaml
2222
from nf_core.pipelines.create_logo import create_logo
2323
from nf_core.pipelines.lint_utils import run_prettier_on_file
24+
from nf_core.pipelines.rocrate import ROCrate
2425
from nf_core.utils import LintConfigType, NFCoreTemplateConfig
2526

2627
log = logging.getLogger(__name__)
@@ -356,6 +357,11 @@ def render_template(self) -> None:
356357
# Make a logo and save it, if it is a nf-core pipeline
357358
self.make_pipeline_logo()
358359

360+
if self.config.skip_features is None or "ro-crate" not in self.config.skip_features:
361+
# Create the RO-Crate metadata file
362+
rocrate_obj = ROCrate(self.outdir)
363+
rocrate_obj.create_rocrate(json_path=self.outdir / "ro-crate-metadata.json")
364+
359365
# Update the .nf-core.yml with linting configurations
360366
self.fix_linting()
361367

nf_core/pipelines/create/template_features.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,19 @@ seqera_platform:
432432
You can extend this file adding any other desired configuration.
433433
nfcore_pipelines: False
434434
custom_pipelines: True
435+
rocrate:
436+
skippable_paths:
437+
- "ro-crate-metadata.json"
438+
short_description: "Add RO-Crate metadata"
439+
description: "Add a RO-Crate metadata file to describe the pipeline"
440+
help_text: |
441+
RO-Crate is a metadata specification to describe research data and software.
442+
This will add a `ro-crate-metadata.json` file to describe the pipeline.
443+
nfcore_pipelines: False
444+
custom_pipelines: True
445+
linting:
446+
files_warn:
447+
- "ro-crate-metadata.json"
435448
vscode:
436449
skippable_paths:
437450
- ".vscode"

nf_core/pipelines/lint/files_exist.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def files_exist(self) -> Dict[str, List[str]]:
6666
conf/igenomes.config
6767
.github/workflows/awstest.yml
6868
.github/workflows/awsfulltest.yml
69+
ro-crate-metadata.json
6970
7071
Files that *must not* be present, due to being renamed or removed in the template:
7172
@@ -171,6 +172,7 @@ def files_exist(self) -> Dict[str, List[str]]:
171172
[Path(".github", "workflows", "awstest.yml")],
172173
[Path(".github", "workflows", "awsfulltest.yml")],
173174
[Path("modules.json")],
175+
[Path("ro-crate-metadata.json")],
174176
]
175177

176178
# List of strings. Fails / warns if any of the strings exist.
@@ -198,6 +200,12 @@ def files_exist(self) -> Dict[str, List[str]]:
198200
]
199201
files_warn_ifexists = [Path(".travis.yml")]
200202

203+
files_hint = [
204+
[
205+
["ro-crate-metadata.json"],
206+
". Run `nf-core rocrate` to generate this file. Read more about RO-Crates in the [nf-core/tools docs](https://nf-co.re/tools#create-a-ro-crate-metadata-file).",
207+
],
208+
]
201209
# Remove files that should be ignored according to the linting config
202210
ignore_files = self.lint_config.get("files_exist", []) if self.lint_config is not None else []
203211

@@ -225,7 +233,11 @@ def pf(file_path: Union[str, Path]) -> Path:
225233
if any([pf(f).is_file() for f in files]):
226234
passed.append(f"File found: {self._wrap_quotes(files)}")
227235
else:
228-
warned.append(f"File not found: {self._wrap_quotes(files)}")
236+
hint = ""
237+
for file_hint in files_hint:
238+
if file_hint[0] == files:
239+
hint = str(file_hint[1])
240+
warned.append(f"File not found: {self._wrap_quotes(files)}{hint}")
229241

230242
# Files that cause an error if they exist
231243
for file in files_fail_ifexists:

0 commit comments

Comments
 (0)