diff --git a/.editorconfig b/.editorconfig
index 449f446a3b..5aa8697d30 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -20,3 +20,11 @@ indent_style = unset
[**/Makefile]
indent_style = unset
+
+[tests/__snapshots__/*]
+charset = unset
+end_of_line = unset
+insert_final_newline = unset
+trim_trailing_whitespace = unset
+indent_style = unset
+indent_size = unset
diff --git a/.github/actions/create-lint-wf/action.yml b/.github/actions/create-lint-wf/action.yml
index 0bc5e432e7..9052c90ddc 100644
--- a/.github/actions/create-lint-wf/action.yml
+++ b/.github/actions/create-lint-wf/action.yml
@@ -27,7 +27,7 @@ runs:
run: |
mkdir -p create-lint-wf && cd create-lint-wf
export NXF_WORK=$(pwd)
- nf-core --log-file log.txt create -n testpipeline -d "This pipeline is for testing" -a "Testing McTestface" --plain
+ nf-core --log-file log.txt pipelines create -n testpipeline -d "This pipeline is for testing" -a "Testing McTestface"
# Try syncing it before we change anything
- name: nf-core sync
diff --git a/.github/workflows/create-test-lint-wf-template.yml b/.github/workflows/create-test-lint-wf-template.yml
index 0de7287a57..4ae2714534 100644
--- a/.github/workflows/create-test-lint-wf-template.yml
+++ b/.github/workflows/create-test-lint-wf-template.yml
@@ -84,29 +84,29 @@ jobs:
run: |
mkdir create-test-lint-wf
export NXF_WORK=$(pwd)
- printf "prefix: my-prefix\nskip: ['ci', 'github_badges', 'igenomes', 'nf_core_configs']" > create-test-lint-wf/template_skip_all.yml
+ printf "org: my-prefix\nskip: ['ci', 'github_badges', 'igenomes', 'nf_core_configs']" > create-test-lint-wf/template_skip_all.yml
- name: Create template skip github_badges
run: |
- printf "prefix: my-prefix\nskip: github_badges" > create-test-lint-wf/template_skip_github_badges.yml
+ printf "org: my-prefix\nskip: github_badges" > create-test-lint-wf/template_skip_github_badges.yml
- name: Create template skip igenomes
run: |
- printf "prefix: my-prefix\nskip: igenomes" > create-test-lint-wf/template_skip_igenomes.yml
+ printf "org: my-prefix\nskip: igenomes" > create-test-lint-wf/template_skip_igenomes.yml
- name: Create template skip ci
run: |
- printf "prefix: my-prefix\nskip: ci" > create-test-lint-wf/template_skip_ci.yml
+ printf "org: my-prefix\nskip: ci" > create-test-lint-wf/template_skip_ci.yml
- name: Create template skip nf_core_configs
run: |
- printf "prefix: my-prefix\nskip: nf_core_configs" > create-test-lint-wf/template_skip_nf_core_configs.yml
+ printf "org: my-prefix\nskip: nf_core_configs" > create-test-lint-wf/template_skip_nf_core_configs.yml
# Create a pipeline from the template
- name: create a pipeline from the template ${{ matrix.TEMPLATE }}
run: |
cd create-test-lint-wf
- nf-core --log-file log.txt create -n testpipeline -d "This pipeline is for testing" -a "Testing McTestface" --template-yaml ${{ matrix.TEMPLATE }}
+ nf-core --log-file log.txt pipelines create -n testpipeline -d "This pipeline is for testing" -a "Testing McTestface" --template-yaml ${{ matrix.TEMPLATE }}
- name: run the pipeline
run: |
diff --git a/.github/workflows/create-test-wf.yml b/.github/workflows/create-test-wf.yml
index 87cdf2e7bb..a95a477459 100644
--- a/.github/workflows/create-test-wf.yml
+++ b/.github/workflows/create-test-wf.yml
@@ -70,7 +70,11 @@ jobs:
run: |
mkdir create-test-wf && cd create-test-wf
export NXF_WORK=$(pwd)
- nf-core --log-file log.txt create -n testpipeline -d "This pipeline is for testing" -a "Testing McTestface" --plain
+ nf-core --log-file log.txt pipelines create -n testpipeline -d "This pipeline is for testing" -a "Testing McTestface"
+ # echo current directory
+ pwd
+ # echo content of current directory
+ ls -la
nextflow run nf-core-testpipeline -profile test,self_hosted_runner --outdir ./results
- name: Upload log file artifact
diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml
index 70b9cfd0a8..4e873385e8 100644
--- a/.github/workflows/pytest.yml
+++ b/.github/workflows/pytest.yml
@@ -142,6 +142,13 @@ jobs:
exit 1
fi
+ - name: Store snapshot report
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
+ if: always()
+ with:
+ name: Snapshot Report ${{ matrix.test }}
+ path: ./snapshot_report.html
+
- name: Upload coverage
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
with:
diff --git a/.gitignore b/.gitignore
index 271fdb14e3..a3721da86e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -115,3 +115,6 @@ ENV/
pip-wheel-metadata
.vscode
.*.sw?
+
+# Textual
+snapshot_report.html
diff --git a/MANIFEST.in b/MANIFEST.in
index 5ec177b783..68f115d97f 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -9,3 +9,4 @@ include nf_core/assets/logo/nf-core-repo-logo-base-lightbg.png
include nf_core/assets/logo/nf-core-repo-logo-base-darkbg.png
include nf_core/assets/logo/placeholder_logo.svg
include nf_core/assets/logo/MavenPro-Bold.ttf
+include nf_core/pipelines/create/create.tcss
diff --git a/nf_core/__main__.py b/nf_core/__main__.py
index 147b0586b2..67af238b5c 100644
--- a/nf_core/__main__.py
+++ b/nf_core/__main__.py
@@ -17,7 +17,7 @@
from nf_core.download import DownloadError
from nf_core.modules.modules_repo import NF_CORE_MODULES_REMOTE
from nf_core.params_file import ParamsFileBuilder
-from nf_core.utils import check_if_outdated, rich_force_colors, setup_nfcore_dir
+from nf_core.utils import check_if_outdated, nfcore_logo, rich_force_colors, setup_nfcore_dir
# Set up logging as the root logger
# Submodules should all traverse back to this
@@ -45,7 +45,7 @@
{
"name": "Commands for developers",
"commands": [
- "create",
+ "pipelines",
"lint",
"modules",
"subworkflows",
@@ -56,6 +56,12 @@
],
},
],
+ "nf-core pipelines": [
+ {
+ "name": "Pipeline commands",
+ "commands": ["create"],
+ },
+ ],
"nf-core modules": [
{
"name": "For pipelines",
@@ -115,25 +121,11 @@ def run_nf_core():
# print nf-core header if environment variable is not set
if os.environ.get("_NF_CORE_COMPLETE") is None:
# Print nf-core header
- stderr.print(f"\n[green]{' ' * 42},--.[grey39]/[green],-.", highlight=False)
- stderr.print(
- "[blue] ___ __ __ __ ___ [green]/,-._.--~\\",
- highlight=False,
- )
- stderr.print(
- r"[blue] |\ | |__ __ / ` / \ |__) |__ [yellow] } {",
- highlight=False,
- )
- stderr.print(
- r"[blue] | \| | \__, \__/ | \ |___ [green]\`-._,-`-,",
- highlight=False,
- )
- stderr.print(
- "[green] `._,._,'\n",
- highlight=False,
- )
+ stderr.print("\n")
+ for line in nfcore_logo:
+ stderr.print(line, highlight=False)
stderr.print(
- f"[grey39] nf-core/tools version {__version__} - [link=https://nf-co.re]https://nf-co.re[/]",
+ f"\n[grey39] nf-core/tools version {__version__} - [link=https://nf-co.re]https://nf-co.re[/]",
highlight=False,
)
try:
@@ -494,53 +486,6 @@ def licences(pipeline, json):
sys.exit(1)
-# nf-core create
-@nf_core_cli.command()
-@click.option(
- "-n",
- "--name",
- type=str,
- help="The name of your new pipeline",
-)
-@click.option("-d", "--description", type=str, help="A short description of your pipeline")
-@click.option("-a", "--author", type=str, help="Name of the main author(s)")
-@click.option("--version", type=str, default="1.0dev", help="The initial version number to use")
-@click.option(
- "-f",
- "--force",
- is_flag=True,
- default=False,
- help="Overwrite output directory if it already exists",
-)
-@click.option("-o", "--outdir", help="Output directory for new pipeline (default: pipeline name)")
-@click.option("-t", "--template-yaml", help="Pass a YAML file to customize the template")
-@click.option("--plain", is_flag=True, help="Use the standard nf-core template")
-def create(name, description, author, version, force, outdir, template_yaml, plain):
- """
- Create a new pipeline using the nf-core template.
-
- Uses the nf-core template to make a skeleton Nextflow pipeline with all required
- files, boilerplate code and best-practices.
- """
- from nf_core.create import PipelineCreate
-
- try:
- create_obj = PipelineCreate(
- name,
- description,
- author,
- version=version,
- force=force,
- outdir=outdir,
- template_yaml_path=template_yaml,
- plain=plain,
- )
- create_obj.init_pipeline()
- except UserWarning as e:
- log.error(e)
- sys.exit(1)
-
-
# nf-core lint
@nf_core_cli.command()
@click.option(
@@ -658,6 +603,111 @@ def lint(
sys.exit(1)
+# nf-core pipelines subcommands
+@nf_core_cli.group()
+@click.pass_context
+def pipelines(ctx):
+ """
+ Commands to manage nf-core pipelines.
+ """
+ # ensure that ctx.obj exists and is a dict (in case `cli()` is called
+ # by means other than the `if` block below)
+ ctx.ensure_object(dict)
+
+
+# nf-core pipelines create
+@pipelines.command("create")
+@click.pass_context
+@click.option(
+ "-n",
+ "--name",
+ type=str,
+ help="The name of your new pipeline",
+)
+@click.option("-d", "--description", type=str, help="A short description of your pipeline")
+@click.option("-a", "--author", type=str, help="Name of the main author(s)")
+@click.option("--version", type=str, default="1.0.0dev", help="The initial version number to use")
+@click.option("-f", "--force", is_flag=True, default=False, help="Overwrite output directory if it already exists")
+@click.option("-o", "--outdir", help="Output directory for new pipeline (default: pipeline name)")
+@click.option("-t", "--template-yaml", help="Pass a YAML file to customize the template")
+@click.option(
+ "--organisation",
+ type=str,
+ default="nf-core",
+ help="The name of the GitHub organisation where the pipeline will be hosted (default: nf-core)",
+)
+def create_pipeline(ctx, name, description, author, version, force, outdir, template_yaml, organisation):
+ """
+ Create a new pipeline using the nf-core template.
+
+ Uses the nf-core template to make a skeleton Nextflow pipeline with all required
+ files, boilerplate code and best-practices.
+ \n\n
+ Run without any command line arguments to use an interactive interface.
+ """
+ from nf_core.pipelines.create import PipelineCreateApp
+ from nf_core.pipelines.create.create import PipelineCreate
+
+ if (name and description and author) or (template_yaml):
+ # If all command arguments are used, run without the interactive interface
+ try:
+ create_obj = PipelineCreate(
+ name,
+ description,
+ author,
+ version=version,
+ force=force,
+ outdir=outdir,
+ template_config=template_yaml,
+ organisation=organisation,
+ )
+ create_obj.init_pipeline()
+ except UserWarning as e:
+ log.error(e)
+ sys.exit(1)
+ elif name or description or author or version != "1.0.0dev" or force or outdir or organisation != "nf-core":
+ log.error(
+ "[red]Partial arguments supplied.[/] "
+ "Run without [i]any[/] arguments for an interactive interface, "
+ "or with at least name + description + author to use non-interactively."
+ )
+ sys.exit(1)
+ else:
+ log.info("Launching interactive nf-core pipeline creation tool.")
+ app = PipelineCreateApp()
+ app.run()
+ sys.exit(app.return_code or 0)
+
+
+# nf-core create (deprecated)
+@nf_core_cli.command(hidden=True, deprecated=True)
+@click.option(
+ "-n",
+ "--name",
+ type=str,
+ help="The name of your new pipeline",
+)
+@click.option("-d", "--description", type=str, help="A short description of your pipeline")
+@click.option("-a", "--author", type=str, help="Name of the main author(s)")
+@click.option("--version", type=str, help="The initial version number to use")
+@click.option("-f", "--force", is_flag=True, default=False, help="Overwrite output directory if it already exists")
+@click.option("-o", "--outdir", help="Output directory for new pipeline (default: pipeline name)")
+@click.option("-t", "--template-yaml", help="Pass a YAML file to customize the template")
+@click.option("--plain", is_flag=True, help="Use the standard nf-core template")
+def create(name, description, author, version, force, outdir, template_yaml, plain):
+ """
+ DEPRECATED
+ Create a new pipeline using the nf-core template.
+
+ Uses the nf-core template to make a skeleton Nextflow pipeline with all required
+ files, boilerplate code and best-practices.
+ """
+ log.error(
+ "The `[magenta]nf-core create[/]` command is deprecated. Use `[magenta]nf-core pipelines create[/]` instead."
+ )
+ sys.exit(0)
+
+
# nf-core modules subcommands
@nf_core_cli.group()
@click.option(
diff --git a/nf_core/lint/files_unchanged.py b/nf_core/lint/files_unchanged.py
index 014c2b5f09..fc044b6597 100644
--- a/nf_core/lint/files_unchanged.py
+++ b/nf_core/lint/files_unchanged.py
@@ -8,7 +8,7 @@
import yaml
-import nf_core.create
+import nf_core.pipelines.create.create
log = logging.getLogger(__name__)
@@ -109,7 +109,7 @@ def files_unchanged(self) -> Dict[str, Union[List[str], bool]]:
]
# Only show error messages from pipeline creation
- logging.getLogger("nf_core.create").setLevel(logging.ERROR)
+ logging.getLogger("nf_core.pipelines.create").setLevel(logging.ERROR)
# Generate a new pipeline with nf-core create that we can compare to
tmp_dir = tempfile.mkdtemp()
@@ -119,16 +119,16 @@ def files_unchanged(self) -> Dict[str, Union[List[str], bool]]:
"name": short_name,
"description": self.nf_config["manifest.description"].strip("\"'"),
"author": self.nf_config["manifest.author"].strip("\"'"),
- "prefix": prefix,
+ "org": prefix,
}
template_yaml_path = Path(tmp_dir, "template.yaml")
with open(template_yaml_path, "w") as fh:
yaml.dump(template_yaml, fh, default_flow_style=False)
- test_pipeline_dir = Path(tmp_dir, f"{prefix}-{short_name}")
- create_obj = nf_core.create.PipelineCreate(
- None, None, None, no_git=True, outdir=test_pipeline_dir, template_yaml_path=template_yaml_path
+ test_pipeline_dir = os.path.join(tmp_dir, f"{prefix}-{short_name}")
+ create_obj = nf_core.pipelines.create.create.PipelineCreate(
+ None, None, None, no_git=True, outdir=test_pipeline_dir, template_config=template_yaml_path
)
create_obj.init_pipeline()
diff --git a/nf_core/pipeline-template/.github/CONTRIBUTING.md b/nf_core/pipeline-template/.github/CONTRIBUTING.md
index 6244a6544e..3f541162d3 100644
--- a/nf_core/pipeline-template/.github/CONTRIBUTING.md
+++ b/nf_core/pipeline-template/.github/CONTRIBUTING.md
@@ -9,7 +9,7 @@ Please use the pre-filled template to save time.
However, don't be put off by this template - other more general issues and suggestions are welcome!
Contributions to the code are even more welcome ;)
-{% if branded -%}
+{% if is_nfcore -%}
> [!NOTE]
> If you need help using or modifying {{ name }} then the best place to ask is on the nf-core Slack [#{{ short_name }}](https://nfcore.slack.com/channels/{{ short_name }}) channel ([join our Slack here](https://nf-co.re/join/slack)).
@@ -63,7 +63,7 @@ These tests are run both with the latest available version of `Nextflow` and als
- Fix the bug, and bump version (X.Y.Z+1).
- A PR should be made on `master` from patch to directly this particular bug.
-{% if branded -%}
+{% if is_nfcore -%}
## Getting help
diff --git a/nf_core/pipeline-template/.github/PULL_REQUEST_TEMPLATE.md b/nf_core/pipeline-template/.github/PULL_REQUEST_TEMPLATE.md
index 4f01a97993..9ad257a0b8 100644
--- a/nf_core/pipeline-template/.github/PULL_REQUEST_TEMPLATE.md
+++ b/nf_core/pipeline-template/.github/PULL_REQUEST_TEMPLATE.md
@@ -16,7 +16,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/{{ name }}/t
- [ ] This comment contains a description of changes (with reason).
- [ ] If you've fixed a bug or added code that should be tested, add tests!
- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/{{ name }}/tree/master/.github/CONTRIBUTING.md)
- {%- if branded %}
+ {%- if is_nfcore %}
- [ ] If necessary, also make a PR on the {{ name }} _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository.
{%- endif %}
- [ ] Make sure your code lints (`nf-core lint`).
diff --git a/nf_core/pipeline-template/README.md b/nf_core/pipeline-template/README.md
index 88e0f1719f..e6351b0c6f 100644
--- a/nf_core/pipeline-template/README.md
+++ b/nf_core/pipeline-template/README.md
@@ -1,4 +1,4 @@
-{% if branded -%}
+{% if is_nfcore -%}