diff --git a/.github/snapshots/adaptivecard.nf.test.snap b/.github/snapshots/adaptivecard.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/adaptivecard.nf.test.snap +++ b/.github/snapshots/adaptivecard.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/changelog.nf.test.snap b/.github/snapshots/changelog.nf.test.snap index aa731135a1..dce153ef5e 100644 --- a/.github/snapshots/changelog.nf.test.snap +++ b/.github/snapshots/changelog.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/ci.nf.test.snap b/.github/snapshots/ci.nf.test.snap index 79ff07945a..f327e5b10c 100644 --- a/.github/snapshots/ci.nf.test.snap +++ b/.github/snapshots/ci.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/citations.nf.test.snap b/.github/snapshots/citations.nf.test.snap index a135c5586e..860baca828 100644 --- a/.github/snapshots/citations.nf.test.snap +++ b/.github/snapshots/citations.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/code_linters.nf.test.snap b/.github/snapshots/code_linters.nf.test.snap index a135c5586e..860baca828 100644 --- a/.github/snapshots/code_linters.nf.test.snap +++ b/.github/snapshots/code_linters.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/codespaces.nf.test.snap b/.github/snapshots/codespaces.nf.test.snap index a135c5586e..860baca828 100644 --- a/.github/snapshots/codespaces.nf.test.snap +++ b/.github/snapshots/codespaces.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/default.nf.test.snap b/.github/snapshots/default.nf.test.snap index 0af1896079..522cb600b6 100644 --- a/.github/snapshots/default.nf.test.snap +++ b/.github/snapshots/default.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/documentation.nf.test.snap b/.github/snapshots/documentation.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/documentation.nf.test.snap +++ b/.github/snapshots/documentation.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/email.nf.test.snap b/.github/snapshots/email.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/email.nf.test.snap +++ b/.github/snapshots/email.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/github_badges.nf.test.snap b/.github/snapshots/github_badges.nf.test.snap index a0da86f7bf..44dd973359 100644 --- a/.github/snapshots/github_badges.nf.test.snap +++ b/.github/snapshots/github_badges.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/gitpod.nf.test.snap b/.github/snapshots/gitpod.nf.test.snap index a135c5586e..860baca828 100644 --- a/.github/snapshots/gitpod.nf.test.snap +++ b/.github/snapshots/gitpod.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/gpu.nf.test.snap b/.github/snapshots/gpu.nf.test.snap index 0d51c52abf..8ab9a90bf6 100644 --- a/.github/snapshots/gpu.nf.test.snap +++ b/.github/snapshots/gpu.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/igenomes.nf.test.snap b/.github/snapshots/igenomes.nf.test.snap index 8d57911ba9..7d3d0951f8 100644 --- a/.github/snapshots/igenomes.nf.test.snap +++ b/.github/snapshots/igenomes.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/license.nf.test.snap b/.github/snapshots/license.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/license.nf.test.snap +++ b/.github/snapshots/license.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/nf_core_configs.nf.test.snap b/.github/snapshots/nf_core_configs.nf.test.snap index a135c5586e..860baca828 100644 --- a/.github/snapshots/nf_core_configs.nf.test.snap +++ b/.github/snapshots/nf_core_configs.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/nf_schema.nf.test.snap b/.github/snapshots/nf_schema.nf.test.snap index 6ccaacba0b..25eb8c5dba 100644 --- a/.github/snapshots/nf_schema.nf.test.snap +++ b/.github/snapshots/nf_schema.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/rocrate.nf.test.snap b/.github/snapshots/rocrate.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/rocrate.nf.test.snap +++ b/.github/snapshots/rocrate.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/seqera_platform.nf.test.snap b/.github/snapshots/seqera_platform.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/seqera_platform.nf.test.snap +++ b/.github/snapshots/seqera_platform.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/slackreport.nf.test.snap b/.github/snapshots/slackreport.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/slackreport.nf.test.snap +++ b/.github/snapshots/slackreport.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/.github/snapshots/vscode.nf.test.snap b/.github/snapshots/vscode.nf.test.snap index c8ebafde24..e45193040a 100644 --- a/.github/snapshots/vscode.nf.test.snap +++ b/.github/snapshots/vscode.nf.test.snap @@ -47,6 +47,7 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/fastqc-status-check-heatmap.pdf", "multiqc/multiqc_plots/pdf/fastqc_overrepresented_sequences_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_n_content_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_per_base_sequence_quality_plot.pdf", @@ -59,6 +60,7 @@ "multiqc/multiqc_plots/pdf/fastqc_sequence_length_distribution_plot.pdf", "multiqc/multiqc_plots/pdf/fastqc_top_overrepresented_sequences_table.pdf", "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/fastqc-status-check-heatmap.png", "multiqc/multiqc_plots/png/fastqc_overrepresented_sequences_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_n_content_plot.png", "multiqc/multiqc_plots/png/fastqc_per_base_sequence_quality_plot.png", @@ -71,6 +73,7 @@ "multiqc/multiqc_plots/png/fastqc_sequence_length_distribution_plot.png", "multiqc/multiqc_plots/png/fastqc_top_overrepresented_sequences_table.png", "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/fastqc-status-check-heatmap.svg", "multiqc/multiqc_plots/svg/fastqc_overrepresented_sequences_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_n_content_plot.svg", "multiqc/multiqc_plots/svg/fastqc_per_base_sequence_quality_plot.svg", diff --git a/CHANGELOG.md b/CHANGELOG.md index 66a77dd299..bf888a581e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Update mcr.microsoft.com/devcontainers/miniconda Docker digest to 2be0f5a ([#3946](https://github.com/nf-core/tools/pull/3946)) - Fix quote handling in meta.yml ([#3948](https://github.com/nf-core/tools/pull/3948)) - Fix docker errors in test ([#3924](https://github.com/nf-core/tools/pull/3924)) +- Add new command to generate pipeline container config files ([#3955](https://github.com/nf-core/tools/pull/3955)) - Update actions/checkout digest to 8e8c483 ([#3956](https://github.com/nf-core/tools/pull/3956)) - Update GitHub Actions ([#3957](https://github.com/nf-core/tools/pull/3957)) - Update astral-sh/setup-uv digest to ed21f2f ([#3959](https://github.com/nf-core/tools/pull/3959)) diff --git a/nf_core/components/components_utils.py b/nf_core/components/components_utils.py index 7423de7f2b..5ec89d1c40 100644 --- a/nf_core/components/components_utils.py +++ b/nf_core/components/components_utils.py @@ -9,6 +9,7 @@ import nf_core.utils from nf_core.modules.modules_repo import ModulesRepo +from nf_core.pipelines.containers_utils import ContainerConfigs log = logging.getLogger(__name__) @@ -279,3 +280,10 @@ def _iterate_input_output(type) -> DictWithStrAndTuple: # If the tool name was not found in the response log.warning(f"Could not find an EDAM ontology term for '{tool_name}'") return None + + +def try_generate_container_configs(directory: Path, path: Path): + try: + ContainerConfigs(directory, str(path)).generate_container_configs() + except UserWarning as e: + log.warning(f"Could not regenerate container configuration files: {e}") diff --git a/nf_core/components/install.py b/nf_core/components/install.py index 61e088ef16..c5392c364a 100644 --- a/nf_core/components/install.py +++ b/nf_core/components/install.py @@ -16,6 +16,7 @@ from nf_core.components.components_utils import ( get_components_to_install, prompt_component_version_sha, + try_generate_container_configs, ) from nf_core.components.constants import ( NF_CORE_MODULES_NAME, @@ -157,7 +158,7 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool if not self.install_component_files(component, version, self.modules_repo, install_folder): return False - # Update module.json with newly installed subworkflow + # Update module.json with newly installed component modules_json.load() modules_json.update( self.component_type, self.modules_repo, component, version, self.installed_by, install_track @@ -167,6 +168,10 @@ def install(self, component: str | dict[str, str], silent: bool = False) -> bool # Install included modules and subworkflows self.install_included_components(component_dir) + # Regenerate container configuration files for the pipeline when modules are installed + if self.component_type == "modules": + try_generate_container_configs(self.directory, self.modules_repo.repo_path) + if not silent: modules_json.load() modules_json.dump(run_prettier=True) diff --git a/nf_core/components/remove.py b/nf_core/components/remove.py index afe12c88a9..ef0668ddd8 100644 --- a/nf_core/components/remove.py +++ b/nf_core/components/remove.py @@ -8,6 +8,7 @@ import nf_core.utils from nf_core.components.components_command import ComponentCommand +from nf_core.components.components_utils import try_generate_container_configs from nf_core.modules.modules_json import ModulesJson from .install import ComponentInstall @@ -172,6 +173,10 @@ def remove(self, component, repo_url=None, repo_path=None, removed_by=None, remo # remember removed dependencies if dependency_removed: removed_components.append(component_name.replace("/", "_")) + # Regenerate container configuration files for the pipeline when modules are removed + if self.component_type == "modules": + try_generate_container_configs(self.directory, repo_path) + # print removed dependencies if removed_components: log.info(f"Removed files for '{component}' and its dependencies '{', '.join(removed_components)}'.") diff --git a/nf_core/components/update.py b/nf_core/components/update.py index fcdb005e9f..af97625730 100644 --- a/nf_core/components/update.py +++ b/nf_core/components/update.py @@ -13,6 +13,7 @@ from nf_core.components.components_utils import ( get_components_to_install, prompt_component_version_sha, + try_generate_container_configs, ) from nf_core.components.install import ComponentInstall from nf_core.components.remove import ComponentRemove @@ -298,6 +299,10 @@ def update(self, component=None, silent=False, updated=None, check_diff_exist=Tr # Update modules.json with newly installed component self.modules_json.update(self.component_type, modules_repo, component, version, installed_by=None) updated.append(component) + + # Regenerate container configuration files for the pipeline when modules are updated + if self.component_type == "modules": + try_generate_container_configs(self.directory, modules_repo.repo_path) recursive_update = True modules_to_update, subworkflows_to_update = self.get_components_to_update(component) if not silent and len(modules_to_update + subworkflows_to_update) > 0: diff --git a/nf_core/pipeline-template/modules.json b/nf_core/pipeline-template/modules.json index caec6d9d75..a5923bc563 100644 --- a/nf_core/pipeline-template/modules.json +++ b/nf_core/pipeline-template/modules.json @@ -8,12 +8,12 @@ {%- if fastqc %} "fastqc": { "branch": "master", - "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", + "git_sha": "5bdb098216aaf5df9c3b6343e6204cd932503c16", "installed_by": ["modules"] }{% endif %}{%- if multiqc %}{% if fastqc %},{% endif %} "multiqc": { "branch": "master", - "git_sha": "af27af1be706e6a2bb8fe454175b0cdf77f47b49", + "git_sha": "5bdb098216aaf5df9c3b6343e6204cd932503c16", "installed_by": ["modules"] } {%- endif %} diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf b/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf index 23e16634c3..4b3041dc53 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/main.nf @@ -11,9 +11,9 @@ process FASTQC { tuple val(meta), path(reads) output: - tuple val(meta), path("*.html"), emit: html - tuple val(meta), path("*.zip") , emit: zip - path "versions.yml" , emit: versions + tuple val(meta) , path("*.html") , emit: html + tuple val(meta) , path("*.zip") , emit: zip + tuple val("${task.process}"), val('fastqc'), eval('fastqc --version | sed "/FastQC v/!d; s/.*v//"'), emit: versions_fastqc, topic: versions when: task.ext.when == null || task.ext.when @@ -43,11 +43,6 @@ process FASTQC { --threads ${task.cpus} \\ --memory ${fastqc_memory} \\ ${renamed_files} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ stub: @@ -55,10 +50,5 @@ process FASTQC { """ touch ${prefix}.html touch ${prefix}.zip - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ } diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml b/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml index c8d9d025ac..49164c88fb 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/meta.yml @@ -53,13 +53,28 @@ output: description: FastQC report archive pattern: "*_{fastqc.zip}" ontologies: [] + versions_fastqc: + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool authors: - "@drpatelh" - "@grst" @@ -70,3 +85,27 @@ maintainers: - "@grst" - "@ewels" - "@FelixKrueger" +containers: + conda: + linux_amd64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-af7a5314d5015c29_1/condalock + linux_arm64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-df99cb252670875a_2/condalock + docker: + linux_amd64: + build_id: bd-af7a5314d5015c29_1 + name: community.wave.seqera.io/library/fastqc:0.12.1--af7a5314d5015c29 + scanId: sc-a618548acbee5a8a_30 + linux_arm64: + build_id: bd-df99cb252670875a_2 + name: community.wave.seqera.io/library/fastqc:0.12.1--df99cb252670875a + scanId: sc-b5913ed5d42b22d2_18 + singularity: + linux_amd64: + build_id: bd-104d26ddd9519960_1 + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--104d26ddd9519960 + https: https://community.wave.seqera.io/v2/library/fastqc/blobs/sha256:e0c976cb2eca5fee72618a581537a4f8ea42fcae24c9b201e2e0f764fd28648a + linux_arm64: + build_id: bd-d56b505a93aef38a_1 + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--d56b505a93aef38a + https: https://community.wave.seqera.io/v2/library/fastqc/blobs/sha256:fd39534bf298698cbe3ee4d4a6f1e73330ec4bca44c38dd9a4d06cb5ea838017 diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test index e9d79a074e..66c44da9bf 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test @@ -30,7 +30,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -58,7 +58,7 @@ nextflow_process { { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -82,7 +82,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -106,7 +106,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -142,7 +142,7 @@ nextflow_process { { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -166,7 +166,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } diff --git a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap index d5db3092fb..c8ee120f56 100644 --- a/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap +++ b/nf_core/pipeline-template/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -1,15 +1,21 @@ { "sarscov2 custom_prefix": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:16.374038" + "timestamp": "2025-10-28T16:39:14.518503" }, "sarscov2 single-end [fastq] - stub": { "content": [ @@ -33,7 +39,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -44,8 +54,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -59,10 +73,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:24.993809" + "timestamp": "2025-10-28T16:39:19.309008" }, "sarscov2 custom_prefix - stub": { "content": [ @@ -86,7 +100,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -97,8 +115,12 @@ "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -112,58 +134,82 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:10.93942" + "timestamp": "2025-10-28T16:39:44.94888" }, "sarscov2 interleaved [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:42.355718" + "timestamp": "2025-10-28T16:38:45.168496" }, "sarscov2 paired-end [bam]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:53.276274" + "timestamp": "2025-10-28T16:38:53.268919" }, "sarscov2 multiple [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:05.527626" + "timestamp": "2025-10-28T16:39:05.050305" }, "sarscov2 paired-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:31.188871" + "timestamp": "2025-10-28T16:38:37.2373" }, "sarscov2 paired-end [fastq] - stub": { "content": [ @@ -187,7 +233,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -198,8 +248,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -213,10 +267,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:34.273566" + "timestamp": "2025-10-28T16:39:24.450398" }, "sarscov2 multiple [fastq] - stub": { "content": [ @@ -240,7 +294,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -251,8 +309,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -266,22 +328,28 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:02.304411" + "timestamp": "2025-10-28T16:39:39.758762" }, "sarscov2 single-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:19.095607" + "timestamp": "2025-10-28T16:38:29.555068" }, "sarscov2 interleaved [fastq] - stub": { "content": [ @@ -305,7 +373,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -316,8 +388,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -331,10 +407,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:44.640184" + "timestamp": "2025-10-28T16:39:29.193136" }, "sarscov2 paired-end [bam] - stub": { "content": [ @@ -358,7 +434,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -369,8 +449,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -384,9 +468,9 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:53.550742" + "timestamp": "2025-10-28T16:39:34.144919" } } \ No newline at end of file diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml b/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml index d02016a009..009874d4c0 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.32 + - bioconda::multiqc=1.33 diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf b/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf index c1158fb08c..3b0e975be6 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/main.nf @@ -3,11 +3,11 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8c/8c6c120d559d7ee04c7442b61ad7cf5a9e8970be5feefb37d68eeaa60c1034eb/data' : - 'community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf' }" + 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34e733a9ae16a27e80fe00f863ea1479c96416017f24a907996126283e7ecd4d/data' : + 'community.wave.seqera.io/library/multiqc:1.33--ee7739d47738383b' }" input: - path multiqc_files, stageAs: "?/*" + path multiqc_files, stageAs: "?/*" path(multiqc_config) path(extra_multiqc_config) path(multiqc_logo) @@ -15,10 +15,11 @@ process MULTIQC { path(sample_names) output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions + path "*.html" , emit: report + path "*_data" , emit: data + path "*_plots" , optional:true, emit: plots + tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions + // MultiQC should not push its versions to the `versions` topic. Its input depends on the versions topic to be resolved thus outputting to the topic will let the pipeline hang forever when: task.ext.when == null || task.ext.when @@ -26,38 +27,29 @@ process MULTIQC { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' - def config = multiqc_config ? "--config $multiqc_config" : '' - def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def config = multiqc_config ? "--config ${multiqc_config}" : '' + def extra_config = extra_multiqc_config ? "--config ${extra_multiqc_config}" : '' def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' def replace = replace_names ? "--replace-names ${replace_names}" : '' def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ - $args \\ - $config \\ - $prefix \\ - $extra_config \\ - $logo \\ - $replace \\ - $samples \\ + ${args} \\ + ${config} \\ + ${prefix} \\ + ${extra_config} \\ + ${logo} \\ + ${replace} \\ + ${samples} \\ . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ stub: """ mkdir multiqc_data + touch multiqc_data/.stub mkdir multiqc_plots touch multiqc_report.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ } diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml b/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml index ce30eb732b..f790cab0ff 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/meta.yml @@ -57,10 +57,10 @@ input: - edam: http://edamontology.org/format_3475 # TSV output: report: - - "*multiqc_report.html": + - "*.html": type: file description: MultiQC report file - pattern: "multiqc_report.html" + pattern: ".html" ontologies: [] data: - "*_data": @@ -74,12 +74,15 @@ output: pattern: "*_data" ontologies: [] versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - multiqc: + type: string + description: The tool name + - multiqc --version | sed "s/.* //g": + type: eval + description: The expression to obtain the version of the tool authors: - "@abhi18av" - "@bunop" @@ -90,3 +93,27 @@ maintainers: - "@bunop" - "@drpatelh" - "@jfy133" +containers: + conda: + linux_amd64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-d58f60e4deb769bf_1/condalock + linux_arm64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-193776baee4194db_1/condalock + docker: + linux_amd64: + build_id: bd-d58f60e4deb769bf_1 + name: community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf + scanId: sc-d76ac07493e940b4_6 + linux_arm64: + build_id: bd-193776baee4194db_1 + name: community.wave.seqera.io/library/multiqc:1.32--193776baee4194db + scanId: sc-86caded0bff8246e_3 + singularity: + linux_amd64: + build_id: bd-e649ffa094d1ef4a_1 + name: oras://community.wave.seqera.io/library/multiqc:1.32--e649ffa094d1ef4a + https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:8c6c120d559d7ee04c7442b61ad7cf5a9e8970be5feefb37d68eeaa60c1034eb + linux_arm64: + build_id: bd-aee0064f5570ef22_1 + name: oras://community.wave.seqera.io/library/multiqc:1.32--aee0064f5570ef22 + https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:f02c59ebf6e9a00aa954ee8188a4ecc5c743e18f40b9215a242f67606a00f9cf diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/custom_prefix.config b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/custom_prefix.config new file mode 100644 index 0000000000..b30b1358b0 --- /dev/null +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/custom_prefix.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = "custom_prefix" + } +} diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test index 33316a7ddb..d1ae8b06c1 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test @@ -30,7 +30,33 @@ nextflow_process { { assert process.success }, { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_single") } + { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } + ) + } + + } + + test("sarscov2 single-end [fastqc] - custom prefix") { + config "./custom_prefix.config" + + when { + process { + """ + input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = [] + input[2] = [] + input[3] = [] + input[4] = [] + input[5] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/custom_prefix.html" }, + { assert process.out.data[0] ==~ ".*/custom_prefix_data" } ) } @@ -56,7 +82,7 @@ nextflow_process { { assert process.success }, { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_config") } + { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } ) } } @@ -84,7 +110,7 @@ nextflow_process { { assert snapshot(process.out.report.collect { file(it).getName() } + process.out.data.collect { file(it).getName() } + process.out.plots.collect { file(it).getName() } + - process.out.versions ).match("multiqc_stub") } + process.out.findAll { key, val -> key.startsWith("versions")} ).match() } ) } diff --git a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap index a88bafd679..d72d35b747 100644 --- a/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/nf_core/pipeline-template/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -1,41 +1,61 @@ { - "multiqc_versions_single": { + "sarscov2 single-end [fastqc]": { "content": [ - [ - "versions.yml:md5,737bb2c7cad54ffc2ec020791dc48b8f" - ] + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], "meta": { "nf-test": "0.9.3", - "nextflow": "24.10.4" + "nextflow": "25.10.2" }, - "timestamp": "2025-10-27T13:33:24.356715" + "timestamp": "2025-12-09T10:10:43.020315838" }, - "multiqc_stub": { + "sarscov2 single-end [fastqc] - stub": { "content": [ [ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,737bb2c7cad54ffc2ec020791dc48b8f" + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ] ], "meta": { "nf-test": "0.9.3", - "nextflow": "24.10.4" + "nextflow": "25.10.2" }, - "timestamp": "2025-10-27T13:34:11.103619" + "timestamp": "2025-12-09T10:11:14.131950776" }, - "multiqc_versions_config": { + "sarscov2 single-end [fastqc] [config]": { "content": [ - [ - "versions.yml:md5,737bb2c7cad54ffc2ec020791dc48b8f" - ] + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], "meta": { "nf-test": "0.9.3", - "nextflow": "24.10.4" + "nextflow": "25.10.2" }, - "timestamp": "2025-10-27T13:34:04.615233" + "timestamp": "2025-12-09T10:11:07.15692209" } } \ No newline at end of file diff --git a/nf_core/pipeline-template/workflows/pipeline.nf b/nf_core/pipeline-template/workflows/pipeline.nf index 4e91263d01..d293842657 100644 --- a/nf_core/pipeline-template/workflows/pipeline.nf +++ b/nf_core/pipeline-template/workflows/pipeline.nf @@ -43,14 +43,13 @@ workflow {{ short_name|upper }} { FASTQC ( ch_samplesheet ) - {% if multiqc %}ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}){% endif %} - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + {% if multiqc %}ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it -> it[1]}){% endif %} {%- endif %} // // Collate and save software versions // - def topic_versions = Channel.topic("versions") + def topic_versions = channel.topic("versions") .distinct() .branch { entry -> versions_file: entry instanceof Path diff --git a/nf_core/pipelines/containers_utils.py b/nf_core/pipelines/containers_utils.py new file mode 100644 index 0000000000..0a9722cc78 --- /dev/null +++ b/nf_core/pipelines/containers_utils.py @@ -0,0 +1,107 @@ +import json +import logging +from pathlib import Path + +import yaml + +from nf_core.utils import NF_INSPECT_MIN_NF_VERSION, check_nextflow_version, pretty_nf_version, run_cmd + +log = logging.getLogger(__name__) + + +class ContainerConfigs: + """Generates the container configuration files for a pipeline. + + Args: + workflow_directory (str | Path): The directory containing the workflow files. + org (str): Organisation path. + """ + + def __init__( + self, + workflow_directory: Path = Path("."), + org: str = "nf-core", + ): + self.workflow_directory = workflow_directory + self.org: str = org + + def check_nextflow_version_sufficient(self) -> None: + """Check if the Nextflow version is sufficient to run `nextflow inspect`.""" + if not check_nextflow_version(NF_INSPECT_MIN_NF_VERSION): + raise UserWarning( + f"To use Seqera containers Nextflow version >= {pretty_nf_version(NF_INSPECT_MIN_NF_VERSION)} is required.\n" + f"Please update your Nextflow version with [magenta]'nextflow self-update'[/]\n" + ) + + def generate_container_configs(self) -> None: + """ + Generate the container configuration files for a pipeline. + Requires Nextflow >= 25.04.4 + """ + self.check_nextflow_version_sufficient() + log.debug("Generating container config file with [magenta bold]nextflow inspect[/].") + try: + # Run nextflow inspect + executable = "nextflow" + cmd_params = f"inspect -format json {self.workflow_directory}" + cmd_out = run_cmd(executable, cmd_params) + if cmd_out is None: + raise UserWarning("Failed to run `nextflow inspect`. Please check your Nextflow installation.") + + out, _ = cmd_out + out_json = json.loads(out) + + except RuntimeError as e: + log.error("Running 'nextflow inspect' failed with the following error:") + raise UserWarning(e) + + module_names = [p.get("name") for p in out_json["processes"] if p.get("name")] + + platforms: dict[str, list[str]] = { + "docker_amd64": ["docker", "linux_amd64", "name"], + "docker_arm64": ["docker", "linux_arm64", "name"], + "singularity_oras_amd64": ["singularity", "linux_amd64", "name"], + "singularity_oras_arm64": ["singularity", "linux_arm64", "name"], + "singularity_https_amd64": ["singularity", "linux_amd64", "https"], + "singularity_https_arm64": ["singularity", "linux_arm64", "https"], + "conda_amd64_lockfile": ["conda", "linux_amd64", "lock_file"], + "conda_arm64_lockfile": ["conda", "linux_arm64", "lock_file"], + } + + # Build containers dict from module meta.yml files + # Pre-initialize all platforms to avoid repeated existence checks + containers: dict[str, dict[str, str]] = {platform: {} for platform in platforms} + for m_name in module_names: + # Parse module path once with maxsplit to handle edge cases + parts = m_name.split("_", 1) + if len(parts) == 2: + module_path = Path(parts[0].lower()) / parts[1].lower() + else: + module_path = Path(m_name.lower()) + + try: + meta_path = self.workflow_directory / "modules" / self.org / module_path / "meta.yml" + with open(meta_path) as fh: + meta = yaml.safe_load(fh) + except FileNotFoundError: + log.warning(f"Could not find meta.yml for {m_name}") + continue + + # Extract containers for all platforms + for platform_name, (runtime, arch, protocol) in platforms.items(): + try: + containers[platform_name][m_name] = meta["containers"][runtime][arch][protocol] + except (KeyError, TypeError): + log.warning(f"Could not find {platform_name} container for {m_name}") + continue + + # write config files + for platform, module_containers in containers.items(): + if not module_containers: + continue + lines = [ + f"process {{ withName: '{module_name}' {{ container = '{container}' }} }}\n" + for module_name, container in module_containers.items() + ] + config_path = self.workflow_directory / "conf" / f"containers_{platform}.config" + config_path.write_text("".join(lines)) diff --git a/tests/pipelines/test_container_configs.py b/tests/pipelines/test_container_configs.py new file mode 100644 index 0000000000..54d70def6f --- /dev/null +++ b/tests/pipelines/test_container_configs.py @@ -0,0 +1,81 @@ +"""Tests for the ContainerConfigs helper used by pipelines.""" + +from unittest.mock import patch + +import pytest +import ruamel.yaml + +from nf_core.modules.install import ModuleInstall +from nf_core.pipelines.containers_utils import ContainerConfigs +from nf_core.utils import NF_INSPECT_MIN_NF_VERSION, pretty_nf_version + +from ..test_pipelines import TestPipelines + +yaml = ruamel.yaml.YAML() + + +class TestContainerConfigs(TestPipelines): + """Tests for ContainerConfigs using a test pipeline.""" + + def setUp(self) -> None: + super().setUp() + self.container_configs = ContainerConfigs(self.pipeline_dir, "nf-core") + + def test_check_nextflow_version_sufficient_ok(self) -> None: + """check_nextflow_version should return silently when version is sufficient.""" + with patch( + "nf_core.pipelines.containers_utils.check_nextflow_version", + return_value=True, + ) as mocked_check: + self.container_configs.check_nextflow_version_sufficient() + + mocked_check.assert_called_once_with(NF_INSPECT_MIN_NF_VERSION) + + def test_check_nextflow_version_sufficient_too_low(self) -> None: + """check_nextflow_version should raise UserWarning when version is too low.""" + with patch( + "nf_core.pipelines.containers_utils.check_nextflow_version", + return_value=False, + ): + with pytest.raises(UserWarning) as excinfo: + self.container_configs.check_nextflow_version_sufficient() + + # Error message should mention the minimal required version + assert pretty_nf_version(NF_INSPECT_MIN_NF_VERSION) in str(excinfo.value) + + def test_generate_all_container_configs(self) -> None: + """Run generate_all_container_configs in a pipeline.""" + # Install fastqc and multiqc + mods_install = ModuleInstall( + self.pipeline_dir, + prompt=False, + force=False, + ) + mods_install.install("fastqc") + mods_install.install("multiqc") + + self.container_configs.generate_container_configs() + + conf_dir = self.pipeline_dir / "conf" + # Expected platforms and one expected container + platforms: dict[str, list[str]] = { + "docker_amd64": ["docker", "linux_amd64", "name"], + "docker_arm64": ["docker", "linux_arm64", "name"], + "singularity_oras_amd64": ["singularity", "linux_amd64", "name"], + "singularity_oras_arm64": ["singularity", "linux_arm64", "name"], + "singularity_https_amd64": ["singularity", "linux_amd64", "https"], + "singularity_https_arm64": ["singularity", "linux_arm64", "https"], + "conda_amd64_lockfile": ["conda", "linux_amd64", "lock_file"], + "conda_arm64_lockfile": ["conda", "linux_arm64", "lock_file"], + } + + with open(self.pipeline_dir / "modules" / "nf-core" / "fastqc" / "meta.yml") as fh: + fastqc_meta_yml = yaml.load(fh) + + for p_name, (runtime, arch, protocol) in platforms.items(): + cfg_path = conf_dir / f"containers_{p_name}.config" + assert cfg_path.exists() + with cfg_path.open("r") as fh: + content = fh.readlines() + value = fastqc_meta_yml["containers"][runtime][arch][protocol] + assert f"process {{ withName: 'FASTQC' {{ container = '{value}' }} }}\n" in content